1 /** 2 * Copyright (c) 2021-2025 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 #ifndef LIBPANDAFILE_FILE_READER_H_ 16 #define LIBPANDAFILE_FILE_READER_H_ 17 18 #include <type_traits> 19 #include "annotation_data_accessor.h" 20 #include "bytecode_instruction.h" 21 #include "class_data_accessor.h" 22 #include "code_data_accessor.h" 23 #include "debug_data_accessor.h" 24 #include "field_data_accessor.h" 25 #include "file_item_container.h" 26 #include "libpandafile/helpers.h" 27 #include "literal_data_accessor.h" 28 #include "method_data_accessor.h" 29 #include "method_handle_data_accessor.h" 30 #include "os/file.h" 31 #include "param_annotations_data_accessor.h" 32 #include "proto_data_accessor.h" 33 #include "utils/pandargs.h" 34 #include "utils/span.h" 35 #include "utils/type_helpers.h" 36 #include "utils/leb128.h" 37 #if !PANDA_TARGET_WINDOWS 38 #include "securec.h" 39 #endif 40 41 #include <cstdint> 42 #include <cerrno> 43 44 #include <limits> 45 #include <vector> 46 47 namespace ark::panda_file { 48 49 class FileReader { 50 public: 51 // default methods FileReader(std::unique_ptr<const File> && file)52 explicit FileReader(std::unique_ptr<const File> &&file) : file_(std::move(file)) {} 53 virtual ~FileReader() = default; 54 55 bool ReadContainer(bool shouldRebuildIndices = true); 56 GetContainerPtr()57 ItemContainer *GetContainerPtr() 58 { 59 return &container_; 60 } 61 GetFilePtr()62 const File *GetFilePtr() const 63 { 64 return file_.get(); 65 } 66 GetItems()67 const std::map<File::EntityId, BaseItem *> *GetItems() const 68 { 69 return &itemsDone_; 70 } 71 72 void ComputeLayoutAndUpdateIndices(); 73 74 NO_COPY_SEMANTIC(FileReader); 75 NO_MOVE_SEMANTIC(FileReader); 76 77 private: 78 bool ReadLiteralArrayItems(); 79 bool ReadRegionHeaders(); 80 bool ReadClasses(); 81 82 void EmplaceLiteralVals(std::vector<panda_file::LiteralItem> &literalArray, 83 const panda_file::LiteralDataAccessor::LiteralValue &value, 84 const panda_file::LiteralTag &tag); 85 bool CreateLiteralArrayItem(LiteralDataAccessor *litArrayAccessor, File::EntityId arrayId, uint32_t index); 86 ValueItem *SetElemValueItem(AnnotationDataAccessor::Tag &annTag, AnnotationDataAccessor::Elem &annElem); 87 AnnotationItem *CreateAnnotationItem(File::EntityId annId); 88 BaseClassItem *GetCatchTypeItem(CodeDataAccessor::CatchBlock &catchBlock, File::EntityId methodId, 89 MethodItem *methodItem); 90 void SetMethodCodeIfPresent(std::optional<File::EntityId> &codeId, MethodItem *methodItem, 91 File::EntityId &methodId); 92 TypeItem *SetRetType(ProtoDataAccessor &protoAcc, size_t &referenceNum); 93 MethodItem *CreateMethodItem(ClassItem *cls, File::EntityId methodId); 94 ForeignMethodItem *CreateForeignMethodItem(BaseClassItem *fcls, File::EntityId methodId); 95 void SetFieldValue(FieldItem *fieldItem, Type fieldType, FieldDataAccessor &fieldAcc); 96 FieldItem *CreateFieldItem(ClassItem *cls, File::EntityId fieldId); 97 ForeignFieldItem *CreateForeignFieldItem(BaseClassItem *fcls, File::EntityId fieldId); 98 BaseItem *CheckAndGetExistingFileItem(File::EntityId id, ItemTypes itemType); 99 ClassItem *CreateClassItem(File::EntityId classId); 100 ForeignClassItem *CreateForeignClassItem(File::EntityId classId); 101 MethodHandleItem *CreateMethodHandleItem(File::EntityId mhId); 102 TypeItem *CreateParamTypeItem(ProtoDataAccessor *protoAcc, size_t paramNum, size_t referenceNum); 103 std::vector<MethodParamItem> CreateMethodParamItems(ProtoDataAccessor *protoAcc, MethodDataAccessor *methodAcc, 104 size_t referenceNum); 105 DebugInfoItem *CreateDebugInfoItem(File::EntityId debugInfoId); 106 void UpdateDebugInfoDependecies(File::EntityId debugInfoId); 107 void UpdateDebugInfo(DebugInfoItem *debugInfoItem, File::EntityId debugInfoId); 108 109 void InstUpdateId(CodeItem *codeItem, MethodItem *methodItem, std::map<BaseItem *, File::EntityId> &reverseDone); 110 111 bool TryCreateMethodItem(File::EntityId methodId); 112 bool TryCreateFieldItem(File::EntityId fieldId); 113 114 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true> SetIntegerFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)115 void SetIntegerFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem) 116 { 117 auto value = fieldAcc->GetValue<T>(); 118 if (!value) { 119 return; 120 } 121 122 // NOLINTNEXTLINE(readability-braces-around-statements) 123 if constexpr (is_same_v<T, int64_t> || is_same_v<T, uint64_t>) { 124 auto *valueItem = container_.GetOrCreateLongValueItem(value.value()); 125 fieldItem->SetValue(valueItem); 126 // NOLINTNEXTLINE(readability-misleading-indentation) 127 } else { 128 auto *valueItem = container_.GetOrCreateIntegerValueItem(value.value()); 129 fieldItem->SetValue(valueItem); 130 } 131 } 132 133 template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true> SetFloatFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)134 void SetFloatFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem) 135 { 136 auto value = fieldAcc->GetValue<T>(); 137 if (!value) { 138 return; 139 } 140 141 // NOLINTNEXTLINE(readability-braces-around-statements) 142 if constexpr (is_same_v<T, double>) { 143 auto *valueItem = container_.GetOrCreateDoubleValueItem(value.value()); 144 fieldItem->SetValue(valueItem); 145 // NOLINTNEXTLINE(readability-misleading-indentation) 146 } else { 147 auto *valueItem = container_.GetOrCreateFloatValueItem(value.value()); 148 fieldItem->SetValue(valueItem); 149 } 150 } 151 SetStringFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)152 void SetStringFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem) 153 { 154 auto value = fieldAcc->GetValue<uint32_t>(); 155 if (value) { 156 panda_file::File::EntityId stringId(value.value()); 157 auto data = file_->GetStringData(stringId); 158 std::string stringData(reinterpret_cast<const char *>(data.data)); 159 auto *stringItem = container_.GetOrCreateStringItem(stringData); 160 auto *valueItem = container_.GetOrCreateIdValueItem(stringItem); 161 fieldItem->SetValue(valueItem); 162 } 163 } 164 165 // Creates foreign or non-foreign method item CreateGenericMethodItem(BaseClassItem * classItem,File::EntityId methodId)166 inline BaseItem *CreateGenericMethodItem(BaseClassItem *classItem, File::EntityId methodId) 167 { 168 if (file_->IsExternal(methodId)) { 169 return CreateForeignMethodItem(classItem, methodId); 170 } 171 LOG_IF(classItem->IsForeign(), FATAL, PANDAFILE) << "Non-foreign methods should not belong to foreign class."; 172 return CreateMethodItem(static_cast<ClassItem *>(classItem), methodId); 173 } 174 175 // Creates foreign or non-foreign field item CreateGenericFieldItem(BaseClassItem * classItem,File::EntityId fieldId)176 inline BaseItem *CreateGenericFieldItem(BaseClassItem *classItem, File::EntityId fieldId) 177 { 178 if (file_->IsExternal(fieldId)) { 179 return CreateForeignFieldItem(classItem, fieldId); 180 } 181 LOG_IF(classItem->IsForeign(), FATAL, PANDAFILE) << "Non-foreign fields should not belong to foreign class."; 182 return CreateFieldItem(static_cast<ClassItem *>(classItem), fieldId); 183 } 184 185 // Creates foreign or non-foreign class item CreateGenericClassItem(File::EntityId classId)186 inline BaseClassItem *CreateGenericClassItem(File::EntityId classId) 187 { 188 if (file_->IsExternal(classId)) { 189 return CreateForeignClassItem(classId); 190 } 191 return CreateClassItem(classId); 192 } 193 194 void InstCheckByFlags(BytecodeInstruction &inst, MethodItem *methodItem, 195 const std::map<BaseItem *, File::EntityId> &reverseDone); 196 void UpdateCodeAndDebugInfoDependencies(const std::map<BaseItem *, File::EntityId> &reverseDone); 197 198 std::unique_ptr<const File> file_; 199 ItemContainer container_; 200 std::map<File::EntityId, BaseItem *> itemsDone_; 201 }; 202 203 } // namespace ark::panda_file 204 205 #endif // LIBPANDAFILE_FILE_READER_H_ 206