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 27namespace panda::ecmascript { 28 29using uint8 = uint8_t; 30using uint16 = uint16_t; 31using uint32 = uint32_t; 32using uint64 = uint64_t; 33using int8 = int8_t; 34using int16 = int16_t; 35using int32 = int32_t; 36using int64 = int64_t; 37using uintptr = uintptr_t; 38 39const uint8 kLeftShift4Bits = 4; 40static const uint8 k8Bits = 8; 41 42class Section { 43public: 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 55 virtual void ClearData() 56 { 57 return; 58 } 59 60 void SetIndex(maplebe::SectionIndex idx) 61 { 62 sectionIndex = idx; 63 } 64 65 maplebe::SectionIndex GetIndex() const 66 { 67 return sectionIndex; 68 } 69 70 void SetInfo(maplebe::Word value) 71 { 72 sectionHeader.sh_info = value; 73 } 74 75 void SetLink(const Section §ion) 76 { 77 sectionHeader.sh_link = static_cast<maplebe::Word>(section.GetIndex()); 78 } 79 80 void SetEntSize(maplebe::Xword value) 81 { 82 sectionHeader.sh_entsize = value; 83 } 84 85 void SetSectionSize(maplebe::Xword size) 86 { 87 sectionHeader.sh_size = size; 88 } 89 90 virtual maplebe::Xword GetSectionSize() 91 { 92 return sectionHeader.sh_size; 93 } 94 95 void SetAddr(maplebe::Address addr) 96 { 97 sectionHeader.sh_addr = addr; 98 } 99 100 maplebe::Address GetAddr() const 101 { 102 return sectionHeader.sh_addr; 103 } 104 105 maplebe::Xword GetFlags() const 106 { 107 return sectionHeader.sh_flags; 108 } 109 110 void SetOffset(maplebe::Offset value) 111 { 112 sectionHeader.sh_offset = value; 113 } 114 115 maplebe::Offset GetOffset() const 116 { 117 return sectionHeader.sh_offset; 118 } 119 120 maplebe::Xword GetAlign() const 121 { 122 return sectionHeader.sh_addralign; 123 } 124 125 const std::string &GetName() const 126 { 127 return name; 128 } 129 130 void SetSectionHeaderNameIndex(maplebe::Word index) 131 { 132 sectionHeader.sh_name = index; 133 } 134 135 maplebe::Word GetType() const 136 { 137 return sectionHeader.sh_type; 138 } 139 140 const maplebe::SectionHeader &GetSectionHeader() const 141 { 142 return sectionHeader; 143 } 144 145private: 146 std::string name; 147 maplebe::SectionIndex sectionIndex {}; 148 maplebe::SectionHeader sectionHeader {}; 149}; /* class Section */ 150 151class RelaSection : public Section { 152public: 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 173 void AppendRela(maplebe::Rela rela) 174 { 175 relas.push_back(rela); 176 } 177 178private: 179 std::vector<maplebe::Rela> relas; 180}; /* class RelaSection */ 181 182class SymbolSection : public Section { 183public: 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 205 void AppendSymbol(const maplebe::Symbol &symbol) 206 { 207 symbols.push_back(symbol); 208 } 209 210 uint32 GetSymbolsSize() const 211 { 212 return symbols.size(); 213 } 214 215 uint64 GetIdxInSymbols(int64 symIdx) const 216 { 217 return symbolIdxMap.at(symIdx); 218 } 219 220 void AppendIdxInSymbols(int64 symIdx) 221 { 222 symbolIdxMap[symIdx] = static_cast<uint64>(GetSymbolsSize() - 1); 223 } 224 225 bool ExistSymInSymbols(int64 symIdx) 226 { 227 return symbolIdxMap.count(symIdx) != 0; 228 } 229 230 uint32 GetDataSize() const 231 { 232 return symbols.size() * sizeof(maplebe::Symbol); 233 } 234 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 246private: 247 std::vector<maplebe::Symbol> symbols; 248 std::unordered_map<int64, uint64> symbolIdxMap; 249}; /* class SymbolSection */ 250 251class DataSection : public Section { 252public: 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 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 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 287 uint32 GetDataSize() const 288 { 289 return data.size(); 290 } 291 292 const std::vector<uint8> &GetData() const 293 { 294 return data; 295 } 296 297protected: 298 std::vector<uint8> data; 299}; /* class DataSection */ 300 301class StringSection : public DataSection { 302public: 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 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 319class Alignment { 320public: 321 template <typename T> 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 331class JsJitDumpElf { 332public: 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(); 347private: 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