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