• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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     ClassItem *CreateClassItem(File::EntityId classId);
99     ForeignClassItem *CreateForeignClassItem(File::EntityId classId);
100     MethodHandleItem *CreateMethodHandleItem(File::EntityId mhId);
101     TypeItem *CreateParamTypeItem(ProtoDataAccessor *protoAcc, size_t paramNum, size_t referenceNum);
102     std::vector<MethodParamItem> CreateMethodParamItems(ProtoDataAccessor *protoAcc, MethodDataAccessor *methodAcc,
103                                                         size_t referenceNum);
104     DebugInfoItem *CreateDebugInfoItem(File::EntityId debugInfoId);
105     void UpdateDebugInfoDependecies(File::EntityId debugInfoId);
106     void UpdateDebugInfo(DebugInfoItem *debugInfoItem, File::EntityId debugInfoId);
107 
108     template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
SetIntegerFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)109     void SetIntegerFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem)
110     {
111         auto value = fieldAcc->GetValue<T>();
112         if (!value) {
113             return;
114         }
115 
116         // NOLINTNEXTLINE(readability-braces-around-statements)
117         if constexpr (is_same_v<T, int64_t> || is_same_v<T, uint64_t>) {
118             auto *valueItem = container_.GetOrCreateLongValueItem(value.value());
119             fieldItem->SetValue(valueItem);
120             // NOLINTNEXTLINE(readability-misleading-indentation)
121         } else {
122             auto *valueItem = container_.GetOrCreateIntegerValueItem(value.value());
123             fieldItem->SetValue(valueItem);
124         }
125     }
126 
127     template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
SetFloatFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)128     void SetFloatFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem)
129     {
130         auto value = fieldAcc->GetValue<T>();
131         if (!value) {
132             return;
133         }
134 
135         // NOLINTNEXTLINE(readability-braces-around-statements)
136         if constexpr (is_same_v<T, double>) {
137             auto *valueItem = container_.GetOrCreateDoubleValueItem(value.value());
138             fieldItem->SetValue(valueItem);
139             // NOLINTNEXTLINE(readability-misleading-indentation)
140         } else {
141             auto *valueItem = container_.GetOrCreateFloatValueItem(value.value());
142             fieldItem->SetValue(valueItem);
143         }
144     }
145 
SetStringFieldValue(FieldDataAccessor * fieldAcc,FieldItem * fieldItem)146     void SetStringFieldValue(FieldDataAccessor *fieldAcc, FieldItem *fieldItem)
147     {
148         auto value = fieldAcc->GetValue<uint32_t>();
149         if (value) {
150             panda_file::File::EntityId stringId(value.value());
151             auto data = file_->GetStringData(stringId);
152             std::string stringData(reinterpret_cast<const char *>(data.data));
153             auto *stringItem = container_.GetOrCreateStringItem(stringData);
154             auto *valueItem = container_.GetOrCreateIdValueItem(stringItem);
155             fieldItem->SetValue(valueItem);
156         }
157     }
158 
159     // Creates foreign or non-foreign method item
CreateGenericMethodItem(BaseClassItem * classItem,File::EntityId methodId)160     inline BaseItem *CreateGenericMethodItem(BaseClassItem *classItem, File::EntityId methodId)
161     {
162         if (file_->IsExternal(methodId)) {
163             return CreateForeignMethodItem(classItem, methodId);
164         }
165         return CreateMethodItem(static_cast<ClassItem *>(classItem), methodId);
166     }
167 
168     // Creates foreign or non-foreign field item
CreateGenericFieldItem(BaseClassItem * classItem,File::EntityId fieldId)169     inline BaseItem *CreateGenericFieldItem(BaseClassItem *classItem, File::EntityId fieldId)
170     {
171         if (file_->IsExternal(fieldId)) {
172             return CreateForeignFieldItem(classItem, fieldId);
173         }
174         return CreateFieldItem(static_cast<ClassItem *>(classItem), fieldId);
175     }
176 
177     // Creates foreign or non-foreign class item
CreateGenericClassItem(File::EntityId classId)178     inline BaseClassItem *CreateGenericClassItem(File::EntityId classId)
179     {
180         if (file_->IsExternal(classId)) {
181             return CreateForeignClassItem(classId);
182         }
183         return CreateClassItem(classId);
184     }
185 
186     void InstCheckByFlags(BytecodeInstruction &inst, MethodItem *methodItem,
187                           const std::map<BaseItem *, File::EntityId> &reverseDone);
188     void UpdateCodeAndDebugInfoDependencies(const std::map<BaseItem *, File::EntityId> &reverseDone);
189 
190     std::unique_ptr<const File> file_;
191     ItemContainer container_;
192     std::map<File::EntityId, BaseItem *> itemsDone_;
193 };
194 
195 }  // namespace ark::panda_file
196 
197 #endif  // LIBPANDAFILE_FILE_READER_H_
198