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