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