1 /** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef LIBPANDAFILE_FILE_READER_H 17 #define LIBPANDAFILE_FILE_READER_H 18 19 #include <type_traits> 20 #include "annotation_data_accessor.h" 21 #include "bytecode_instruction.h" 22 #include "class_data_accessor.h" 23 #include "code_data_accessor.h" 24 #include "debug_data_accessor.h" 25 #include "field_data_accessor.h" 26 #include "file_item_container.h" 27 #include "libpandafile/helpers.h" 28 #include "literal_data_accessor.h" 29 #include "method_data_accessor.h" 30 #include "method_handle_data_accessor.h" 31 #include "os/file.h" 32 #include "param_annotations_data_accessor.h" 33 #include "proto_data_accessor.h" 34 #include "utils/pandargs.h" 35 #include "utils/span.h" 36 #include "utils/type_helpers.h" 37 #include "utils/leb128.h" 38 #if !PANDA_TARGET_WINDOWS 39 #include "securec.h" 40 #endif 41 42 #include <cstdint> 43 #include <cerrno> 44 45 #include <limits> 46 #include <vector> 47 48 namespace panda::panda_file { 49 50 class FileReader { 51 public: 52 // default methods FileReader(std::unique_ptr<const File> &&file)53 explicit FileReader(std::unique_ptr<const File> &&file) : file_(std::move(file)) {} 54 virtual ~FileReader() = default; 55 56 bool ReadContainer(); 57 GetContainerPtr()58 ItemContainer *GetContainerPtr() 59 { 60 return &container_; 61 } 62 63 void ComputeLayoutAndUpdateIndices(); 64 65 NO_COPY_SEMANTIC(FileReader); 66 NO_MOVE_SEMANTIC(FileReader); 67 68 private: 69 bool ReadLiteralArrayItems(); 70 bool ReadIndexHeaders(); 71 bool ReadClasses(); 72 73 bool CreateLiteralArrayItem(const LiteralDataAccessor::LiteralValue &lit_value, const LiteralTag &tag, 74 File::EntityId array_id); 75 AnnotationItem *CreateAnnotationItem(File::EntityId ann_id); 76 MethodItem *CreateMethodItem(ClassItem *cls, File::EntityId method_id); 77 ForeignMethodItem *CreateForeignMethodItem(BaseClassItem *fcls, File::EntityId method_id); 78 FieldItem *CreateFieldItem(ClassItem *cls, File::EntityId field_id); 79 ForeignFieldItem *CreateForeignFieldItem(BaseClassItem *fcls, File::EntityId field_id); 80 ClassItem *CreateClassItem(File::EntityId class_id); 81 ForeignClassItem *CreateForeignClassItem(File::EntityId class_id); 82 MethodHandleItem *CreateMethodHandleItem(File::EntityId mh_id); 83 TypeItem *CreateParamTypeItem(ProtoDataAccessor *proto_acc, size_t param_num, size_t reference_num); 84 TypeItem *GetReturnTypeItem(Type type, size_t &reference_num); 85 std::vector<MethodParamItem> CreateMethodParamItems(ProtoDataAccessor *proto_acc, MethodDataAccessor *method_acc, 86 size_t reference_num); 87 DebugInfoItem *CreateDebugInfoItem(File::EntityId debug_info_id); 88 void EnumerateBlocks(MethodDataAccessor method_acc, MethodItem *method_item); 89 void UpdateDebugInfoDependecies(File::EntityId debug_info_id); 90 void UpdateDebugInfo(DebugInfoItem *debug_info_item, File::EntityId debug_info_id); 91 void CreateSuperClassItem(ClassDataAccessor& class_acc, ClassItem* class_item, const std::string& class_name); 92 void AddIndexDependencyInstFlag(CodeItem *code_item, MethodItem *method_item, 93 const std::unordered_map<File::EntityId, File::EntityId> &reverse_done); 94 void UpdateIdInstFlag(CodeItem *code_item, MethodItem *method_item, 95 const std::unordered_map<File::EntityId, File::EntityId> &reverse_done); 96 97 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true> SetIntegerFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item)98 void SetIntegerFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item) 99 { 100 auto value = field_acc->GetValue<T>(); 101 if (!value) { 102 return; 103 } 104 105 // NOLINTNEXTLINE(readability-braces-around-statements) 106 if constexpr (is_same_v<T, int64_t> || is_same_v<T, uint64_t>) { 107 auto *value_item = container_.GetOrCreateLongValueItem(value.value()); 108 field_item->SetValue(value_item); 109 // NOLINTNEXTLINE(readability-misleading-indentation) 110 } else { 111 auto *value_item = container_.GetOrCreateIntegerValueItem(value.value()); 112 field_item->SetValue(value_item); 113 } 114 } 115 116 template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> SetFloatFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item)117 void SetFloatFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item) 118 { 119 auto value = field_acc->GetValue<T>(); 120 if (!value) { 121 return; 122 } 123 124 // NOLINTNEXTLINE(readability-braces-around-statements) 125 if constexpr (is_same_v<T, double>) { 126 auto *value_item = container_.GetOrCreateDoubleValueItem(value.value()); 127 field_item->SetValue(value_item); 128 // NOLINTNEXTLINE(readability-misleading-indentation) 129 } else { 130 auto *value_item = container_.GetOrCreateFloatValueItem(value.value()); 131 field_item->SetValue(value_item); 132 } 133 } 134 SetStringFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item)135 void SetStringFieldValue(FieldDataAccessor *field_acc, FieldItem *field_item) 136 { 137 auto value = field_acc->GetValue<uint32_t>(); 138 if (value) { 139 panda_file::File::EntityId string_id(value.value()); 140 auto data = file_->GetStringData(string_id); 141 std::string string_data(reinterpret_cast<const char *>(data.data)); 142 auto *string_item = container_.GetOrCreateStringItem(string_data); 143 auto *value_item = container_.GetOrCreateIdValueItem(string_item); 144 field_item->SetValue(value_item); 145 } 146 } 147 148 // Creates foreign or non-foreign method item CreateGenericMethodItem(BaseClassItem *class_item, File::EntityId method_id)149 inline BaseItem *CreateGenericMethodItem(BaseClassItem *class_item, File::EntityId method_id) 150 { 151 if (file_->IsExternal(method_id)) { 152 return CreateForeignMethodItem(class_item, method_id); 153 } 154 return CreateMethodItem(static_cast<ClassItem *>(class_item), method_id); 155 } 156 157 // Creates foreign or non-foreign field item CreateGenericFieldItem(BaseClassItem *class_item, File::EntityId field_id)158 inline BaseItem *CreateGenericFieldItem(BaseClassItem *class_item, File::EntityId field_id) 159 { 160 if (file_->IsExternal(field_id)) { 161 return CreateForeignFieldItem(class_item, field_id); 162 } 163 return CreateFieldItem(static_cast<ClassItem *>(class_item), field_id); 164 } 165 166 // Creates foreign or non-foreign class item CreateGenericClassItem(File::EntityId class_id)167 inline BaseClassItem *CreateGenericClassItem(File::EntityId class_id) 168 { 169 if (file_->IsExternal(class_id)) { 170 return CreateForeignClassItem(class_id); 171 } 172 return CreateClassItem(class_id); 173 } 174 175 void UpdateCodeAndDebugInfoDependencies(const std::map<BaseItem *, File::EntityId> &reverse_done); 176 177 std::unique_ptr<const File> file_; 178 ItemContainer container_; 179 std::map<File::EntityId, BaseItem *> items_done_; 180 }; 181 182 } // namespace panda::panda_file 183 184 #endif // LIBPANDAFILE_FILE_READER_H 185