1/* 2 * Copyright (c) 2023 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#include "ecmascript/compiler/aot_file/elf_builder.h" 17 18namespace panda::ecmascript { 19void ElfBuilder::AddShStrTabSection() 20{ 21 std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = 22 des_[ShStrTableModuleDesIndex].GetSectionsInfo(); 23 24 uint32_t size = 1; 25 for (auto &s : sections_) { 26 std::string str = ModuleSectionDes::GetSecName(s); 27 size = size + str.size() + 1; 28 } 29 30 shStrTabPtr_ = std::make_unique<char []>(size); 31 char *dst = shStrTabPtr_.get(); 32 dst[0] = 0x0; 33 uint32_t i = 1; 34 for (auto &s: sections_) { 35 std::string str = ModuleSectionDes::GetSecName(s); 36 uint32_t copySize = str.size(); 37 if (copySize == 0) { 38 UNREACHABLE(); 39 } 40 ASSERT(size >= i); 41 if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) { 42 UNREACHABLE(); 43 } 44 dst[i + copySize] = 0x0; 45 i = i + copySize + 1; 46 } 47 if (sections.find(ElfSecName::SHSTRTAB) != sections.end()) { 48 sections.erase(ElfSecName::SHSTRTAB); 49 } 50 sections[ElfSecName::SHSTRTAB] = std::make_pair(reinterpret_cast<uint64_t>(shStrTabPtr_.get()), size); 51 if (enableSecDump_) { 52 DumpSection(); 53 } 54} 55 56uint32_t ElfBuilder::AddAsmStubStrTab(std::ofstream &elfFile, 57 const std::vector<std::pair<std::string, uint32_t>> &asmStubELFInfo) 58{ 59 uint32_t size = 1; 60 ASSERT(asmStubELFInfo.size() > 0); 61 uint32_t asmStubSymTabNum = asmStubELFInfo.size() - 1; 62 for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) { 63 const std::string &str = asmStubELFInfo[idx].first; 64 size = size + str.size() + 1; 65 } 66 67 std::unique_ptr<char []> asmStubStrTabPtr = std::make_unique<char []>(size); 68 char *dst = asmStubStrTabPtr.get(); 69 dst[0] = 0x0; 70 uint32_t i = 1; 71 for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) { 72 const std::string &str = asmStubELFInfo[idx].first; 73 asmStubStrName_.emplace_back(i); 74 uint32_t copySize = str.size(); 75 if (copySize == 0) { 76 UNREACHABLE(); 77 } 78 if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) { 79 UNREACHABLE(); 80 } 81 dst[i + copySize] = 0x0; 82 i = i + copySize + 1; 83 } 84 elfFile.write(reinterpret_cast<char *>(dst), size); 85 return size; 86} 87 88void ElfBuilder::DumpSection() const 89{ 90 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 91 // dump 92 for (auto &s : sections) { 93 ElfSection section = ElfSection(s.first); 94 if (!section.ShouldDumpToAOTFile()) { 95 continue; 96 } 97 LOG_COMPILER(INFO) << "secname :" << std::dec << static_cast<int>(s.first) 98 << " addr:0x" << std::hex << s.second.first << " size:0x" << s.second.second << std::endl; 99 } 100} 101 102ElfBuilder::ElfBuilder(const std::vector<ModuleSectionDes> &des, 103 const std::vector<ElfSecName> §ions): des_(des), sections_(sections) 104{ 105 Initialize(); 106 AddShStrTabSection(); 107 RemoveNotNeedSection(); 108} 109 110void ElfBuilder::Initialize() 111{ 112 for (size_t i = 0; i < des_.size(); i++) { 113 des_[i].AddArkStackMapSection(); 114 } 115 sectionToAlign_ = { 116 {ElfSecName::TEXT, AOTFileInfo::PAGE_ALIGN}, 117 {ElfSecName::STRTAB, 1}, 118 {ElfSecName::SYMTAB, AOTFileInfo::DATA_SEC_ALIGN}, 119 {ElfSecName::SHSTRTAB, AOTFileInfo::DATA_SEC_ALIGN}, 120 {ElfSecName::ARK_STACKMAP, AOTFileInfo::DATA_SEC_ALIGN}, 121 {ElfSecName::ARK_FUNCENTRY, AOTFileInfo::DATA_SEC_ALIGN}, 122 {ElfSecName::ARK_ASMSTUB, AOTFileInfo::DATA_SEC_ALIGN}, 123 {ElfSecName::ARK_MODULEINFO, AOTFileInfo::DATA_SEC_ALIGN}, 124 }; 125 126 sectionToSegment_ = { 127 {ElfSecName::RODATA, ElfSecName::TEXT}, 128 {ElfSecName::RODATA_CST4, ElfSecName::TEXT}, 129 {ElfSecName::RODATA_CST8, ElfSecName::TEXT}, 130 {ElfSecName::RODATA_CST16, ElfSecName::TEXT}, 131 {ElfSecName::RODATA_CST32, ElfSecName::TEXT}, 132 {ElfSecName::TEXT, ElfSecName::TEXT}, 133 {ElfSecName::STRTAB, ElfSecName::DATA}, 134 {ElfSecName::SYMTAB, ElfSecName::DATA}, 135 {ElfSecName::SHSTRTAB, ElfSecName::DATA}, 136 {ElfSecName::ARK_STACKMAP, ElfSecName::DATA}, 137 {ElfSecName::ARK_FUNCENTRY, ElfSecName::DATA}, 138 {ElfSecName::ARK_ASMSTUB, ElfSecName::TEXT}, 139 {ElfSecName::ARK_MODULEINFO, ElfSecName::DATA}, 140 }; 141 142 segmentToFlag_ = { 143 {ElfSecName::TEXT, llvm::ELF::PF_X | llvm::ELF::PF_R}, 144 {ElfSecName::DATA, llvm::ELF::PF_R}, 145 }; 146 147 SetLastSection(); 148} 149 150void ElfBuilder::RemoveNotNeedSection() 151{ 152 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 153 for (size_t i = 0; i < sections_.size();) { 154 if (sections.find(sections_[i]) == sections.end()) { 155 auto it = sections_.begin() + i; 156 sections_.erase(it); 157 continue; 158 } 159 i++; 160 } 161} 162 163ElfBuilder::~ElfBuilder() 164{ 165 shStrTabPtr_ = nullptr; 166} 167 168uint32_t ElfBuilder::GetShIndex(ElfSecName section) const 169{ 170 std::set<ElfSecName> secSet(sections_.begin(), sections_.end()); 171 uint32_t idx = 1; 172 for (ElfSecName sec : secSet) { 173 if (sec == section) { 174 return idx; 175 } 176 idx++; 177 } 178 return 0; 179} 180 181int ElfBuilder::GetSecNum() const 182{ 183 return sections_.size() + 1; // add first empty section. 184} 185 186/* 187ELF Header as follow: 188ELF Header: 189 Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 190 Class: ELF64 191 Data: 2's complement, little endian 192 Version: 1 (current) 193 OS/ABI: UNIX - System V 194 ABI Version: 0 195 Type: DYN (Shared object file) 196 Machine: Advanced Micro Devices X86-64 197 Version: 0x4000001 198 Entry point address: 0x0 199 Start of program headers: 16384 (bytes into file) 200 Start of section headers: 64 (bytes into file) 201 Flags: 0x0 202 Size of this header: 64 (bytes) 203 Size of program headers: 56 (bytes) 204 Number of program headers: 2 205 Size of section headers: 64 (bytes) 206 Number of section headers: 7 207 Section header string table index: 3 208*/ 209void ElfBuilder::PackELFHeader(llvm::ELF::Elf64_Ehdr &header, uint32_t version, Triple triple) 210{ 211 if (memset_s(reinterpret_cast<void *>(&header), sizeof(llvm::ELF::Elf64_Ehdr), 0, 212 sizeof(llvm::ELF::Elf64_Ehdr)) != EOK) { 213 UNREACHABLE(); 214 } 215 header.e_ident[llvm::ELF::EI_MAG0] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0]; 216 header.e_ident[llvm::ELF::EI_MAG1] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1]; 217 header.e_ident[llvm::ELF::EI_MAG2] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2]; 218 header.e_ident[llvm::ELF::EI_MAG3] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3]; 219 header.e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64; 220 header.e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB; 221 header.e_ident[llvm::ELF::EI_VERSION] = 1; 222 223 header.e_type = llvm::ELF::ET_DYN; 224 switch (triple) { 225 case Triple::TRIPLE_AMD64: 226 header.e_machine = llvm::ELF::EM_X86_64; 227 break; 228 case Triple::TRIPLE_ARM32: 229 header.e_machine = llvm::ELF::EM_ARM; 230 break; 231 case Triple::TRIPLE_AARCH64: 232 header.e_machine = llvm::ELF::EM_AARCH64; 233 break; 234 default: 235 UNREACHABLE(); 236 break; 237 } 238 header.e_version = version; 239 // start of section headers 240 header.e_shoff = sizeof(llvm::ELF::Elf64_Ehdr); 241 // size of ehdr 242 header.e_ehsize = sizeof(llvm::ELF::Elf64_Ehdr); 243 // size of section headers 244 header.e_shentsize = sizeof(llvm::ELF::Elf64_Shdr); 245 // number of section headers 246 header.e_shnum = GetSecNum(); 247 // section header string table index 248 header.e_shstrndx = static_cast<llvm::ELF::Elf64_Half>(GetShIndex(ElfSecName::SHSTRTAB)); 249 // section header stub sec info index 250 header.e_flags = static_cast<llvm::ELF::Elf64_Word>(GetShIndex(ElfSecName::ARK_MODULEINFO)); 251 // phr 252 header.e_phentsize = sizeof(llvm::ELF::Elf64_Phdr); 253 header.e_phnum = GetSegmentNum(); 254} 255 256int ElfBuilder::GetSegmentNum() const 257{ 258 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 259 std::set<ElfSecName> segments; 260 for (auto &s: sections) { 261 ElfSection section = ElfSection(s.first); 262 if (!section.ShouldDumpToAOTFile()) { 263 continue; 264 } 265 auto it = sectionToSegment_.find(s.first); 266 ASSERT(it != sectionToSegment_.end()); 267 ElfSecName name = it->second; 268 segments.insert(name); 269 } 270 return segments.size(); 271} 272 273void ElfBuilder::SetLastSection() 274{ 275 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 276 for (auto &s: sections) { 277 ElfSection section = ElfSection(s.first); 278 if (!section.ShouldDumpToAOTFile()) { 279 continue; 280 } 281 auto it = sectionToSegment_.find(s.first); 282 ASSERT(it != sectionToSegment_.end()); 283 ElfSecName name = it->second; 284 if (name == ElfSecName::TEXT) { 285 lastCodeSection = std::max(lastCodeSection, s.first); 286 } else { 287 lastDataSection = std::max(lastDataSection, s.first); 288 } 289 } 290} 291 292llvm::ELF::Elf64_Word ElfBuilder::FindShName(std::string name, uintptr_t strTabPtr, int strTabSize) 293{ 294 llvm::ELF::Elf64_Word ans = -1; 295 int len = static_cast<int>(name.size()); 296 if (strTabSize < len + 1) { 297 return ans; 298 } 299 LOG_ECMA(DEBUG) << " FindShName name:" << name.c_str() << std::endl; 300 for (int i = 0; i < strTabSize - len + 1; ++i) { 301 char *dst = reinterpret_cast<char *>(strTabPtr) + i; 302 if (name.compare(dst) == 0) { 303 return i; 304 } 305 } 306 return ans; 307} 308 309std::pair<uint64_t, uint32_t> ElfBuilder::FindShStrTab() const 310{ 311 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 312 uint64_t shStrTabAddr = 0; 313 uint32_t shStrTabSize = 0; 314 for (auto &s: sections) { 315 uint32_t curSecSize = des_[ShStrTableModuleDesIndex].GetSecSize(s.first); 316 uint64_t curSecAddr = des_[ShStrTableModuleDesIndex].GetSecAddr(s.first); 317 if (s.first == ElfSecName::SHSTRTAB) { 318 shStrTabSize = curSecSize; 319 shStrTabAddr = curSecAddr; 320 break; 321 } 322 } 323 return std::make_pair(shStrTabAddr, shStrTabSize); 324} 325 326void ElfBuilder::AllocateShdr(std::unique_ptr<llvm::ELF::Elf64_Shdr []> &shdr, const uint32_t &secNum) 327{ 328 shdr = std::make_unique<llvm::ELF::Elf64_Shdr []>(secNum); 329 if (memset_s(reinterpret_cast<void *>(&shdr[0]), 330 sizeof(llvm::ELF::Elf64_Shdr), 331 0, 332 sizeof(llvm::ELF::Elf64_Shdr)) != EOK) { 333 UNREACHABLE(); 334 } 335} 336 337llvm::ELF::Elf64_Off ElfBuilder::ComputeEndAddrOfShdr(const uint32_t &secNum) const 338{ 339 llvm::ELF::Elf64_Off curSecOffset = sizeof(llvm::ELF::Elf64_Ehdr) + secNum * sizeof(llvm::ELF::Elf64_Shdr); 340 curSecOffset = AlignUp(curSecOffset, PageSize()); // not pagesize align will cause performance degradation 341 return curSecOffset; 342} 343 344ElfSecName ElfBuilder::GetSegmentName(const ElfSecName &secName) const 345{ 346 auto it = sectionToSegment_.find(secName); 347 ASSERT(it != sectionToSegment_.end()); 348 ElfSecName segName = it->second; 349 return segName; 350} 351 352void ElfBuilder::MergeTextSections(std::ofstream &file, 353 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo, 354 llvm::ELF::Elf64_Off &curSecOffset) 355{ 356 for (size_t i = 0; i < des_.size(); ++i) { 357 ModuleSectionDes &des = des_[i]; 358 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i]; 359 uint32_t curSecSize = des.GetSecSize(ElfSecName::TEXT); 360 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::TEXT); 361 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN); 362 file.seekp(curSecOffset); 363 auto curModuleSec = des.GetSectionsInfo(); 364 uint64_t rodataAddrBeforeText = 0; 365 uint32_t rodataSizeBeforeText = 0; 366 uint64_t rodataAddrAfterText = 0; 367 uint32_t rodataSizeAfterText = 0; 368 std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) = 369 des.GetMergedRODataAddrAndSize(curSecAddr); 370 if (rodataSizeBeforeText != 0) { 371 file.write(reinterpret_cast<char *>(rodataAddrBeforeText), rodataSizeBeforeText); 372 curInfo.rodataSizeBeforeText = rodataSizeBeforeText; 373 curSecOffset += rodataSizeBeforeText; 374 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN); 375 file.seekp(curSecOffset); 376 } 377 stubTextOffset_.emplace_back(curSecOffset); 378 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize); 379 curInfo.textSize = curSecSize; 380 curSecOffset += curSecSize; 381 if (rodataSizeAfterText != 0) { 382 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::DATA_SEC_ALIGN); 383 file.seekp(curSecOffset); 384 file.write(reinterpret_cast<char *>(rodataAddrAfterText), rodataSizeAfterText); 385 curInfo.rodataSizeAfterText = rodataSizeAfterText; 386 curSecOffset += rodataSizeAfterText; 387 } 388 } 389} 390 391void ElfBuilder::MergeStrtabSections(std::ofstream &file, 392 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo, 393 llvm::ELF::Elf64_Off &curSecOffset) 394{ 395 for (size_t i = 0; i < des_.size(); ++i) { 396 ModuleSectionDes &des = des_[i]; 397 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i]; 398 uint32_t curSecSize = des.GetSecSize(ElfSecName::STRTAB); 399 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::STRTAB); 400 curInfo.strtabSize = curSecSize; 401 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize); 402 curSecOffset += curSecSize; 403 if (des.HasAsmStubStrTab()) { 404 uint32_t asmStubStrTabSize = AddAsmStubStrTab(file, des.GetAsmStubELFInfo()); 405 curSecOffset += asmStubStrTabSize; 406 curInfo.strtabSize += asmStubStrTabSize; 407 } 408 } 409} 410 411void ElfBuilder::MergeSymtabSections(std::ofstream &file, 412 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo, 413 llvm::ELF::Elf64_Off &curSecOffset, 414 llvm::ELF::Elf64_Off &asmStubOffset) 415{ 416 using Elf64_Sym = llvm::ELF::Elf64_Sym; 417 uint32_t strTabSize = 0; 418 uint32_t textSecIndex = GetShIndex(ElfSecName::ARK_ASMSTUB); 419 for (size_t i = 0; i < des_.size(); ++i) { 420 ModuleSectionDes &des = des_[i]; 421 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i]; 422 uint32_t curSecSize = des.GetSecSize(ElfSecName::SYMTAB); 423 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::SYMTAB); 424 curInfo.symtabSize = curSecSize; 425 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize); 426 curSecOffset += curSecSize; 427 strTabSize += des.GetSecSize(ElfSecName::STRTAB); 428 if (des.HasAsmStubStrTab()) { 429 const std::vector<std::pair<std::string, uint32_t>> &asmStubELFInfo = des.GetAsmStubELFInfo(); 430 ASSERT(asmStubELFInfo.size() > 0); 431 uint32_t asmStubSymTabNum = asmStubELFInfo.size() - 1; 432 std::unique_ptr<Elf64_Sym []> syms = std::make_unique<Elf64_Sym []>(asmStubSymTabNum); 433 ASSERT(asmStubStrName_.size() == asmStubSymTabNum); 434 for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) { 435 Elf64_Sym &sym = syms[idx]; 436 sym.setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_FUNC); 437 sym.st_shndx = static_cast<uint16_t>(textSecIndex); 438 sym.st_value = asmStubELFInfo[idx].second + asmStubOffset; 439 sym.st_name = asmStubStrName_[idx]; 440 sym.st_name += strTabSize; 441 sym.st_other = llvm::ELF::STV_DEFAULT; 442 sym.st_size = asmStubELFInfo[idx + 1].second - asmStubELFInfo[idx].second; 443 } 444 uint32_t asmStubSymTabSize = asmStubSymTabNum * sizeof(llvm::ELF::Elf64_Sym); 445 file.write(reinterpret_cast<char *>(syms.get()), asmStubSymTabSize); 446 curInfo.symtabSize += asmStubSymTabSize; 447 curSecOffset += asmStubSymTabSize; 448 } 449 } 450} 451 452void ElfBuilder::MergeArkStackMapSections(std::ofstream &file, 453 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo, 454 llvm::ELF::Elf64_Off &curSecOffset) 455{ 456 for (size_t i = 0; i < des_.size(); ++i) { 457 ModuleSectionDes &des = des_[i]; 458 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i]; 459 uint32_t curSecSize = des.GetSecSize(ElfSecName::ARK_STACKMAP); 460 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::ARK_STACKMAP); 461 uint32_t index = des.GetStartIndex(); 462 uint32_t cnt = des.GetFuncCount(); 463 curInfo.startIndex = index; 464 curInfo.funcCount = cnt; 465 curInfo.stackMapSize = curSecSize; 466 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize); 467 curSecOffset += curSecSize; 468 } 469} 470 471void ElfBuilder::FixSymtab(llvm::ELF::Elf64_Shdr* shdr) 472{ 473 using Elf64_Sym = llvm::ELF::Elf64_Sym; 474 ASSERT(stubTextOffset_.size() == des_.size()); 475 476 uint32_t secNum = static_cast<uint32_t>(GetSecNum()); 477 uint32_t shStrTabIndex = GetShIndex(ElfSecName::SHSTRTAB); 478 uint32_t strTabIndex = GetShIndex(ElfSecName::STRTAB); 479 uint32_t textSecIndex = GetShIndex(ElfSecName::TEXT); 480 481 uint32_t strTabSize = 0; 482 int firstGlobal = -1; 483 uint32_t count = 0; 484 485 for (size_t idx = 0; idx < des_.size(); ++idx) { 486 uint32_t secSize = des_[idx].GetSecSize(ElfSecName::SYMTAB); 487 uint64_t secAddr = des_[idx].GetSecAddr(ElfSecName::SYMTAB); 488 Elf64_Sym *syms = reinterpret_cast<Elf64_Sym*>(secAddr); 489 size_t n = secSize / sizeof(Elf64_Sym); 490 for (size_t i = 0; i < n; ++i) { 491 Elf64_Sym* sy = &syms[i]; 492 if (sy->getBinding() == llvm::ELF::STB_GLOBAL && firstGlobal == -1) { 493 firstGlobal = static_cast<int>(count); 494 } 495 if (sy->getType() == llvm::ELF::STT_SECTION) { 496 sy->st_shndx = static_cast<uint16_t>(shStrTabIndex); 497 } else if (sy->getType() == llvm::ELF::STT_FUNC) { 498 sy->st_shndx = static_cast<uint16_t>(textSecIndex); 499 sy->st_value += stubTextOffset_[idx]; 500 } 501 if (sy->st_shndx > secNum) { 502 sy->st_shndx = 0; 503 } 504 sy->st_name += strTabSize; 505 count++; 506 } 507 strTabSize += des_[idx].GetSecSize(ElfSecName::STRTAB); 508 } 509 shdr->sh_info = static_cast<uint32_t>(firstGlobal); 510 shdr->sh_link = strTabIndex; 511} 512 513/* 514 515section of aot.an layout as follows: 516There are 7 section headers, starting at offset 0x40: 517 518Section Headers: 519 [Nr] Name Type Address Offset Size EntSize Flags Link Info Align 520 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 521 [ 1] .text PROGBITS 0000000000001000 00001000 0000000000000f61 0000000000000000 AX 0 0 16 522 [ 2] .strtab STRTAB 0000000000002000 00002000 0000000000000187 0000000000000000 A 0 0 1 523 [ 3] .symtab SYMTAB 0000000000002188 00002188 00000000000001c8 0000000000000018 A 1 0 8 524 [ 4] .shstrtab STRTAB 0000000000002350 00002350 000000000000003f 0000000000000000 A 0 0 8 525 [ 5] .ark_funcentry PROGBITS 0000000000002390 00002390 00000000000006c0 0000000000000000 A 0 0 8 526 [ 6] .ark_stackmaps PROGBITS 0000000000002a50 00002a50 000000000000070e 0000000000000000 A 0 0 8 527 528section of stub.an layout as follows: 529There are 7 section headers, starting at offset 0x40: 530 531 [Nr] Name Type Address Offset Size EntSize Flags Link Info Align 532 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 533 [ 1] .text PROGBITS 0000000000001000 00001000 000000000008225e 0000000000000000 AX 0 0 16 534 [ 2] .ark_asmstub PROGBITS 0000000000083260 00083260 0000000000002dc0 0000000000000000 AX 0 0 8 535 [ 3] .shstrtab STRTAB 0000000000087000 00087000 000000000000004c 0000000000000000 A 0 0 8 536 [ 4] .ark_funcentry PROGBITS 0000000000087050 00087050 0000000000023ca0 0000000000000000 A 0 0 8 537 [ 5] .ark_stackmaps PROGBITS 00000000000aacf0 000aacf0 0000000000011e90 0000000000000000 A 0 0 8 538 [ 6] .ark_moduleinfo PROGBITS 00000000000bcb80 000bcb80 000000000000003c 0000000000000000 A 0 0 8 539 540Key to Flags: 541 W (write), A (alloc), X (execute), M (merge), S (strings), I (info), 542 L (link order), O (extra OS processing required), G (group), T (TLS), 543 C (compressed), x (unknown), o (OS specific), E (exclude), 544 D (mbind), l (large), p (processor specific) 545*/ 546void ElfBuilder::PackELFSections(std::ofstream &file) 547{ 548 uint32_t moduleNum = des_.size(); 549 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 550 uint32_t secNum = sections.size() + 1; // 1 : section id = 0 is null section 551 std::unique_ptr<llvm::ELF::Elf64_Shdr []> shdr; 552 AllocateShdr(shdr, secNum); 553 std::vector<ModuleSectionDes::ModuleRegionInfo> moduleInfo(moduleNum); 554 llvm::ELF::Elf64_Off curSecOffset = ComputeEndAddrOfShdr(secNum); 555 file.seekp(curSecOffset); 556 557 int i = static_cast<int>(GetShIndex(ElfSecName::TEXT)); 558 auto shStrTab = FindShStrTab(); 559 560 for (auto const &[secName, secInfo] : sections) { 561 auto &curShdr = shdr[i]; 562 ElfSection section = ElfSection(secName); 563 if (!section.ShouldDumpToAOTFile()) { 564 continue; 565 } 566 curShdr.sh_addralign = sectionToAlign_[secName]; 567 curSecOffset = AlignUp(curSecOffset, curShdr.sh_addralign); 568 file.seekp(curSecOffset); 569 ElfSecName segName = GetSegmentName(secName); 570 segments_.insert(segName); 571 std::string secNameStr = ModuleSectionDes::GetSecName(secName); 572 // text section address needs 16 bytes alignment 573 if (secName == ElfSecName::TEXT) { 574 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN); 575 file.seekp(curSecOffset); 576 } 577 llvm::ELF::Elf64_Word shName = FindShName(secNameStr, shStrTab.first, shStrTab.second); 578 ASSERT(shName != static_cast<llvm::ELF::Elf64_Word>(-1)); 579 curShdr.sh_name = shName; 580 curShdr.sh_type = section.Type(); 581 curShdr.sh_flags = section.Flag(); 582 curShdr.sh_addr = curSecOffset; 583 curShdr.sh_offset = static_cast<uint64_t>(curSecOffset); 584 curShdr.sh_info = 0; 585 curShdr.sh_link = static_cast<uint32_t>(section.Link()); 586 sectionToFileOffset_[secName] = static_cast<uintptr_t>(file.tellp()); 587 switch (secName) { 588 case ElfSecName::ARK_MODULEINFO: { 589 uint32_t curSecSize = sizeof(ModuleSectionDes::ModuleRegionInfo) * moduleInfo.size(); 590 file.write(reinterpret_cast<char *>(moduleInfo.data()), curSecSize); 591 curSecOffset += curSecSize; 592 curShdr.sh_size = curSecSize; 593 break; 594 } 595 case ElfSecName::TEXT: { 596 uint32_t curSize = curSecOffset; 597 MergeTextSections(file, moduleInfo, curSecOffset); 598 curShdr.sh_size = curSecOffset - curSize; 599 break; 600 } 601 case ElfSecName::ARK_STACKMAP: { 602 uint32_t curSize = curSecOffset; 603 MergeArkStackMapSections(file, moduleInfo, curSecOffset); 604 curShdr.sh_size = curSecOffset - curSize; 605 break; 606 } 607 case ElfSecName::STRTAB: { 608 uint32_t curSize = curSecOffset; 609 MergeStrtabSections(file, moduleInfo, curSecOffset); 610 curShdr.sh_size = curSecOffset - curSize; 611 break; 612 } 613 case ElfSecName::SYMTAB: { 614 FixSymtab(&curShdr); 615 uint32_t curSize = curSecOffset; 616 uint32_t asmSecIndex = GetShIndex(ElfSecName::ARK_ASMSTUB); 617 MergeSymtabSections(file, moduleInfo, curSecOffset, shdr[asmSecIndex].sh_offset); 618 curShdr.sh_size = curSecOffset - curSize; 619 break; 620 } 621 case ElfSecName::SHSTRTAB: 622 case ElfSecName::ARK_FUNCENTRY: 623 case ElfSecName::ARK_ASMSTUB: { 624 uint32_t curSecSize = des_[FullSecIndex].GetSecSize(secName); 625 uint64_t curSecAddr = des_[FullSecIndex].GetSecAddr(secName); 626 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize); 627 curSecOffset += curSecSize; 628 curShdr.sh_size = curSecSize; 629 break; 630 } 631 default: { 632 LOG_ECMA(FATAL) << "this section should not dump to an file"; 633 break; 634 } 635 } 636 if (secName == lastDataSection || secName == lastCodeSection) { 637 curSecOffset = AlignUp(curSecOffset, PageSize()); 638 file.seekp(curSecOffset); 639 } 640 curShdr.sh_entsize = static_cast<uint64_t>(section.Entsize()); 641 sectionToShdr_[secName] = curShdr; 642 LOG_COMPILER(DEBUG) << " shdr[i].sh_entsize " << std::hex << curShdr.sh_entsize << std::endl; 643 ++i; 644 } 645 uint32_t secEnd = static_cast<uint32_t>(file.tellp()); 646 file.seekp(sizeof(llvm::ELF::Elf64_Ehdr)); 647 file.write(reinterpret_cast<char *>(shdr.get()), secNum * sizeof(llvm::ELF::Elf64_Shdr)); 648 file.seekp(secEnd); 649} 650 651unsigned ElfBuilder::GetPFlag(ElfSecName segment) const 652{ 653 return segmentToFlag_.at(segment); 654} 655 656/* 657segment layout as follows: 658An Elf file 659Entry point 0x0 660There are 2 program headers, starting at offset 16384 661 662Program Headers: 663 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align 664 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000f61 0x0000000000001000 R E 0x1000 665 LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000 0x000000000000115e 0x0000000000002000 R 0x1000 666 667 Section to Segment mapping: 668 Segment Sections... 669 00 .text 670 01 .strtab .symtab .shstrtab .ark_funcentry .ark_stackmaps 671------------------------------------------------------------------------------------------------------------------------------ 672Stub Elf file 673Entry point 0x0 674There are 2 program headers, starting at offset 770048 675 676Program Headers: 677 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align 678 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000085020 0x0000000000086000 R E 0x1000 679 LOAD 0x0000000000087000 0x0000000000087000 0x0000000000087000 0x0000000000035bbc 0x0000000000036000 R 0x1000 680 681 Section to Segment mapping: 682 Segment Sections... 683 00 .text .ark_asmstub 684 01 .shstrtab .ark_funcentry .ark_stackmaps .ark_moduleinfo 685*/ 686void ElfBuilder::PackELFSegment(std::ofstream &file) 687{ 688 llvm::ELF::Elf64_Off e_phoff = static_cast<uint64_t>(file.tellp()); 689 long phoff = (long)offsetof(struct llvm::ELF::Elf64_Ehdr, e_phoff); 690 // write Elf32_Off e_phoff 691 file.seekp(phoff); 692 file.write(reinterpret_cast<char *>(&e_phoff), sizeof(e_phoff)); 693 file.seekp(static_cast<long>(e_phoff)); 694 695 int segNum = GetSegmentNum(); 696 auto phdrs = std::make_unique<llvm::ELF::Elf64_Phdr []>(segNum); 697 std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxOffset; 698 std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxAddress; 699 std::set<ElfSecName> segments; 700 // SecName -> addr & size 701 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo(); 702 llvm::ELF::Elf64_Off offset = e_phoff; 703 for (auto &s: sections) { 704 ElfSection section = ElfSection(s.first); 705 if (!section.ShouldDumpToAOTFile()) { 706 continue; 707 } 708 auto it = sectionToSegment_.find(s.first); 709 ASSERT(it != sectionToSegment_.end()); 710 ElfSecName segName = it->second; 711 segments.insert(segName); 712 if (segmentToMaxOffset.find(segName) == segmentToMaxOffset.end()) { 713 segmentToMaxOffset[segName] = 0; 714 } 715 segmentToMaxOffset[segName] = 716 std::max(segmentToMaxOffset[segName], sectionToShdr_[s.first].sh_offset + sectionToShdr_[s.first].sh_size); 717 segmentToMaxAddress[segName] = 718 std::max(segmentToMaxAddress[segName], sectionToShdr_[s.first].sh_addr + sectionToShdr_[s.first].sh_size); 719 offset = std::min(offset, sectionToShdr_[s.first].sh_offset); 720 } 721 int phdrIndex = 0; 722 llvm::ELF::Elf64_Addr addr = offset; 723 for (auto &it: segments) { 724 ElfSecName name = it; 725 phdrs[phdrIndex].p_align = PageSize(); 726 phdrs[phdrIndex].p_type = llvm::ELF::PT_LOAD; 727 phdrs[phdrIndex].p_flags = GetPFlag(name); 728 offset = AlignUp(offset, PageSize()); 729 phdrs[phdrIndex].p_offset = offset; 730 phdrs[phdrIndex].p_vaddr = addr % phdrs[phdrIndex].p_align == 0 ? 731 addr : (addr / phdrs[phdrIndex].p_align + 1) * phdrs[phdrIndex].p_align; 732 phdrs[phdrIndex].p_paddr = phdrs[phdrIndex].p_vaddr; 733 734 phdrs[phdrIndex].p_filesz = segmentToMaxOffset[name] - phdrs[phdrIndex].p_offset; 735 phdrs[phdrIndex].p_memsz = segmentToMaxAddress[name] - phdrs[phdrIndex].p_vaddr; 736 phdrs[phdrIndex].p_memsz = AlignUp(phdrs[phdrIndex].p_memsz, PageSize()); 737 addr = phdrs[phdrIndex].p_vaddr + phdrs[phdrIndex].p_memsz; 738 offset += phdrs[phdrIndex].p_filesz; 739 ++phdrIndex; 740 } 741 file.write(reinterpret_cast<char *>(phdrs.get()), sizeof(llvm::ELF::Elf64_Phdr) * segNum); 742} 743} // namespace panda::ecmascript 744