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_reader.h" 17 18namespace panda::ecmascript { 19bool ElfReader::VerifyELFHeader(uint32_t version, bool strictMatch) 20{ 21 llvm::ELF::Elf64_Ehdr header = *(reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr())); 22 if (header.e_ident[llvm::ELF::EI_MAG0] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0] 23 || header.e_ident[llvm::ELF::EI_MAG1] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1] 24 || header.e_ident[llvm::ELF::EI_MAG2] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2] 25 || header.e_ident[llvm::ELF::EI_MAG3] != llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3]) { 26 LOG_ECMA(ERROR) << "ELF format error, expected magic is " << llvm::ELF::ElfMagic 27 << ", but got " << header.e_ident[llvm::ELF::EI_MAG0] << header.e_ident[llvm::ELF::EI_MAG1] 28 << header.e_ident[llvm::ELF::EI_MAG2] << header.e_ident[llvm::ELF::EI_MAG3]; 29 return false; 30 } 31 if (!base::FileHeaderBase::VerifyVersion("Elf", header.e_version, version, strictMatch)) { 32 return false; 33 } 34 if (ElfChecker(fileMapMem_).CheckValidElf() == false) { 35 LOG_ECMA(ERROR) << "ELF file content is not valid"; 36 return false; 37 } 38 return true; 39} 40 41ModuleSectionDes::ModuleRegionInfo *ElfReader::GetCurModuleInfo(uint32_t i, llvm::ELF::Elf64_Off offset) 42{ 43 uint64_t codeAddress = reinterpret_cast<uint64_t>(fileMapMem_.GetOriginAddr()); 44 uint64_t info = codeAddress + offset + i * sizeof(ModuleSectionDes::ModuleRegionInfo); 45 return reinterpret_cast<ModuleSectionDes::ModuleRegionInfo *>(info); 46} 47 48void ElfReader::ParseELFSections(ModuleSectionDes &des, std::vector<ElfSecName> &secs) 49{ 50 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr()); 51 char *addr = reinterpret_cast<char *>(ehdr); 52 llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff); 53 ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1)); 54 llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx]; 55 for (size_t j = 0; j < secs.size(); ++j) { 56 int secId = -1; 57 ElfSecName sec = secs[j]; 58 std::string sectionName = ModuleSectionDes::GetSecName(sec); 59 for (size_t i = 0; i < ehdr->e_shnum; ++i) { 60 llvm::ELF::Elf64_Word shName = shdr[i].sh_name; 61 char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset; 62 if (sectionName.compare(curShName) == 0) { 63 secId = static_cast<int>(i); 64 break; 65 } 66 } 67 if (secId == -1) { 68 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab"; 69 continue; 70 } 71 ASSERT(secId > 0 && secId < ehdr->e_shnum); 72 llvm::ELF::Elf64_Shdr secShdr = shdr[secId]; 73 uintptr_t secAddr = reinterpret_cast<uintptr_t>(addr + secShdr.sh_offset); 74 uint32_t secSize = secShdr.sh_size; 75 if (sec == ElfSecName::ARK_FUNCENTRY) { 76 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0)); 77 } 78 if (sec == ElfSecName::ARK_STACKMAP) { 79 des.SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr)); 80 des.SetArkStackMapSize(secSize); 81 } else { 82 des.SetSecAddrAndSize(sec, secAddr, secSize); 83 } 84 } 85} 86 87void ElfReader::ParseELFSections(std::vector<ModuleSectionDes> &des, std::vector<ElfSecName> &secs) 88{ 89 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr()); 90 char *addr = reinterpret_cast<char *>(ehdr); 91 llvm::ELF::Elf64_Shdr *shdrs = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff); 92 ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1)); 93 llvm::ELF::Elf64_Shdr strdr = shdrs[ehdr->e_shstrndx]; 94 ASSERT(ehdr->e_flags != static_cast<llvm::ELF::Elf64_Word>(-1)); 95 llvm::ELF::Elf64_Shdr moduledr = shdrs[ehdr->e_flags]; 96 size_t moduleInfoSize = moduledr.sh_size; 97 uint32_t moduleNum = GetModuleNum(moduleInfoSize); 98 des.resize(moduleNum); 99 std::set<ElfSecName> secSet(secs.begin(), secs.end()); 100 for (ElfSecName sec : secSet) { 101 int secId = -1; 102 std::string sectionName = ModuleSectionDes::GetSecName(sec); 103 for (size_t i = 0; i < ehdr->e_shnum; ++i) { 104 llvm::ELF::Elf64_Word shName = shdrs[i].sh_name; 105 char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset; 106 if (sectionName.compare(curShName) == 0) { 107 secId = static_cast<int>(i); 108 break; 109 } 110 } 111 if (secId == -1) { 112 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab"; 113 continue; 114 } 115 ASSERT(secId > 0 && secId < ehdr->e_shnum); 116 llvm::ELF::Elf64_Shdr secShdr = shdrs[secId]; 117 uintptr_t secAddr = reinterpret_cast<uintptr_t>(addr + secShdr.sh_offset); 118 uint32_t secSize = secShdr.sh_size; 119 switch (sec) { 120 case ElfSecName::TEXT: { 121 llvm::ELF::Elf64_Off secOffset = 0; 122 SeparateTextSections(des, secAddr, secOffset, moduledr.sh_offset); 123 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 124 break; 125 } 126 case ElfSecName::ARK_STACKMAP: { 127 llvm::ELF::Elf64_Off secOffset = 0; 128 SeparateArkStackMapSections(des, secAddr, secOffset, moduledr.sh_offset); 129 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 130 break; 131 } 132 case ElfSecName::STRTAB: { 133 llvm::ELF::Elf64_Off secOffset = 0; 134 SeparateStrtabSections(des, secAddr, secOffset, moduledr.sh_offset); 135 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 136 break; 137 } 138 case ElfSecName::SYMTAB: { 139 llvm::ELF::Elf64_Off secOffset = 0; 140 SeparateSymtabSections(des, secAddr, secOffset, moduledr.sh_offset); 141 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 142 break; 143 } 144 case ElfSecName::SHSTRTAB: 145 case ElfSecName::ARK_FUNCENTRY: 146 case ElfSecName::ARK_ASMSTUB: 147 case ElfSecName::ARK_MODULEINFO: { 148 if (sec == ElfSecName::ARK_FUNCENTRY) { 149 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0)); 150 } 151 des[0].SetSecAddrAndSize(sec, secAddr, secSize); 152 break; 153 } 154 default: { 155 LOG_ECMA(FATAL) << "this section should not dump to stub file"; 156 break; 157 } 158 } 159 } 160} 161 162void ElfReader::ParseELFSections(BinaryBufferParser &parser, 163 std::vector<ModuleSectionDes> &des, 164 std::vector<ElfSecName> &secs) 165{ 166 ASSERT(des.size() == ASMSTUB_MODULE_NUM); 167 uint64_t codeAddress = reinterpret_cast<uint64_t>(stubsMem_.addr_); 168 llvm::ELF::Elf64_Ehdr ehdr; 169 parser.ParseBuffer(&ehdr, sizeof(ehdr), 0); 170 std::vector<llvm::ELF::Elf64_Shdr> shdrs(ehdr.e_shnum); 171 parser.ParseBuffer(shdrs.data(), sizeof(llvm::ELF::Elf64_Shdr) * ehdr.e_shnum, ehdr.e_shoff); 172 173 ASSERT(ehdr.e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1)); 174 llvm::ELF::Elf64_Shdr strdr = shdrs[ehdr.e_shstrndx]; 175 ASSERT(ehdr.e_flags != static_cast<llvm::ELF::Elf64_Word>(-1)); 176 llvm::ELF::Elf64_Shdr moduledr = shdrs[ehdr.e_flags]; 177 [[maybe_unused]] size_t moduleInfoSize = moduledr.sh_size; 178 uint32_t moduleNum = GetModuleNum(moduleInfoSize); 179 ASSERT(moduleNum == ASMSTUB_MODULE_NUM); 180 moduleInfo_.resize(moduleNum); 181 parser.ParseBuffer(moduleInfo_.data(), moduleInfoSize, moduledr.sh_offset); 182 std::set<ElfSecName> secSet(secs.begin(), secs.end()); 183 for (ElfSecName sec : secSet) { 184 int secId = -1; 185 std::string sectionName = ModuleSectionDes::GetSecName(sec); 186 for (size_t i = 0; i < ehdr.e_shnum; ++i) { 187 llvm::ELF::Elf64_Word shName = shdrs[i].sh_name; 188 char *curShName = reinterpret_cast<char *>(parser.GetAddr()) + shName + strdr.sh_offset; 189 if (sectionName.compare(curShName) == 0) { 190 secId = static_cast<int>(i); 191 break; 192 } 193 } 194 if (secId == -1) { 195 LOG_COMPILER(DEBUG) << "sectionName: " << sectionName << " not found in strtab"; 196 continue; 197 } 198 ASSERT(secId > 0 && secId < ehdr.e_shnum); 199 llvm::ELF::Elf64_Shdr secShdr = shdrs[secId]; 200 uint64_t secAddr = static_cast<uint64_t>(codeAddress + secShdr.sh_offset); 201 uint32_t secSize = secShdr.sh_size; 202 switch (sec) { 203 case ElfSecName::TEXT: { 204 llvm::ELF::Elf64_Off secOffset = 0; 205 SeparateTextSections(parser, des, secAddr, secOffset, secShdr.sh_offset); 206 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 207 break; 208 } 209 case ElfSecName::ARK_STACKMAP: { 210 llvm::ELF::Elf64_Off secOffset = 0; 211 SeparateArkStackMapSections(parser, des, secAddr, secOffset, secShdr.sh_offset); 212 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 213 break; 214 } 215 case ElfSecName::STRTAB: { 216 llvm::ELF::Elf64_Off secOffset = 0; 217 SeparateStrtabSections(parser, des, secAddr, secOffset, secShdr.sh_offset); 218 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 219 break; 220 } 221 case ElfSecName::SYMTAB: { 222 llvm::ELF::Elf64_Off secOffset = 0; 223 SeparateSymtabSections(parser, des, secAddr, secOffset, secShdr.sh_offset); 224 ASSERT(static_cast<uint32_t>(secOffset) == secSize); 225 break; 226 } 227 case ElfSecName::SHSTRTAB: 228 case ElfSecName::ARK_FUNCENTRY: 229 case ElfSecName::ARK_ASMSTUB: 230 case ElfSecName::ARK_MODULEINFO: { 231 if (sec == ElfSecName::ARK_FUNCENTRY) { 232 ASSERT((secSize > 0) && (secSize % sizeof(AOTFileInfo::FuncEntryDes) == 0)); 233 } 234 parser.ParseBuffer(reinterpret_cast<void *>(secAddr), secSize, secShdr.sh_offset); 235 des[0].SetSecAddrAndSize(sec, secAddr, secSize); 236 break; 237 } 238 default: { 239 LOG_ECMA(FATAL) << "this section should not dump to stub file"; 240 break; 241 } 242 } 243 } 244} 245 246bool ElfReader::ParseELFSegment() 247{ 248 if (fileMapMem_.GetOriginAddr() == nullptr) { 249 return false; 250 } 251 char *addr = reinterpret_cast<char *>(fileMapMem_.GetOriginAddr()); 252 llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMapMem_.GetOriginAddr()); 253 llvm::ELF::Elf64_Phdr *phdr = reinterpret_cast<llvm::ELF::Elf64_Phdr *>(addr + ehdr->e_phoff); 254 for (int i = 0; i < ehdr->e_phnum; ++i) { 255 if (phdr[i].p_type != llvm::ELF::PT_LOAD) { 256 continue; 257 } 258 if (phdr[i].p_filesz > phdr[i].p_memsz) { 259 LOG_COMPILER(ERROR) << " p_filesz:0x" << std::hex << phdr[i].p_filesz << " > p_memsz:0x" 260 << phdr[i].p_memsz; 261 return false; 262 } 263 if (!phdr[i].p_filesz) { 264 continue; 265 } 266 unsigned char *virtualAddr = reinterpret_cast<unsigned char *>(addr + phdr[i].p_vaddr); 267 ASSERT(phdr[i].p_offset % PageSize() == 0); 268 if ((phdr[i].p_flags & llvm::ELF::PF_X) != 0) { 269 ASSERT(reinterpret_cast<uintptr_t>(virtualAddr) % PageSize() == 0); 270 if (!PageProtect(virtualAddr, phdr[i].p_memsz, PAGE_PROT_EXEC_READ)) { 271 return false; 272 } 273 } 274 } 275 return true; 276} 277 278void ElfReader::SeparateTextSections(std::vector<ModuleSectionDes> &des, 279 const uintptr_t &secAddr, 280 llvm::ELF::Elf64_Off &secOffset, 281 const llvm::ELF::Elf64_Off &moduleInfoOffset) 282{ 283 for (size_t i = 0; i < des.size(); ++i) { 284 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset); 285 secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN); 286 uint32_t rodataSizeBeforeText = moduleInfo->rodataSizeBeforeText; 287 uint32_t rodataSizeAfterText = moduleInfo->rodataSizeAfterText; 288 if (rodataSizeBeforeText != 0) { 289 secOffset += rodataSizeBeforeText; 290 secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN); 291 } 292 uint32_t textSize = moduleInfo->textSize; 293 des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize); 294 secOffset += textSize; 295 if (rodataSizeAfterText != 0) { 296 secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN); 297 secOffset += rodataSizeAfterText; 298 } 299 } 300} 301 302void ElfReader::SeparateArkStackMapSections(std::vector<ModuleSectionDes> &des, 303 const uintptr_t &secAddr, 304 llvm::ELF::Elf64_Off &secOffset, 305 const llvm::ELF::Elf64_Off &moduleInfoOffset) 306{ 307 for (size_t i = 0; i < des.size(); ++i) { 308 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset); 309 uint32_t stackMapSize = moduleInfo->stackMapSize; 310 des[i].SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr + secOffset)); 311 des[i].SetArkStackMapSize(stackMapSize); 312 uint32_t index = moduleInfo->startIndex; 313 uint32_t cnt = moduleInfo->funcCount; 314 des[i].SetStartIndex(index); 315 des[i].SetFuncCount(cnt); 316 secOffset += stackMapSize; 317 } 318} 319 320void ElfReader::SeparateStrtabSections(std::vector<ModuleSectionDes> &des, 321 const uintptr_t &secAddr, 322 llvm::ELF::Elf64_Off &secOffset, 323 const llvm::ELF::Elf64_Off &moduleInfoOffset) 324{ 325 for (size_t i = 0; i < des.size(); ++i) { 326 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset); 327 uint32_t strtabSize = moduleInfo->strtabSize; 328 des[i].SetSecAddrAndSize(ElfSecName::STRTAB, secAddr + secOffset, strtabSize); 329 secOffset += strtabSize; 330 } 331} 332 333void ElfReader::SeparateSymtabSections(std::vector<ModuleSectionDes> &des, 334 const uintptr_t &secAddr, 335 llvm::ELF::Elf64_Off &secOffset, 336 const llvm::ELF::Elf64_Off &moduleInfoOffset) 337{ 338 for (size_t i = 0; i < des.size(); ++i) { 339 auto moduleInfo = GetCurModuleInfo(i, moduleInfoOffset); 340 uint32_t symtabSize = moduleInfo->symtabSize; 341 des[i].SetSecAddrAndSize(ElfSecName::SYMTAB, secAddr + secOffset, symtabSize); 342 secOffset += symtabSize; 343 } 344} 345 346void ElfReader::SeparateTextSections(BinaryBufferParser &parser, 347 std::vector<ModuleSectionDes> &des, 348 const uint64_t &secAddr, 349 llvm::ELF::Elf64_Off &secOffset, 350 const llvm::ELF::Elf64_Off &curShOffset) 351{ 352 for (size_t i = 0; i < des.size(); ++i) { 353 auto moduleInfo = moduleInfo_[i]; 354 secOffset = AlignUp(secOffset, AOTFileInfo::PAGE_ALIGN); 355 uint32_t rodataSizeBeforeText = moduleInfo.rodataSizeBeforeText; 356 uint32_t rodataSizeAfterText = moduleInfo.rodataSizeAfterText; 357 if (rodataSizeBeforeText != 0) { 358 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSizeBeforeText, 359 curShOffset + secOffset); 360 secOffset += rodataSizeBeforeText; 361 secOffset = AlignUp(secOffset, AOTFileInfo::TEXT_SEC_ALIGN); 362 } 363 uint32_t textSize = moduleInfo.textSize; 364 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), textSize, curShOffset + secOffset); 365 des[i].SetSecAddrAndSize(ElfSecName::TEXT, secAddr + secOffset, textSize); 366 secOffset += textSize; 367 if (rodataSizeAfterText != 0) { 368 secOffset = AlignUp(secOffset, AOTFileInfo::DATA_SEC_ALIGN); 369 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), rodataSizeAfterText, 370 curShOffset + secOffset); 371 secOffset += rodataSizeAfterText; 372 } 373 } 374} 375 376void ElfReader::SeparateArkStackMapSections(BinaryBufferParser &parser, 377 std::vector<ModuleSectionDes> &des, 378 const uint64_t &secAddr, 379 llvm::ELF::Elf64_Off &secOffset, 380 const llvm::ELF::Elf64_Off &curShOffset) 381{ 382 for (size_t i = 0; i < des.size(); ++i) { 383 auto moduleInfo = moduleInfo_[i]; 384 uint32_t stackMapSize = moduleInfo.stackMapSize; 385 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), stackMapSize, curShOffset + secOffset); 386 des[i].SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secAddr + secOffset)); 387 des[i].SetArkStackMapSize(stackMapSize); 388 uint32_t index = moduleInfo.startIndex; 389 uint32_t cnt = moduleInfo.funcCount; 390 des[i].SetStartIndex(index); 391 des[i].SetFuncCount(cnt); 392 secOffset += stackMapSize; 393 } 394} 395 396void ElfReader::SeparateStrtabSections(BinaryBufferParser &parser, 397 std::vector<ModuleSectionDes> &des, 398 const uintptr_t &secAddr, 399 llvm::ELF::Elf64_Off &secOffset, 400 const llvm::ELF::Elf64_Off &curShOffset) 401{ 402 for (size_t i = 0; i < des.size(); ++i) { 403 auto moduleInfo = moduleInfo_[i]; 404 uint32_t strtabSize = moduleInfo.strtabSize; 405 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), strtabSize, curShOffset + secOffset); 406 des[i].SetSecAddrAndSize(ElfSecName::STRTAB, secAddr + secOffset, strtabSize); 407 secOffset += strtabSize; 408 } 409} 410 411void ElfReader::SeparateSymtabSections(BinaryBufferParser &parser, 412 std::vector<ModuleSectionDes> &des, 413 const uintptr_t &secAddr, 414 llvm::ELF::Elf64_Off &secOffset, 415 const llvm::ELF::Elf64_Off &curShOffset) 416{ 417 for (size_t i = 0; i < des.size(); ++i) { 418 auto moduleInfo = moduleInfo_[i]; 419 uint32_t symtabSize = moduleInfo.symtabSize; 420 parser.ParseBuffer(reinterpret_cast<void *>(secAddr + secOffset), symtabSize, curShOffset + secOffset); 421 des[i].SetSecAddrAndSize(ElfSecName::SYMTAB, secAddr + secOffset, symtabSize); 422 secOffset += symtabSize; 423 } 424} 425} // namespace panda::ecmascript 426