14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_file/elf_checker.h" 164514f5e3Sopenharmony_ci#include <fstream> 174514f5e3Sopenharmony_ci#include <type_traits> 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_cinamespace panda::ecmascript { 204514f5e3Sopenharmony_ci/* Check Aligned */ 214514f5e3Sopenharmony_citemplate <typename AlignType> static bool CheckAlign(void* alignPtr, size_t offset = 0) 224514f5e3Sopenharmony_ci{ 234514f5e3Sopenharmony_ci if (ALLOW_UNALIGNED != 0) { 244514f5e3Sopenharmony_ci return true; 254514f5e3Sopenharmony_ci } 264514f5e3Sopenharmony_ci size_t ptrPos = reinterpret_cast<size_t>(alignPtr) + offset; 274514f5e3Sopenharmony_ci if ((ptrPos & (alignof(AlignType) - 1)) == 0) { 284514f5e3Sopenharmony_ci return true; 294514f5e3Sopenharmony_ci } else { 304514f5e3Sopenharmony_ci return false; 314514f5e3Sopenharmony_ci } 324514f5e3Sopenharmony_ci} 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_ci/* Swap LSB and MSB */ 354514f5e3Sopenharmony_citemplate <typename IntType> static void ByteSwap(IntType& x) 364514f5e3Sopenharmony_ci{ 374514f5e3Sopenharmony_ci static constexpr unsigned int iByteMuskOff0 = 0xffu; 384514f5e3Sopenharmony_ci static constexpr unsigned int iByteMuskOff1 = iByteMuskOff0 << 8; 394514f5e3Sopenharmony_ci static constexpr unsigned int iByteMuskOff2 = iByteMuskOff1 << 8; 404514f5e3Sopenharmony_ci static constexpr unsigned int iByteMuskOff3 = iByteMuskOff2 << 8; 414514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff0 = 0xffuLL; 424514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff1 = llByteMuskOff0 << 8; 434514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff2 = llByteMuskOff1 << 8; 444514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff3 = llByteMuskOff2 << 8; 454514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff4 = llByteMuskOff3 << 8; 464514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff5 = llByteMuskOff4 << 8; 474514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff6 = llByteMuskOff5 << 8; 484514f5e3Sopenharmony_ci static constexpr unsigned long long llByteMuskOff7 = llByteMuskOff6 << 8; 494514f5e3Sopenharmony_ci static constexpr unsigned int move1 = 8; // 8: move 8 bits 504514f5e3Sopenharmony_ci static constexpr unsigned int move2 = move1 + 8 * 2; // 8: skip one pair 514514f5e3Sopenharmony_ci static constexpr unsigned int move3 = move2 + 8 * 2; // 8: skip another pair 524514f5e3Sopenharmony_ci static constexpr unsigned int move4 = move3 + 8 * 2; // 8: skip another pair 534514f5e3Sopenharmony_ci switch (sizeof(IntType)) { 544514f5e3Sopenharmony_ci case sizeof(int8_t): 554514f5e3Sopenharmony_ci return; 564514f5e3Sopenharmony_ci case sizeof(int16_t): 574514f5e3Sopenharmony_ci x = IntType((((x) >> move1) & iByteMuskOff0) | 584514f5e3Sopenharmony_ci (((x) & iByteMuskOff0) << move1)); // 8: position to change between LSB and MSB 594514f5e3Sopenharmony_ci return; 604514f5e3Sopenharmony_ci case sizeof(int32_t): 614514f5e3Sopenharmony_ci x = ((((x) & iByteMuskOff3) >> move2) | (((x) & iByteMuskOff2) >> move1) | 624514f5e3Sopenharmony_ci (((x) & iByteMuskOff1) << move1) | (((x) & iByteMuskOff0) << move2)); 634514f5e3Sopenharmony_ci return; 644514f5e3Sopenharmony_ci case sizeof(int64_t): 654514f5e3Sopenharmony_ci x = ((((x) & llByteMuskOff7) >> move4) | (((x) & llByteMuskOff6) >> move3) | 664514f5e3Sopenharmony_ci (((x) & llByteMuskOff5) >> move2) | (((x) & llByteMuskOff4) >> move1) | 674514f5e3Sopenharmony_ci (((x) & llByteMuskOff3) << move1) | (((x) & llByteMuskOff2) << move2) | 684514f5e3Sopenharmony_ci (((x) & llByteMuskOff1) << move3) | (((x) & llByteMuskOff0) << move4)); 694514f5e3Sopenharmony_ci return; 704514f5e3Sopenharmony_ci default: 714514f5e3Sopenharmony_ci return; 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci} 744514f5e3Sopenharmony_ci 754514f5e3Sopenharmony_ci/* This function requires copying memory. Avoid using it if MemMap is avalible. */ 764514f5e3Sopenharmony_ciElfChecker::ElfChecker(const void* data, int len) : elfLen_(len), elfErrorCode_(0), fromMmap_(false) 774514f5e3Sopenharmony_ci{ 784514f5e3Sopenharmony_ci if (len <= 0 || data == nullptr) { 794514f5e3Sopenharmony_ci elfData_ = nullptr; 804514f5e3Sopenharmony_ci return; 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci elfData_ = new char[len]; 834514f5e3Sopenharmony_ci if (memcpy_s(elfData_, len, data, len) != 0) { 844514f5e3Sopenharmony_ci delete[] elfData_; 854514f5e3Sopenharmony_ci elfData_ = nullptr; 864514f5e3Sopenharmony_ci return; 874514f5e3Sopenharmony_ci } 884514f5e3Sopenharmony_ci} 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ciElfChecker::ElfChecker(const std::string& path) : elfErrorCode_(0), fromMmap_(false) 914514f5e3Sopenharmony_ci{ 924514f5e3Sopenharmony_ci if (!panda::ecmascript::FileExist(path.c_str())) { 934514f5e3Sopenharmony_ci elfData_ = nullptr; 944514f5e3Sopenharmony_ci elfLen_ = 0; 954514f5e3Sopenharmony_ci return; 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci std::ifstream file(path, std::ios::binary | std::ios::ate); 984514f5e3Sopenharmony_ci if (file.is_open() == false) { 994514f5e3Sopenharmony_ci elfData_ = nullptr; 1004514f5e3Sopenharmony_ci elfLen_ = 0; 1014514f5e3Sopenharmony_ci return; 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci elfLen_ = static_cast<size_t>(file.tellg()); 1044514f5e3Sopenharmony_ci file.seekg(0, std::ios::beg); 1054514f5e3Sopenharmony_ci if (elfLen_ <= 0) { 1064514f5e3Sopenharmony_ci elfData_ = nullptr; 1074514f5e3Sopenharmony_ci return; 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci elfData_ = new char[elfLen_]; 1104514f5e3Sopenharmony_ci file.read(elfData_, elfLen_); 1114514f5e3Sopenharmony_ci return; 1124514f5e3Sopenharmony_ci} 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ciElfChecker::ElfChecker(const MemMap& mem) : elfErrorCode_(0), fromMmap_(true) 1154514f5e3Sopenharmony_ci{ 1164514f5e3Sopenharmony_ci elfData_ = reinterpret_cast<char*>(mem.GetMem()); 1174514f5e3Sopenharmony_ci elfLen_ = mem.GetSize(); 1184514f5e3Sopenharmony_ci if (elfLen_ == 0) { 1194514f5e3Sopenharmony_ci elfData_ = nullptr; 1204514f5e3Sopenharmony_ci } 1214514f5e3Sopenharmony_ci} 1224514f5e3Sopenharmony_ci 1234514f5e3Sopenharmony_cibool ElfChecker::CheckValidElf() 1244514f5e3Sopenharmony_ci{ 1254514f5e3Sopenharmony_ci if (elfData_ == nullptr || elfLen_ <= 0) { 1264514f5e3Sopenharmony_ci return false; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci Elf* elf = ElfMemory(elfData_, elfLen_); 1294514f5e3Sopenharmony_ci if (elf == nullptr || elf->kind == ELF_KIND_NONE || CheckIfError() == false) { 1304514f5e3Sopenharmony_ci ElfRelease(elf); 1314514f5e3Sopenharmony_ci return false; 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci int release_num = ElfRelease(elf); 1344514f5e3Sopenharmony_ci if (release_num != 0 || CheckIfError() == false) { 1354514f5e3Sopenharmony_ci return false; 1364514f5e3Sopenharmony_ci } 1374514f5e3Sopenharmony_ci return true; 1384514f5e3Sopenharmony_ci} 1394514f5e3Sopenharmony_ci 1404514f5e3Sopenharmony_ciint ElfChecker::CheckIfError() const 1414514f5e3Sopenharmony_ci{ 1424514f5e3Sopenharmony_ci if (elfErrorCode_ != ELF_ERR_NOERROR) { 1434514f5e3Sopenharmony_ci return false; 1444514f5e3Sopenharmony_ci } 1454514f5e3Sopenharmony_ci return true; 1464514f5e3Sopenharmony_ci} 1474514f5e3Sopenharmony_ci 1484514f5e3Sopenharmony_civoid ElfChecker::SetErrorCode(int value) 1494514f5e3Sopenharmony_ci{ 1504514f5e3Sopenharmony_ci if (value >= 0 && value < ELF_ERR_NUM) { 1514514f5e3Sopenharmony_ci elfErrorCode_ = value; 1524514f5e3Sopenharmony_ci } else { 1534514f5e3Sopenharmony_ci elfErrorCode_ = ELF_ERR_UNKNOWN_ERROR; 1544514f5e3Sopenharmony_ci } 1554514f5e3Sopenharmony_ci} 1564514f5e3Sopenharmony_ci 1574514f5e3Sopenharmony_ciElfChecker::Elf* ElfChecker::ElfAllocate( 1584514f5e3Sopenharmony_ci void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent, ElfKind kind, size_t extra) 1594514f5e3Sopenharmony_ci{ 1604514f5e3Sopenharmony_ci size_t alloc_size = sizeof(Elf) + extra; 1614514f5e3Sopenharmony_ci Elf* result = reinterpret_cast<Elf*>(new char[alloc_size]()); 1624514f5e3Sopenharmony_ci if (result == nullptr) { 1634514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_NOMEM); 1644514f5e3Sopenharmony_ci } else { 1654514f5e3Sopenharmony_ci result->kind = kind; 1664514f5e3Sopenharmony_ci result->refCount = 1; 1674514f5e3Sopenharmony_ci result->cmd = cmd; 1684514f5e3Sopenharmony_ci result->startOffset = offset; 1694514f5e3Sopenharmony_ci result->maxSize = maxsize; 1704514f5e3Sopenharmony_ci result->mapAddress = mapAddress; 1714514f5e3Sopenharmony_ci result->parent = parent; 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci return result; 1754514f5e3Sopenharmony_ci} 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ciElfChecker::ElfKind ElfChecker::GetElfKind(void* buf) const 1784514f5e3Sopenharmony_ci{ 1794514f5e3Sopenharmony_ci /* Could be an ELF file. */ 1804514f5e3Sopenharmony_ci int eclass = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_CLASS]; 1814514f5e3Sopenharmony_ci int data = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_DATA]; 1824514f5e3Sopenharmony_ci int version = (int)(reinterpret_cast<unsigned char*>(buf))[llvm::ELF::EI_VERSION]; 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci if (eclass > llvm::ELF::ELFCLASSNONE && eclass <= llvm::ELF::ELFCLASS64 && data > llvm::ELF::ELFDATANONE && 1854514f5e3Sopenharmony_ci data <= llvm::ELF::ELFDATA2MSB && version == llvm::ELF::EV_CURRENT) { 1864514f5e3Sopenharmony_ci return ELF_KIND_ELF; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci /* We do not know this file type. */ 1904514f5e3Sopenharmony_ci return ELF_KIND_NONE; 1914514f5e3Sopenharmony_ci} 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci/* Get the number of sections from the ELF header. */ 1944514f5e3Sopenharmony_citemplate <typename FromElfHeader, typename FromElfSectionHeader, typename SizeType> 1954514f5e3Sopenharmony_cisize_t ElfChecker::GetSectionHeaderNum( 1964514f5e3Sopenharmony_ci FromElfHeader* ehdr, size_t maxsize, unsigned char* eIdent, void* mapAddress, int64_t offset) 1974514f5e3Sopenharmony_ci{ 1984514f5e3Sopenharmony_ci size_t result = ehdr->e_shnum; 1994514f5e3Sopenharmony_ci if (SECUREC_UNLIKELY(result == 0) && ehdr->e_shoff != 0) { 2004514f5e3Sopenharmony_ci if (SECUREC_UNLIKELY(ehdr->e_shoff >= maxsize) || 2014514f5e3Sopenharmony_ci SECUREC_UNLIKELY(maxsize - ehdr->e_shoff < sizeof(FromElfSectionHeader))) { 2024514f5e3Sopenharmony_ci return 0; 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci SizeType size; 2054514f5e3Sopenharmony_ci FromElfSectionHeader* dest = 2064514f5e3Sopenharmony_ci reinterpret_cast<FromElfSectionHeader*>(reinterpret_cast<char*>(mapAddress) + ehdr->e_shoff + offset); 2074514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && CheckAlign<FromElfSectionHeader>(dest) == true) { 2084514f5e3Sopenharmony_ci /* We can directly access the memory. */ 2094514f5e3Sopenharmony_ci size = dest->sh_size; 2104514f5e3Sopenharmony_ci } else { 2114514f5e3Sopenharmony_ci char* memSrc = 2124514f5e3Sopenharmony_ci reinterpret_cast<char*>(mapAddress) + ehdr->e_shoff + offset + offsetof(FromElfSectionHeader, sh_size); 2134514f5e3Sopenharmony_ci if (memcpy_s(&size, sizeof(size), memSrc, sizeof(SizeType)) != 0) { 2144514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_NOMEM); 2154514f5e3Sopenharmony_ci return 0; 2164514f5e3Sopenharmony_ci } 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) { 2194514f5e3Sopenharmony_ci ByteSwap(size); 2204514f5e3Sopenharmony_ci } 2214514f5e3Sopenharmony_ci if (size > ~((llvm::ELF::Elf64_Word)0)) { 2224514f5e3Sopenharmony_ci /* Invalid value, it is too large. */ 2234514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 2244514f5e3Sopenharmony_ci return 0; 2254514f5e3Sopenharmony_ci } 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci result = size; 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci 2304514f5e3Sopenharmony_ci /* If the section headers were truncated, pretend none were there. 2314514f5e3Sopenharmony_ci */ 2324514f5e3Sopenharmony_ci if (ehdr->e_shoff > maxsize || maxsize - ehdr->e_shoff < sizeof(FromElfSectionHeader) * result) { 2334514f5e3Sopenharmony_ci result = 0; 2344514f5e3Sopenharmony_ci } 2354514f5e3Sopenharmony_ci return result; 2364514f5e3Sopenharmony_ci} 2374514f5e3Sopenharmony_ci 2384514f5e3Sopenharmony_ci/* Get Section Header Number */ 2394514f5e3Sopenharmony_cisize_t ElfChecker::GetShnum(void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxsize) 2404514f5e3Sopenharmony_ci{ 2414514f5e3Sopenharmony_ci union { 2424514f5e3Sopenharmony_ci llvm::ELF::Elf32_Ehdr* e32; 2434514f5e3Sopenharmony_ci llvm::ELF::Elf64_Ehdr* e64; 2444514f5e3Sopenharmony_ci void* p; 2454514f5e3Sopenharmony_ci } ehdrPtr; 2464514f5e3Sopenharmony_ci union { 2474514f5e3Sopenharmony_ci llvm::ELF::Elf32_Ehdr e32; 2484514f5e3Sopenharmony_ci llvm::ELF::Elf64_Ehdr e64; 2494514f5e3Sopenharmony_ci } ehdrMem; 2504514f5e3Sopenharmony_ci bool is32 = eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32; 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_ci if ((is32 && maxsize < sizeof(llvm::ELF::Elf32_Ehdr)) || (!is32 && maxsize < sizeof(llvm::ELF::Elf64_Ehdr))) { 2534514f5e3Sopenharmony_ci /* Not long enough */ 2544514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 2554514f5e3Sopenharmony_ci return 0; 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci /* Make the ELF header available. */ 2584514f5e3Sopenharmony_ci bool isAligned = (is32 ? CheckAlign<llvm::ELF::Elf32_Ehdr>(eIdent) : CheckAlign<llvm::ELF::Elf64_Ehdr>(eIdent)); 2594514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && isAligned) { 2604514f5e3Sopenharmony_ci ehdrPtr.p = eIdent; 2614514f5e3Sopenharmony_ci } else { 2624514f5e3Sopenharmony_ci ehdrPtr.p = &ehdrMem; 2634514f5e3Sopenharmony_ci if (is32) { 2644514f5e3Sopenharmony_ci if (ALLOW_UNALIGNED) { 2654514f5e3Sopenharmony_ci ehdrMem.e32.e_shnum = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(eIdent)->e_shnum; 2664514f5e3Sopenharmony_ci ehdrMem.e32.e_shoff = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(eIdent)->e_shoff; 2674514f5e3Sopenharmony_ci } else { 2684514f5e3Sopenharmony_ci if (memcpy_s(&ehdrMem, sizeof(ehdrMem), eIdent, sizeof(llvm::ELF::Elf32_Ehdr)) != 0) { 2694514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_NOMEM); 2704514f5e3Sopenharmony_ci return 0; 2714514f5e3Sopenharmony_ci }; 2724514f5e3Sopenharmony_ci } 2734514f5e3Sopenharmony_ci 2744514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) { 2754514f5e3Sopenharmony_ci ByteSwap(ehdrMem.e32.e_shnum); 2764514f5e3Sopenharmony_ci ByteSwap(ehdrMem.e32.e_shoff); 2774514f5e3Sopenharmony_ci } 2784514f5e3Sopenharmony_ci } else { 2794514f5e3Sopenharmony_ci if (ALLOW_UNALIGNED) { 2804514f5e3Sopenharmony_ci ehdrMem.e64.e_shnum = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(eIdent)->e_shnum; 2814514f5e3Sopenharmony_ci ehdrMem.e64.e_shoff = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(eIdent)->e_shoff; 2824514f5e3Sopenharmony_ci } else { 2834514f5e3Sopenharmony_ci if (memcpy_s(&ehdrMem, sizeof(ehdrMem), eIdent, sizeof(llvm::ELF::Elf64_Ehdr)) != 0) { 2844514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_NOMEM); 2854514f5e3Sopenharmony_ci return 0; 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci }; 2884514f5e3Sopenharmony_ci 2894514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) { 2904514f5e3Sopenharmony_ci ByteSwap(ehdrMem.e64.e_shnum); 2914514f5e3Sopenharmony_ci ByteSwap(ehdrMem.e64.e_shoff); 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci } 2944514f5e3Sopenharmony_ci } 2954514f5e3Sopenharmony_ci if (is32) { 2964514f5e3Sopenharmony_ci return GetSectionHeaderNum<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Shdr, llvm::ELF::Elf32_Word>( 2974514f5e3Sopenharmony_ci ehdrPtr.e32, maxsize, eIdent, mapAddress, offset); 2984514f5e3Sopenharmony_ci } else { 2994514f5e3Sopenharmony_ci return GetSectionHeaderNum<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Shdr, llvm::ELF::Elf64_Xword>( 3004514f5e3Sopenharmony_ci ehdrPtr.e64, maxsize, eIdent, mapAddress, offset); 3014514f5e3Sopenharmony_ci } 3024514f5e3Sopenharmony_ci} 3034514f5e3Sopenharmony_ci 3044514f5e3Sopenharmony_ci/* Get Details from mapAddress, */ 3054514f5e3Sopenharmony_citemplate <typename ElfEhdr, typename ElfShdr, typename ElfItemField> 3064514f5e3Sopenharmony_ciElfChecker::Elf* ElfChecker::GetElfItem(ElfItemField& elfItemField, void* mapAddress, unsigned char* eIdent, 3074514f5e3Sopenharmony_ci int64_t offset, size_t maxSize, ElfCommand cmd, size_t scnCnt, Elf* elf) 3084514f5e3Sopenharmony_ci{ 3094514f5e3Sopenharmony_ci /* This pointer might not be directly usable if the alignment is 3104514f5e3Sopenharmony_ci not sufficient for the architecture. */ 3114514f5e3Sopenharmony_ci ElfEhdr* ehdr = reinterpret_cast<ElfEhdr*>(reinterpret_cast<char*>(mapAddress) + offset); 3124514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && CheckAlign<ElfEhdr>(ehdr)) { 3134514f5e3Sopenharmony_ci /* We can use the mmapped memory. */ 3144514f5e3Sopenharmony_ci elfItemField.ehdr = ehdr; 3154514f5e3Sopenharmony_ci } else { 3164514f5e3Sopenharmony_ci if (memcpy_s(&elfItemField.elfHeaderMem, sizeof(ElfEhdr), eIdent, sizeof(ElfEhdr)) != 0) { 3174514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_NOMEM); 3184514f5e3Sopenharmony_ci return nullptr; 3194514f5e3Sopenharmony_ci } 3204514f5e3Sopenharmony_ci elfItemField.ehdr = reinterpret_cast<ElfEhdr*>(&elfItemField.elfHeaderMem); 3214514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] != ELF_BYTEORDER) { 3224514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_type); 3234514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_machine); 3244514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_version); 3254514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_entry); 3264514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_phoff); 3274514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_shoff); 3284514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_flags); 3294514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_ehsize); 3304514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_phentsize); 3314514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_phnum); 3324514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_shentsize); 3334514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_shnum); 3344514f5e3Sopenharmony_ci ByteSwap(elfItemField.elfHeaderMem.e_shstrndx); 3354514f5e3Sopenharmony_ci } 3364514f5e3Sopenharmony_ci } 3374514f5e3Sopenharmony_ci auto elfSHOff = elfItemField.ehdr->e_shoff; 3384514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_DATA] == ELF_BYTEORDER && cmd != ELF_CMD_READ_MMAP && 3394514f5e3Sopenharmony_ci CheckAlign<ElfShdr>(ehdr, elfSHOff)) { 3404514f5e3Sopenharmony_ci if (SECUREC_UNLIKELY(scnCnt > 0 && elfSHOff >= maxSize) || 3414514f5e3Sopenharmony_ci SECUREC_UNLIKELY(maxSize - elfSHOff < scnCnt * sizeof(ElfShdr))) { 3424514f5e3Sopenharmony_ci delete[] reinterpret_cast<char*>(elf); 3434514f5e3Sopenharmony_ci elf = nullptr; 3444514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 3454514f5e3Sopenharmony_ci return nullptr; 3464514f5e3Sopenharmony_ci } 3474514f5e3Sopenharmony_ci if (scnCnt > 0) { 3484514f5e3Sopenharmony_ci elfItemField.shdr = reinterpret_cast<ElfShdr*>(reinterpret_cast<char*>(ehdr) + elfSHOff); 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci for (size_t cnt = 0; cnt < scnCnt; ++cnt) { 3514514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].index = cnt; 3524514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].elf = elf; 3534514f5e3Sopenharmony_ci if (std::is_same<ElfShdr, llvm::ELF::Elf32_Shdr>::value) { 3544514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].shdr.e32 = 3554514f5e3Sopenharmony_ci reinterpret_cast<llvm::ELF::Elf32_Shdr*>(&elfItemField.shdr[cnt]); 3564514f5e3Sopenharmony_ci } else { 3574514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].shdr.e64 = 3584514f5e3Sopenharmony_ci reinterpret_cast<llvm::ELF::Elf64_Shdr*>(&elfItemField.shdr[cnt]); 3594514f5e3Sopenharmony_ci } 3604514f5e3Sopenharmony_ci 3614514f5e3Sopenharmony_ci if (SECUREC_LIKELY(elfItemField.shdr[cnt].sh_offset < maxSize) && 3624514f5e3Sopenharmony_ci SECUREC_LIKELY(elfItemField.shdr[cnt].sh_size <= maxSize - elfItemField.shdr[cnt].sh_offset)) { 3634514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].rawDataBase = elfItemField.sections.data()[cnt].dataBase = 3644514f5e3Sopenharmony_ci (reinterpret_cast<char*>(mapAddress) + offset + elfItemField.shdr[cnt].sh_offset); 3654514f5e3Sopenharmony_ci } 3664514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].list = &elfItemField.sections; 3674514f5e3Sopenharmony_ci 3684514f5e3Sopenharmony_ci /* If this is a section with an extended index add a 3694514f5e3Sopenharmony_ci reference in the section which uses the extended 3704514f5e3Sopenharmony_ci index. */ 3714514f5e3Sopenharmony_ci if (elfItemField.shdr[cnt].sh_type == llvm::ELF::SHT_SYMTAB_SHNDX && 3724514f5e3Sopenharmony_ci elfItemField.shdr[cnt].sh_link < scnCnt) { 3734514f5e3Sopenharmony_ci elfItemField.sections.data()[elfItemField.shdr[cnt].sh_link] 3744514f5e3Sopenharmony_ci .extendSectionHeaderIndex = static_cast<int>(cnt); 3754514f5e3Sopenharmony_ci } 3764514f5e3Sopenharmony_ci /* Set the own extendSectionHeaderIndex field in case it has not yet 3774514f5e3Sopenharmony_ci been set. */ 3784514f5e3Sopenharmony_ci if (elfItemField.sections.data()[cnt].extendSectionHeaderIndex == 0) { 3794514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].extendSectionHeaderIndex = -1; 3804514f5e3Sopenharmony_ci } 3814514f5e3Sopenharmony_ci } 3824514f5e3Sopenharmony_ci } else { 3834514f5e3Sopenharmony_ci for (size_t cnt = 0; cnt < scnCnt; ++cnt) { 3844514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].index = cnt; 3854514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].elf = elf; 3864514f5e3Sopenharmony_ci elfItemField.sections.data()[cnt].list = &elfItemField.sections; 3874514f5e3Sopenharmony_ci } 3884514f5e3Sopenharmony_ci } 3894514f5e3Sopenharmony_ci 3904514f5e3Sopenharmony_ci /* So far only one block with sections. */ 3914514f5e3Sopenharmony_ci elfItemField.sectionLast = &elfItemField.sections; 3924514f5e3Sopenharmony_ci return elf; 3934514f5e3Sopenharmony_ci} 3944514f5e3Sopenharmony_ci 3954514f5e3Sopenharmony_ci/* Create descriptor for ELF file in memory. */ 3964514f5e3Sopenharmony_ciElfChecker::Elf* ElfChecker::FileReadElf( 3974514f5e3Sopenharmony_ci void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxSize, ElfCommand cmd, Elf* parent) 3984514f5e3Sopenharmony_ci{ 3994514f5e3Sopenharmony_ci /* Verify the binary is of the class we can handle. */ 4004514f5e3Sopenharmony_ci if (SECUREC_UNLIKELY((eIdent[llvm::ELF::EI_CLASS] != llvm::ELF::ELFCLASS32 && 4014514f5e3Sopenharmony_ci eIdent[llvm::ELF::EI_CLASS] != llvm::ELF::ELFCLASS64) || 4024514f5e3Sopenharmony_ci (eIdent[llvm::ELF::EI_DATA] != llvm::ELF::ELFDATA2LSB && 4034514f5e3Sopenharmony_ci eIdent[llvm::ELF::EI_DATA] != llvm::ELF::ELFDATA2MSB))) { 4044514f5e3Sopenharmony_ci /* Cannot handle this. */ 4054514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 4064514f5e3Sopenharmony_ci return nullptr; 4074514f5e3Sopenharmony_ci } 4084514f5e3Sopenharmony_ci 4094514f5e3Sopenharmony_ci size_t scncnt = GetShnum(mapAddress, eIdent, offset, maxSize); 4104514f5e3Sopenharmony_ci if (CheckIfError() == false) { 4114514f5e3Sopenharmony_ci return nullptr; 4124514f5e3Sopenharmony_ci } 4134514f5e3Sopenharmony_ci 4144514f5e3Sopenharmony_ci /* Check for too many sections. */ 4154514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) { 4164514f5e3Sopenharmony_ci if (scncnt > SIZE_MAX / (sizeof(ElfSectionBase) + sizeof(llvm::ELF::Elf32_Shdr))) { 4174514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 4184514f5e3Sopenharmony_ci return nullptr; 4194514f5e3Sopenharmony_ci } 4204514f5e3Sopenharmony_ci } else if (scncnt > SIZE_MAX / (sizeof(ElfSectionBase) + sizeof(llvm::ELF::Elf64_Shdr))) { 4214514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_ELF); 4224514f5e3Sopenharmony_ci return nullptr; 4234514f5e3Sopenharmony_ci } 4244514f5e3Sopenharmony_ci 4254514f5e3Sopenharmony_ci /* We can now allocate the memory. Even if there are no section 4264514f5e3Sopenharmony_ci headers, we allocate space for a zeroth section in case we need it 4274514f5e3Sopenharmony_ci later. */ 4284514f5e3Sopenharmony_ci const size_t scnMax = (scncnt ? scncnt : (cmd == ELF_CMD_RDWR || cmd == ELF_CMD_RDWR_MMAP) ? 1 : 0); 4294514f5e3Sopenharmony_ci Elf* elf = ElfAllocate(mapAddress, offset, maxSize, cmd, parent, ELF_KIND_ELF, scnMax * sizeof(ElfSectionBase)); 4304514f5e3Sopenharmony_ci if (elf == nullptr) { 4314514f5e3Sopenharmony_ci return nullptr; 4324514f5e3Sopenharmony_ci } 4334514f5e3Sopenharmony_ci 4344514f5e3Sopenharmony_ci ASSERT((unsigned int)scncnt == scncnt); 4354514f5e3Sopenharmony_ci ASSERT(offsetof(Elf, state.elf32.sections) == offsetof(Elf, state.elf64.sections)); 4364514f5e3Sopenharmony_ci elf->state.elf32.sections.cnt = scncnt; 4374514f5e3Sopenharmony_ci elf->state.elf32.sections.max = scnMax; 4384514f5e3Sopenharmony_ci 4394514f5e3Sopenharmony_ci /* Make the class easily available. */ 4404514f5e3Sopenharmony_ci elf->binaryClass = eIdent[llvm::ELF::EI_CLASS]; 4414514f5e3Sopenharmony_ci 4424514f5e3Sopenharmony_ci if (eIdent[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32) { 4434514f5e3Sopenharmony_ci return GetElfItem<llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Shdr, decltype(elf->state.elf32)>( 4444514f5e3Sopenharmony_ci elf->state.elf32, mapAddress, eIdent, offset, maxSize, cmd, scncnt, elf); 4454514f5e3Sopenharmony_ci } else { 4464514f5e3Sopenharmony_ci return GetElfItem<llvm::ELF::Elf64_Ehdr, llvm::ELF::Elf64_Shdr, decltype(elf->state.elf64)>( 4474514f5e3Sopenharmony_ci elf->state.elf64, mapAddress, eIdent, offset, maxSize, cmd, scncnt, elf); 4484514f5e3Sopenharmony_ci } 4494514f5e3Sopenharmony_ci} 4504514f5e3Sopenharmony_ci 4514514f5e3Sopenharmony_ciElfChecker::Elf* ElfChecker::ReadMmapedFile( 4524514f5e3Sopenharmony_ci void* mapAddress, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent) 4534514f5e3Sopenharmony_ci{ 4544514f5e3Sopenharmony_ci unsigned char* eIdent = reinterpret_cast<unsigned char*>(mapAddress) + offset; 4554514f5e3Sopenharmony_ci /* See what kind of object we have here. */ 4564514f5e3Sopenharmony_ci ElfKind kind = GetElfKind(eIdent); 4574514f5e3Sopenharmony_ci if (kind == ELF_KIND_ELF) { 4584514f5e3Sopenharmony_ci return FileReadElf(mapAddress, eIdent, offset, maxsize, cmd, parent); 4594514f5e3Sopenharmony_ci } else { 4604514f5e3Sopenharmony_ci return ElfAllocate(mapAddress, offset, maxsize, cmd, parent, ELF_KIND_NONE, 0); 4614514f5e3Sopenharmony_ci } 4624514f5e3Sopenharmony_ci} 4634514f5e3Sopenharmony_ci 4644514f5e3Sopenharmony_ciElfChecker::Elf* ElfChecker::ElfMemory(char* image, size_t size) 4654514f5e3Sopenharmony_ci{ 4664514f5e3Sopenharmony_ci if (image == nullptr) { 4674514f5e3Sopenharmony_ci SetErrorCode(ELF_ERR_INVALID_OPERAND); 4684514f5e3Sopenharmony_ci return nullptr; 4694514f5e3Sopenharmony_ci } 4704514f5e3Sopenharmony_ci return ReadMmapedFile(image, 0, size, ELF_CMD_READ, nullptr); 4714514f5e3Sopenharmony_ci} 4724514f5e3Sopenharmony_ci 4734514f5e3Sopenharmony_ciint ElfChecker::ElfRelease(Elf* elf) const 4744514f5e3Sopenharmony_ci{ 4754514f5e3Sopenharmony_ci if (elf == nullptr) { 4764514f5e3Sopenharmony_ci return 0; 4774514f5e3Sopenharmony_ci } 4784514f5e3Sopenharmony_ci if (elf->refCount != 0) { 4794514f5e3Sopenharmony_ci --elf->refCount; 4804514f5e3Sopenharmony_ci if (elf->refCount != 0) { 4814514f5e3Sopenharmony_ci int result = elf->refCount; 4824514f5e3Sopenharmony_ci return result; 4834514f5e3Sopenharmony_ci } 4844514f5e3Sopenharmony_ci } 4854514f5e3Sopenharmony_ci Elf* parent = elf->parent; 4864514f5e3Sopenharmony_ci delete[] reinterpret_cast<char*>(elf); 4874514f5e3Sopenharmony_ci elf = nullptr; 4884514f5e3Sopenharmony_ci return (parent != nullptr && parent->refCount == 0 ? ElfRelease(parent) : 0); 4894514f5e3Sopenharmony_ci} 4904514f5e3Sopenharmony_ci 4914514f5e3Sopenharmony_ciElfChecker::~ElfChecker() 4924514f5e3Sopenharmony_ci{ 4934514f5e3Sopenharmony_ci if (fromMmap_ == false && elfData_ != nullptr) { 4944514f5e3Sopenharmony_ci delete[] elfData_; 4954514f5e3Sopenharmony_ci elfData_ = nullptr; 4964514f5e3Sopenharmony_ci } 4974514f5e3Sopenharmony_ci} 4984514f5e3Sopenharmony_ci} // namespace panda::ecmascript 499