• 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 
16 #ifndef COMPILER_AOT_AOT_FILE_H
17 #define COMPILER_AOT_AOT_FILE_H
18 
19 #include "aot_headers.h"
20 #include "compiler/code_info/code_info.h"
21 #include "os/library_loader.h"
22 #include "utils/span.h"
23 #include "libpandafile/file.h"
24 
25 #include <string>
26 #include <array>
27 #include <memory>
28 #include <algorithm>
29 
30 namespace panda::compiler {
31 class RuntimeInterface;
32 
33 class AotFile {
34 public:
35     static constexpr std::array MAGIC = {'.', 'a', 'n', '\0'};
36     static constexpr std::array VERSION = {'0', '0', '6', '\0'};
37 
38     enum AotSlotType { PLT_SLOT = 1, VTABLE_INDEX = 2, CLASS_SLOT = 3, STRING_SLOT = 4, INLINECACHE_SLOT = 5 };
39 
AotFile(panda::os::library_loader::LibraryHandle && handle,Span<const uint8_t> aot_data,Span<const uint8_t> code)40     AotFile(panda::os::library_loader::LibraryHandle &&handle, Span<const uint8_t> aot_data, Span<const uint8_t> code)
41         : handle_(std::move(handle)), aot_data_(aot_data), code_(code)
42     {
43     }
44 
45     NO_MOVE_SEMANTIC(AotFile);
46     NO_COPY_SEMANTIC(AotFile);
47     ~AotFile() = default;
48 
49 public:
50     static Expected<std::unique_ptr<AotFile>, std::string> Open(const std::string &file_name, uint32_t gc_type,
51                                                                 bool for_dump = false);
52 
GetCode()53     const void *GetCode() const
54     {
55         return code_.data();
56     }
57 
GetCodeSize()58     size_t GetCodeSize() const
59     {
60         return code_.size();
61     }
62 
FileHeaders()63     auto FileHeaders() const
64     {
65         return aot_data_.SubSpan<const PandaFileHeader>(GetAotHeader()->files_offset, GetFilesCount());
66     }
67 
GetMethodHeader(size_t index)68     auto GetMethodHeader(size_t index) const
69     {
70         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
71         return reinterpret_cast<const MethodHeader *>(&aot_data_[GetAotHeader()->methods_offset]) + index;
72     }
73 
GetMethodHeadersPtr()74     const MethodHeader *GetMethodHeadersPtr() const
75     {
76         return reinterpret_cast<const MethodHeader *>(&aot_data_[GetAotHeader()->methods_offset]);
77     }
78 
GetClassHeaders(const PandaFileHeader & file_header)79     auto GetClassHeaders(const PandaFileHeader &file_header) const
80     {
81         return aot_data_.SubSpan<const ClassHeader>(GetAotHeader()->classes_offset +
82                                                         file_header.classes_offset * sizeof(ClassHeader),
83                                                     file_header.classes_count);
84     }
85 
GetClassHashTable(const PandaFileHeader & file_header)86     auto GetClassHashTable(const PandaFileHeader &file_header) const
87     {
88         return aot_data_.SubSpan<const panda::panda_file::EntityPairHeader>(GetAotHeader()->class_hash_tables_offset +
89                                                                                 file_header.class_hash_table_offset,
90                                                                             file_header.class_hash_table_size);
91     }
92 
GetMethodsBitmap()93     const uint8_t *GetMethodsBitmap() const
94     {
95         return &aot_data_[GetAotHeader()->bitmap_offset];
96     }
97 
GetFilesCount()98     size_t GetFilesCount() const
99     {
100         return GetAotHeader()->files_count;
101     }
102 
FindPandaFile(const std::string & file_name)103     const PandaFileHeader *FindPandaFile(const std::string &file_name) const
104     {
105         auto file_headers = FileHeaders();
106         auto res = std::find_if(file_headers.begin(), file_headers.end(), [this, &file_name](auto &header) {
107             return file_name == GetString(header.file_name_str);
108         });
109         return res == file_headers.end() ? nullptr : res;
110     }
111 
GetMethodCode(const MethodHeader * method_header)112     const uint8_t *GetMethodCode(const MethodHeader *method_header) const
113     {
114         return code_.data() + method_header->code_offset;
115     }
116 
GetString(size_t offset)117     const char *GetString(size_t offset) const
118     {
119         return reinterpret_cast<const char *>(aot_data_.data() + GetAotHeader()->strtab_offset + offset);
120     }
121 
GetAotHeader()122     const AotHeader *GetAotHeader() const
123     {
124         return reinterpret_cast<const AotHeader *>(aot_data_.data());
125     }
126 
GetFileName()127     const char *GetFileName() const
128     {
129         return GetString(GetAotHeader()->file_name_str);
130     }
131 
GetCommandLine()132     const char *GetCommandLine() const
133     {
134         return GetString(GetAotHeader()->cmdline_str);
135     }
136 
GetClassContext()137     const char *GetClassContext() const
138     {
139         return GetString(GetAotHeader()->class_ctx_str);
140     }
141 
IsCompiledWithCha()142     bool IsCompiledWithCha() const
143     {
144         return GetAotHeader()->with_cha != 0U;
145     }
146 
IsBootPandaFile()147     bool IsBootPandaFile() const
148     {
149         return GetAotHeader()->boot_aot != 0U;
150     }
151 
152     void InitializeGot(RuntimeInterface *runtime);
153 
154     void PatchTable(RuntimeInterface *runtime);
155 
156 private:
157     panda::os::library_loader::LibraryHandle handle_ {nullptr};
158     Span<const uint8_t> aot_data_;
159     Span<const uint8_t> code_;
160 };
161 
162 class AotClass final {
163 public:
164     AotClass() = default;
AotClass(const AotFile * file,const ClassHeader * header)165     AotClass(const AotFile *file, const ClassHeader *header) : aot_file_(file), header_(header) {}
166     ~AotClass() = default;
167     DEFAULT_COPY_SEMANTIC(AotClass);
168     DEFAULT_MOVE_SEMANTIC(AotClass);
169 
170     const void *FindMethodCodeEntry(size_t index) const;
171     Span<const uint8_t> FindMethodCodeSpan(size_t index) const;
172     const MethodHeader *FindMethodHeader(size_t index) const;
173 
174     BitVectorSpan GetBitmap() const;
175 
GetMethodHeaders()176     auto GetMethodHeaders() const
177     {
178         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
179         return Span(aot_file_->GetMethodHeadersPtr() + header_->methods_offset, header_->methods_count);
180     }
181 
Invalid()182     static AotClass Invalid()
183     {
184         return AotClass();
185     }
186 
IsValid()187     bool IsValid() const
188     {
189         return header_ != nullptr;
190     }
191 
192 private:
193     const AotFile *aot_file_ {nullptr};
194     const ClassHeader *header_ {nullptr};
195 };
196 
197 class AotPandaFile {
198 public:
199     AotPandaFile() = default;
AotPandaFile(AotFile * file,const PandaFileHeader * header)200     AotPandaFile(AotFile *file, const PandaFileHeader *header) : aot_file_(file), header_(header)
201     {
202         LoadClassHashTable();
203     }
204 
205     DEFAULT_MOVE_SEMANTIC(AotPandaFile);
206     DEFAULT_COPY_SEMANTIC(AotPandaFile);
207     ~AotPandaFile() = default;
208 
GetAotFile()209     const AotFile *GetAotFile() const
210     {
211         return aot_file_;
212     }
GetHeader()213     const PandaFileHeader *GetHeader()
214     {
215         return header_;
216     }
GetHeader()217     const PandaFileHeader *GetHeader() const
218     {
219         return header_;
220     }
GetFileName()221     std::string GetFileName() const
222     {
223         return GetAotFile()->GetString(GetHeader()->file_name_str);
224     }
225     AotClass GetClass(uint32_t class_id) const;
226 
GetClassHeaders()227     Span<const ClassHeader> GetClassHeaders() const
228     {
229         return aot_file_->GetClassHeaders(*header_);
230     }
231 
GetMethodCodeInfo(const MethodHeader * method_header)232     CodeInfo GetMethodCodeInfo(const MethodHeader *method_header) const
233     {
234         return CodeInfo(GetAotFile()->GetMethodCode(method_header), method_header->code_size);
235     }
236 
LoadClassHashTable()237     void LoadClassHashTable()
238     {
239         class_hash_table_ = GetAotFile()->GetClassHashTable(*header_);
240     }
241 
GetClassHashTable()242     panda::Span<const panda::panda_file::EntityPairHeader> GetClassHashTable() const
243     {
244         return class_hash_table_;
245     }
246 
247 private:
248     AotFile *aot_file_ {nullptr};
249     const PandaFileHeader *header_ {nullptr};
250     panda::Span<const panda::panda_file::EntityPairHeader> class_hash_table_;
251 };
252 }  // namespace panda::compiler
253 
254 #endif  // COMPILER_AOT_AOT_FILE_H
255