1 /* 2 * Copyright (c) 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 16 #ifndef ECMASCRIPT_JIT_DUMP_ELF_H 17 #define ECMASCRIPT_JIT_DUMP_ELF_H 18 19 #include <vector> 20 #include <string> 21 #include <unistd.h> 22 #include <unordered_map> 23 24 #include "ecmascript/compiler/codegen/maple/maple_be/include/cg/elf_types.h" 25 #include "ecmascript/log_wrapper.h" 26 27 namespace panda::ecmascript { 28 29 using uint8 = uint8_t; 30 using uint16 = uint16_t; 31 using uint32 = uint32_t; 32 using uint64 = uint64_t; 33 using int8 = int8_t; 34 using int16 = int16_t; 35 using int32 = int32_t; 36 using int64 = int64_t; 37 using uintptr = uintptr_t; 38 39 const uint8 kLeftShift4Bits = 4; 40 static const uint8 k8Bits = 8; 41 42 class Section { 43 public: Section(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align)44 Section(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align) : name(name) 45 { 46 sectionHeader.sh_type = type; 47 sectionHeader.sh_flags = flags; 48 sectionHeader.sh_addralign = align; 49 } 50 51 virtual ~Section() = default; 52 virtual void GenerateData() = 0; 53 virtual void WriteSection(int fd) = 0; 54 ClearData()55 virtual void ClearData() 56 { 57 return; 58 } 59 SetIndex(maplebe::SectionIndex idx)60 void SetIndex(maplebe::SectionIndex idx) 61 { 62 sectionIndex = idx; 63 } 64 GetIndex() const65 maplebe::SectionIndex GetIndex() const 66 { 67 return sectionIndex; 68 } 69 SetInfo(maplebe::Word value)70 void SetInfo(maplebe::Word value) 71 { 72 sectionHeader.sh_info = value; 73 } 74 SetLink(const Section §ion)75 void SetLink(const Section §ion) 76 { 77 sectionHeader.sh_link = static_cast<maplebe::Word>(section.GetIndex()); 78 } 79 SetEntSize(maplebe::Xword value)80 void SetEntSize(maplebe::Xword value) 81 { 82 sectionHeader.sh_entsize = value; 83 } 84 SetSectionSize(maplebe::Xword size)85 void SetSectionSize(maplebe::Xword size) 86 { 87 sectionHeader.sh_size = size; 88 } 89 GetSectionSize()90 virtual maplebe::Xword GetSectionSize() 91 { 92 return sectionHeader.sh_size; 93 } 94 SetAddr(maplebe::Address addr)95 void SetAddr(maplebe::Address addr) 96 { 97 sectionHeader.sh_addr = addr; 98 } 99 GetAddr() const100 maplebe::Address GetAddr() const 101 { 102 return sectionHeader.sh_addr; 103 } 104 GetFlags() const105 maplebe::Xword GetFlags() const 106 { 107 return sectionHeader.sh_flags; 108 } 109 SetOffset(maplebe::Offset value)110 void SetOffset(maplebe::Offset value) 111 { 112 sectionHeader.sh_offset = value; 113 } 114 GetOffset() const115 maplebe::Offset GetOffset() const 116 { 117 return sectionHeader.sh_offset; 118 } 119 GetAlign() const120 maplebe::Xword GetAlign() const 121 { 122 return sectionHeader.sh_addralign; 123 } 124 GetName() const125 const std::string &GetName() const 126 { 127 return name; 128 } 129 SetSectionHeaderNameIndex(maplebe::Word index)130 void SetSectionHeaderNameIndex(maplebe::Word index) 131 { 132 sectionHeader.sh_name = index; 133 } 134 GetType() const135 maplebe::Word GetType() const 136 { 137 return sectionHeader.sh_type; 138 } 139 GetSectionHeader() const140 const maplebe::SectionHeader &GetSectionHeader() const 141 { 142 return sectionHeader; 143 } 144 145 private: 146 std::string name; 147 maplebe::SectionIndex sectionIndex {}; 148 maplebe::SectionHeader sectionHeader {}; 149 }; /* class Section */ 150 151 class RelaSection : public Section { 152 public: RelaSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Word info, maplebe::Xword align, const Section &link)153 RelaSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Word info, 154 maplebe::Xword align, const Section &link) : Section(name, type, flags, align) 155 { 156 SetEntSize(sizeof(maplebe::Rela)); 157 SetInfo(info); 158 SetLink(link); 159 } 160 161 ~RelaSection() = default; 162 163 void GenerateData() override 164 { 165 SetSectionSize(relas.size() * sizeof(maplebe::Rela)); 166 } 167 168 void WriteSection(int fd) override 169 { 170 (void)write(fd, reinterpret_cast<const char *>(relas.data()), relas.size() * sizeof(maplebe::Rela)); 171 } 172 AppendRela(maplebe::Rela rela)173 void AppendRela(maplebe::Rela rela) 174 { 175 relas.push_back(rela); 176 } 177 178 private: 179 std::vector<maplebe::Rela> relas; 180 }; /* class RelaSection */ 181 182 class SymbolSection : public Section { 183 public: SymbolSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align, const Section &link)184 SymbolSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align, 185 const Section &link) : Section(name, type, flags, align) 186 { 187 SetEntSize(sizeof(maplebe::Symbol)); 188 SetLink(link); 189 SetInfo(1); 190 AppendSymbol({0, 0, 0, 0, 0, 0}); 191 } 192 193 ~SymbolSection() = default; 194 195 void GenerateData() override 196 { 197 SetSectionSize(symbols.size() * sizeof(maplebe::Symbol)); 198 } 199 200 void WriteSection(int fd) override 201 { 202 (void)write(fd, reinterpret_cast<const char *>(symbols.data()), symbols.size() * sizeof(maplebe::Symbol)); 203 } 204 AppendSymbol(const maplebe::Symbol &symbol)205 void AppendSymbol(const maplebe::Symbol &symbol) 206 { 207 symbols.push_back(symbol); 208 } 209 GetSymbolsSize() const210 uint32 GetSymbolsSize() const 211 { 212 return symbols.size(); 213 } 214 GetIdxInSymbols(int64 symIdx) const215 uint64 GetIdxInSymbols(int64 symIdx) const 216 { 217 return symbolIdxMap.at(symIdx); 218 } 219 AppendIdxInSymbols(int64 symIdx)220 void AppendIdxInSymbols(int64 symIdx) 221 { 222 symbolIdxMap[symIdx] = static_cast<uint64>(GetSymbolsSize() - 1); 223 } 224 ExistSymInSymbols(int64 symIdx)225 bool ExistSymInSymbols(int64 symIdx) 226 { 227 return symbolIdxMap.count(symIdx) != 0; 228 } 229 GetDataSize() const230 uint32 GetDataSize() const 231 { 232 return symbols.size() * sizeof(maplebe::Symbol); 233 } 234 GetAddr()235 const char *GetAddr() 236 { 237 return reinterpret_cast<const char*>(symbols.data()); 238 } 239 240 void ClearData() override 241 { 242 symbols.clear(); 243 symbolIdxMap.clear(); 244 } 245 246 private: 247 std::vector<maplebe::Symbol> symbols; 248 std::unordered_map<int64, uint64> symbolIdxMap; 249 }; /* class SymbolSection */ 250 251 class DataSection : public Section { 252 public: DataSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align)253 DataSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align) 254 : Section(name, type, flags, align) {} 255 256 ~DataSection() = default; 257 258 virtual void GenerateData() override 259 { 260 SetSectionSize(data.size()); 261 } 262 263 virtual void WriteSection(int fd) override 264 { 265 (void)write(fd, reinterpret_cast<const char *>(data.data()), data.size()); 266 } 267 AppendData(const void *value, size_t size)268 void AppendData(const void *value, size_t size) 269 { 270 auto pdata = reinterpret_cast<const uint8 *>(value); 271 data.insert(data.end(), pdata, pdata + size); 272 } 273 AppendData(int64 value, size_t size)274 void AppendData(int64 value, size_t size) 275 { 276 for (size_t i = 0; i < size; i++) { 277 auto pdata = static_cast<uint8>(value >> (i * k8Bits)); 278 data.push_back(pdata); 279 } 280 } 281 282 void ClearData() override 283 { 284 data.clear(); 285 } 286 GetDataSize() const287 uint32 GetDataSize() const 288 { 289 return data.size(); 290 } 291 GetData() const292 const std::vector<uint8> &GetData() const 293 { 294 return data; 295 } 296 297 protected: 298 std::vector<uint8> data; 299 }; /* class DataSection */ 300 301 class StringSection : public DataSection { 302 public: StringSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align)303 StringSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align) 304 : DataSection(name, type, flags, align) 305 { 306 AddString("\0"); 307 } 308 309 ~StringSection() = default; 310 AddString(const std::string &str)311 size_t AddString(const std::string &str) 312 { 313 size_t pos = data.size(); 314 AppendData(str.c_str(), str.size() + 1); 315 return pos; 316 } 317 }; /* class StringSection */ 318 319 class Alignment { 320 public: 321 template <typename T> Align(T offset, T align)322 static T Align(T offset, T align) 323 { 324 if (align <= 1) { 325 return offset; 326 } 327 return (offset + align - 1) & (~(align - 1)); 328 } 329 }; /* class Alignment */ 330 331 class JsJitDumpElf { 332 public: 333 void Init(); 334 void SetFileOffset(int fd, uint64 offset); 335 void Initx86ElfHeader(); 336 void InitArmElfHeader(); 337 void WriteJitElfFile(int fd); 338 void LayoutSections(); 339 void UpdateSectionOffset(Section §ion); 340 void UpdateGlobalOffset(Section §ion); 341 void RegisterSection(Section §ion); 342 void AppendData(std::vector<uint8> &codeBuff); 343 void AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx); 344 void AppendGlobalSymsToSymTabSec(); 345 void AppendSymbolToSymTab(int64 symIdx, uint64 funcSymValue, uint64 funcSymSize, const std::string &symbolName); 346 void ClearData(); 347 private: 348 std::vector<std::pair<maplebe::Symbol, int64>> localSymTab; 349 DataSection *textSection = nullptr; 350 SymbolSection *symbolTabSection = nullptr; 351 maplebe::FileHeader header {}; 352 StringSection *strTabSection = nullptr; 353 std::vector<Section *> sections; 354 maplebe::Offset globalOffset = 0; /* global offset of the elf file */ 355 }; 356 357 } // namespace panda::ecmascript 358 #endif // ECMASCRIPT_JIT_DUMP_ELF_H 359