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