14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 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
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_file/elf_builder.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript {
194514f5e3Sopenharmony_civoid ElfBuilder::AddShStrTabSection()
204514f5e3Sopenharmony_ci{
214514f5e3Sopenharmony_ci    std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections =
224514f5e3Sopenharmony_ci        des_[ShStrTableModuleDesIndex].GetSectionsInfo();
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_ci    uint32_t size = 1;
254514f5e3Sopenharmony_ci    for (auto &s : sections_) {
264514f5e3Sopenharmony_ci        std::string str = ModuleSectionDes::GetSecName(s);
274514f5e3Sopenharmony_ci        size = size + str.size() + 1;
284514f5e3Sopenharmony_ci    }
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_ci    shStrTabPtr_ = std::make_unique<char []>(size);
314514f5e3Sopenharmony_ci    char *dst = shStrTabPtr_.get();
324514f5e3Sopenharmony_ci    dst[0] = 0x0;
334514f5e3Sopenharmony_ci    uint32_t i = 1;
344514f5e3Sopenharmony_ci    for (auto &s: sections_) {
354514f5e3Sopenharmony_ci        std::string str = ModuleSectionDes::GetSecName(s);
364514f5e3Sopenharmony_ci        uint32_t copySize = str.size();
374514f5e3Sopenharmony_ci        if (copySize == 0) {
384514f5e3Sopenharmony_ci            UNREACHABLE();
394514f5e3Sopenharmony_ci        }
404514f5e3Sopenharmony_ci        ASSERT(size >= i);
414514f5e3Sopenharmony_ci        if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) {
424514f5e3Sopenharmony_ci            UNREACHABLE();
434514f5e3Sopenharmony_ci        }
444514f5e3Sopenharmony_ci        dst[i + copySize] = 0x0;
454514f5e3Sopenharmony_ci        i = i + copySize + 1;
464514f5e3Sopenharmony_ci    }
474514f5e3Sopenharmony_ci    if (sections.find(ElfSecName::SHSTRTAB) != sections.end()) {
484514f5e3Sopenharmony_ci        sections.erase(ElfSecName::SHSTRTAB);
494514f5e3Sopenharmony_ci    }
504514f5e3Sopenharmony_ci    sections[ElfSecName::SHSTRTAB] = std::make_pair(reinterpret_cast<uint64_t>(shStrTabPtr_.get()), size);
514514f5e3Sopenharmony_ci    if (enableSecDump_) {
524514f5e3Sopenharmony_ci        DumpSection();
534514f5e3Sopenharmony_ci    }
544514f5e3Sopenharmony_ci}
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ciuint32_t ElfBuilder::AddAsmStubStrTab(std::ofstream &elfFile,
574514f5e3Sopenharmony_ci    const std::vector<std::pair<std::string, uint32_t>> &asmStubELFInfo)
584514f5e3Sopenharmony_ci{
594514f5e3Sopenharmony_ci    uint32_t size = 1;
604514f5e3Sopenharmony_ci    ASSERT(asmStubELFInfo.size() > 0);
614514f5e3Sopenharmony_ci    uint32_t asmStubSymTabNum = asmStubELFInfo.size() - 1;
624514f5e3Sopenharmony_ci    for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) {
634514f5e3Sopenharmony_ci        const std::string &str = asmStubELFInfo[idx].first;
644514f5e3Sopenharmony_ci        size = size + str.size() + 1;
654514f5e3Sopenharmony_ci    }
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ci    std::unique_ptr<char []> asmStubStrTabPtr = std::make_unique<char []>(size);
684514f5e3Sopenharmony_ci    char *dst = asmStubStrTabPtr.get();
694514f5e3Sopenharmony_ci    dst[0] = 0x0;
704514f5e3Sopenharmony_ci    uint32_t i = 1;
714514f5e3Sopenharmony_ci    for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) {
724514f5e3Sopenharmony_ci        const std::string &str = asmStubELFInfo[idx].first;
734514f5e3Sopenharmony_ci        asmStubStrName_.emplace_back(i);
744514f5e3Sopenharmony_ci        uint32_t copySize = str.size();
754514f5e3Sopenharmony_ci        if (copySize == 0) {
764514f5e3Sopenharmony_ci            UNREACHABLE();
774514f5e3Sopenharmony_ci        }
784514f5e3Sopenharmony_ci        if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) {
794514f5e3Sopenharmony_ci            UNREACHABLE();
804514f5e3Sopenharmony_ci        }
814514f5e3Sopenharmony_ci        dst[i + copySize] = 0x0;
824514f5e3Sopenharmony_ci        i = i + copySize + 1;
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci    elfFile.write(reinterpret_cast<char *>(dst), size);
854514f5e3Sopenharmony_ci    return size;
864514f5e3Sopenharmony_ci}
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_civoid ElfBuilder::DumpSection() const
894514f5e3Sopenharmony_ci{
904514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
914514f5e3Sopenharmony_ci    // dump
924514f5e3Sopenharmony_ci    for (auto &s : sections) {
934514f5e3Sopenharmony_ci        ElfSection section = ElfSection(s.first);
944514f5e3Sopenharmony_ci        if (!section.ShouldDumpToAOTFile()) {
954514f5e3Sopenharmony_ci            continue;
964514f5e3Sopenharmony_ci        }
974514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "secname :" << std::dec << static_cast<int>(s.first)
984514f5e3Sopenharmony_ci            << " addr:0x" << std::hex << s.second.first << " size:0x" << s.second.second << std::endl;
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci}
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ciElfBuilder::ElfBuilder(const std::vector<ModuleSectionDes> &des,
1034514f5e3Sopenharmony_ci    const std::vector<ElfSecName> &sections): des_(des), sections_(sections)
1044514f5e3Sopenharmony_ci{
1054514f5e3Sopenharmony_ci    Initialize();
1064514f5e3Sopenharmony_ci    AddShStrTabSection();
1074514f5e3Sopenharmony_ci    RemoveNotNeedSection();
1084514f5e3Sopenharmony_ci}
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_civoid ElfBuilder::Initialize()
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    for (size_t i = 0; i < des_.size(); i++) {
1134514f5e3Sopenharmony_ci        des_[i].AddArkStackMapSection();
1144514f5e3Sopenharmony_ci    }
1154514f5e3Sopenharmony_ci    sectionToAlign_ = {
1164514f5e3Sopenharmony_ci        {ElfSecName::TEXT, AOTFileInfo::PAGE_ALIGN},
1174514f5e3Sopenharmony_ci        {ElfSecName::STRTAB, 1},
1184514f5e3Sopenharmony_ci        {ElfSecName::SYMTAB, AOTFileInfo::DATA_SEC_ALIGN},
1194514f5e3Sopenharmony_ci        {ElfSecName::SHSTRTAB, AOTFileInfo::DATA_SEC_ALIGN},
1204514f5e3Sopenharmony_ci        {ElfSecName::ARK_STACKMAP, AOTFileInfo::DATA_SEC_ALIGN},
1214514f5e3Sopenharmony_ci        {ElfSecName::ARK_FUNCENTRY, AOTFileInfo::DATA_SEC_ALIGN},
1224514f5e3Sopenharmony_ci        {ElfSecName::ARK_ASMSTUB, AOTFileInfo::DATA_SEC_ALIGN},
1234514f5e3Sopenharmony_ci        {ElfSecName::ARK_MODULEINFO, AOTFileInfo::DATA_SEC_ALIGN},
1244514f5e3Sopenharmony_ci    };
1254514f5e3Sopenharmony_ci
1264514f5e3Sopenharmony_ci    sectionToSegment_ = {
1274514f5e3Sopenharmony_ci        {ElfSecName::RODATA, ElfSecName::TEXT},
1284514f5e3Sopenharmony_ci        {ElfSecName::RODATA_CST4, ElfSecName::TEXT},
1294514f5e3Sopenharmony_ci        {ElfSecName::RODATA_CST8, ElfSecName::TEXT},
1304514f5e3Sopenharmony_ci        {ElfSecName::RODATA_CST16, ElfSecName::TEXT},
1314514f5e3Sopenharmony_ci        {ElfSecName::RODATA_CST32, ElfSecName::TEXT},
1324514f5e3Sopenharmony_ci        {ElfSecName::TEXT, ElfSecName::TEXT},
1334514f5e3Sopenharmony_ci        {ElfSecName::STRTAB, ElfSecName::DATA},
1344514f5e3Sopenharmony_ci        {ElfSecName::SYMTAB, ElfSecName::DATA},
1354514f5e3Sopenharmony_ci        {ElfSecName::SHSTRTAB, ElfSecName::DATA},
1364514f5e3Sopenharmony_ci        {ElfSecName::ARK_STACKMAP, ElfSecName::DATA},
1374514f5e3Sopenharmony_ci        {ElfSecName::ARK_FUNCENTRY, ElfSecName::DATA},
1384514f5e3Sopenharmony_ci        {ElfSecName::ARK_ASMSTUB, ElfSecName::TEXT},
1394514f5e3Sopenharmony_ci        {ElfSecName::ARK_MODULEINFO, ElfSecName::DATA},
1404514f5e3Sopenharmony_ci    };
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ci    segmentToFlag_ = {
1434514f5e3Sopenharmony_ci        {ElfSecName::TEXT, llvm::ELF::PF_X | llvm::ELF::PF_R},
1444514f5e3Sopenharmony_ci        {ElfSecName::DATA, llvm::ELF::PF_R},
1454514f5e3Sopenharmony_ci    };
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ci    SetLastSection();
1484514f5e3Sopenharmony_ci}
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_civoid ElfBuilder::RemoveNotNeedSection()
1514514f5e3Sopenharmony_ci{
1524514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
1534514f5e3Sopenharmony_ci    for (size_t i = 0; i < sections_.size();) {
1544514f5e3Sopenharmony_ci        if (sections.find(sections_[i]) == sections.end()) {
1554514f5e3Sopenharmony_ci            auto it = sections_.begin() + i;
1564514f5e3Sopenharmony_ci            sections_.erase(it);
1574514f5e3Sopenharmony_ci            continue;
1584514f5e3Sopenharmony_ci        }
1594514f5e3Sopenharmony_ci        i++;
1604514f5e3Sopenharmony_ci    }
1614514f5e3Sopenharmony_ci}
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ciElfBuilder::~ElfBuilder()
1644514f5e3Sopenharmony_ci{
1654514f5e3Sopenharmony_ci    shStrTabPtr_ = nullptr;
1664514f5e3Sopenharmony_ci}
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ciuint32_t ElfBuilder::GetShIndex(ElfSecName section) const
1694514f5e3Sopenharmony_ci{
1704514f5e3Sopenharmony_ci    std::set<ElfSecName> secSet(sections_.begin(), sections_.end());
1714514f5e3Sopenharmony_ci    uint32_t idx = 1;
1724514f5e3Sopenharmony_ci    for (ElfSecName sec : secSet) {
1734514f5e3Sopenharmony_ci        if (sec == section) {
1744514f5e3Sopenharmony_ci            return idx;
1754514f5e3Sopenharmony_ci        }
1764514f5e3Sopenharmony_ci        idx++;
1774514f5e3Sopenharmony_ci    }
1784514f5e3Sopenharmony_ci    return 0;
1794514f5e3Sopenharmony_ci}
1804514f5e3Sopenharmony_ci
1814514f5e3Sopenharmony_ciint ElfBuilder::GetSecNum() const
1824514f5e3Sopenharmony_ci{
1834514f5e3Sopenharmony_ci    return sections_.size() + 1; // add first empty section.
1844514f5e3Sopenharmony_ci}
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ci/*
1874514f5e3Sopenharmony_ciELF Header as follow:
1884514f5e3Sopenharmony_ciELF Header:
1894514f5e3Sopenharmony_ci  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
1904514f5e3Sopenharmony_ci  Class:                             ELF64
1914514f5e3Sopenharmony_ci  Data:                              2's complement, little endian
1924514f5e3Sopenharmony_ci  Version:                           1 (current)
1934514f5e3Sopenharmony_ci  OS/ABI:                            UNIX - System V
1944514f5e3Sopenharmony_ci  ABI Version:                       0
1954514f5e3Sopenharmony_ci  Type:                              DYN (Shared object file)
1964514f5e3Sopenharmony_ci  Machine:                           Advanced Micro Devices X86-64
1974514f5e3Sopenharmony_ci  Version:                           0x4000001
1984514f5e3Sopenharmony_ci  Entry point address:               0x0
1994514f5e3Sopenharmony_ci  Start of program headers:          16384 (bytes into file)
2004514f5e3Sopenharmony_ci  Start of section headers:          64 (bytes into file)
2014514f5e3Sopenharmony_ci  Flags:                             0x0
2024514f5e3Sopenharmony_ci  Size of this header:               64 (bytes)
2034514f5e3Sopenharmony_ci  Size of program headers:           56 (bytes)
2044514f5e3Sopenharmony_ci  Number of program headers:         2
2054514f5e3Sopenharmony_ci  Size of section headers:           64 (bytes)
2064514f5e3Sopenharmony_ci  Number of section headers:         7
2074514f5e3Sopenharmony_ci  Section header string table index: 3
2084514f5e3Sopenharmony_ci*/
2094514f5e3Sopenharmony_civoid ElfBuilder::PackELFHeader(llvm::ELF::Elf64_Ehdr &header, uint32_t version, Triple triple)
2104514f5e3Sopenharmony_ci{
2114514f5e3Sopenharmony_ci    if (memset_s(reinterpret_cast<void *>(&header), sizeof(llvm::ELF::Elf64_Ehdr), 0,
2124514f5e3Sopenharmony_ci                 sizeof(llvm::ELF::Elf64_Ehdr)) != EOK) {
2134514f5e3Sopenharmony_ci        UNREACHABLE();
2144514f5e3Sopenharmony_ci    }
2154514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_MAG0] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0];
2164514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_MAG1] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1];
2174514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_MAG2] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2];
2184514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_MAG3] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3];
2194514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
2204514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
2214514f5e3Sopenharmony_ci    header.e_ident[llvm::ELF::EI_VERSION] = 1;
2224514f5e3Sopenharmony_ci
2234514f5e3Sopenharmony_ci    header.e_type = llvm::ELF::ET_DYN;
2244514f5e3Sopenharmony_ci    switch (triple) {
2254514f5e3Sopenharmony_ci        case Triple::TRIPLE_AMD64:
2264514f5e3Sopenharmony_ci            header.e_machine = llvm::ELF::EM_X86_64;
2274514f5e3Sopenharmony_ci            break;
2284514f5e3Sopenharmony_ci        case Triple::TRIPLE_ARM32:
2294514f5e3Sopenharmony_ci            header.e_machine = llvm::ELF::EM_ARM;
2304514f5e3Sopenharmony_ci            break;
2314514f5e3Sopenharmony_ci        case Triple::TRIPLE_AARCH64:
2324514f5e3Sopenharmony_ci            header.e_machine = llvm::ELF::EM_AARCH64;
2334514f5e3Sopenharmony_ci            break;
2344514f5e3Sopenharmony_ci        default:
2354514f5e3Sopenharmony_ci            UNREACHABLE();
2364514f5e3Sopenharmony_ci            break;
2374514f5e3Sopenharmony_ci    }
2384514f5e3Sopenharmony_ci    header.e_version = version;
2394514f5e3Sopenharmony_ci    // start of section headers
2404514f5e3Sopenharmony_ci    header.e_shoff = sizeof(llvm::ELF::Elf64_Ehdr);
2414514f5e3Sopenharmony_ci    // size of ehdr
2424514f5e3Sopenharmony_ci    header.e_ehsize = sizeof(llvm::ELF::Elf64_Ehdr);
2434514f5e3Sopenharmony_ci    // size of section headers
2444514f5e3Sopenharmony_ci    header.e_shentsize = sizeof(llvm::ELF::Elf64_Shdr);
2454514f5e3Sopenharmony_ci    // number of section headers
2464514f5e3Sopenharmony_ci    header.e_shnum = GetSecNum();
2474514f5e3Sopenharmony_ci    // section header string table index
2484514f5e3Sopenharmony_ci    header.e_shstrndx = static_cast<llvm::ELF::Elf64_Half>(GetShIndex(ElfSecName::SHSTRTAB));
2494514f5e3Sopenharmony_ci    // section header stub sec info index
2504514f5e3Sopenharmony_ci    header.e_flags = static_cast<llvm::ELF::Elf64_Word>(GetShIndex(ElfSecName::ARK_MODULEINFO));
2514514f5e3Sopenharmony_ci    // phr
2524514f5e3Sopenharmony_ci    header.e_phentsize = sizeof(llvm::ELF::Elf64_Phdr);
2534514f5e3Sopenharmony_ci    header.e_phnum = GetSegmentNum();
2544514f5e3Sopenharmony_ci}
2554514f5e3Sopenharmony_ci
2564514f5e3Sopenharmony_ciint ElfBuilder::GetSegmentNum() const
2574514f5e3Sopenharmony_ci{
2584514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
2594514f5e3Sopenharmony_ci    std::set<ElfSecName> segments;
2604514f5e3Sopenharmony_ci    for (auto &s: sections) {
2614514f5e3Sopenharmony_ci        ElfSection section = ElfSection(s.first);
2624514f5e3Sopenharmony_ci        if (!section.ShouldDumpToAOTFile()) {
2634514f5e3Sopenharmony_ci            continue;
2644514f5e3Sopenharmony_ci        }
2654514f5e3Sopenharmony_ci        auto it = sectionToSegment_.find(s.first);
2664514f5e3Sopenharmony_ci        ASSERT(it != sectionToSegment_.end());
2674514f5e3Sopenharmony_ci        ElfSecName name = it->second;
2684514f5e3Sopenharmony_ci        segments.insert(name);
2694514f5e3Sopenharmony_ci    }
2704514f5e3Sopenharmony_ci    return segments.size();
2714514f5e3Sopenharmony_ci}
2724514f5e3Sopenharmony_ci
2734514f5e3Sopenharmony_civoid ElfBuilder::SetLastSection()
2744514f5e3Sopenharmony_ci{
2754514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
2764514f5e3Sopenharmony_ci    for (auto &s: sections) {
2774514f5e3Sopenharmony_ci        ElfSection section = ElfSection(s.first);
2784514f5e3Sopenharmony_ci        if (!section.ShouldDumpToAOTFile()) {
2794514f5e3Sopenharmony_ci            continue;
2804514f5e3Sopenharmony_ci        }
2814514f5e3Sopenharmony_ci        auto it = sectionToSegment_.find(s.first);
2824514f5e3Sopenharmony_ci        ASSERT(it != sectionToSegment_.end());
2834514f5e3Sopenharmony_ci        ElfSecName name = it->second;
2844514f5e3Sopenharmony_ci        if (name == ElfSecName::TEXT) {
2854514f5e3Sopenharmony_ci            lastCodeSection = std::max(lastCodeSection, s.first);
2864514f5e3Sopenharmony_ci        } else {
2874514f5e3Sopenharmony_ci            lastDataSection = std::max(lastDataSection, s.first);
2884514f5e3Sopenharmony_ci        }
2894514f5e3Sopenharmony_ci    }
2904514f5e3Sopenharmony_ci}
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_cillvm::ELF::Elf64_Word ElfBuilder::FindShName(std::string name, uintptr_t strTabPtr, int strTabSize)
2934514f5e3Sopenharmony_ci{
2944514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Word ans = -1;
2954514f5e3Sopenharmony_ci    int len = static_cast<int>(name.size());
2964514f5e3Sopenharmony_ci    if (strTabSize < len + 1) {
2974514f5e3Sopenharmony_ci        return ans;
2984514f5e3Sopenharmony_ci    }
2994514f5e3Sopenharmony_ci    LOG_ECMA(DEBUG) << "  FindShName name:" << name.c_str() << std::endl;
3004514f5e3Sopenharmony_ci    for (int i = 0; i < strTabSize - len + 1; ++i) {
3014514f5e3Sopenharmony_ci        char *dst = reinterpret_cast<char *>(strTabPtr) + i;
3024514f5e3Sopenharmony_ci        if (name.compare(dst) == 0) {
3034514f5e3Sopenharmony_ci            return i;
3044514f5e3Sopenharmony_ci        }
3054514f5e3Sopenharmony_ci    }
3064514f5e3Sopenharmony_ci    return ans;
3074514f5e3Sopenharmony_ci}
3084514f5e3Sopenharmony_ci
3094514f5e3Sopenharmony_cistd::pair<uint64_t, uint32_t> ElfBuilder::FindShStrTab() const
3104514f5e3Sopenharmony_ci{
3114514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
3124514f5e3Sopenharmony_ci    uint64_t shStrTabAddr = 0;
3134514f5e3Sopenharmony_ci    uint32_t shStrTabSize = 0;
3144514f5e3Sopenharmony_ci    for (auto &s: sections) {
3154514f5e3Sopenharmony_ci        uint32_t curSecSize = des_[ShStrTableModuleDesIndex].GetSecSize(s.first);
3164514f5e3Sopenharmony_ci        uint64_t curSecAddr = des_[ShStrTableModuleDesIndex].GetSecAddr(s.first);
3174514f5e3Sopenharmony_ci        if (s.first == ElfSecName::SHSTRTAB) {
3184514f5e3Sopenharmony_ci            shStrTabSize = curSecSize;
3194514f5e3Sopenharmony_ci            shStrTabAddr = curSecAddr;
3204514f5e3Sopenharmony_ci            break;
3214514f5e3Sopenharmony_ci        }
3224514f5e3Sopenharmony_ci    }
3234514f5e3Sopenharmony_ci    return std::make_pair(shStrTabAddr, shStrTabSize);
3244514f5e3Sopenharmony_ci}
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_civoid ElfBuilder::AllocateShdr(std::unique_ptr<llvm::ELF::Elf64_Shdr []> &shdr, const uint32_t &secNum)
3274514f5e3Sopenharmony_ci{
3284514f5e3Sopenharmony_ci    shdr = std::make_unique<llvm::ELF::Elf64_Shdr []>(secNum);
3294514f5e3Sopenharmony_ci    if (memset_s(reinterpret_cast<void *>(&shdr[0]),
3304514f5e3Sopenharmony_ci                 sizeof(llvm::ELF::Elf64_Shdr),
3314514f5e3Sopenharmony_ci                 0,
3324514f5e3Sopenharmony_ci                 sizeof(llvm::ELF::Elf64_Shdr)) != EOK) {
3334514f5e3Sopenharmony_ci        UNREACHABLE();
3344514f5e3Sopenharmony_ci    }
3354514f5e3Sopenharmony_ci}
3364514f5e3Sopenharmony_ci
3374514f5e3Sopenharmony_cillvm::ELF::Elf64_Off ElfBuilder::ComputeEndAddrOfShdr(const uint32_t &secNum) const
3384514f5e3Sopenharmony_ci{
3394514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Off curSecOffset = sizeof(llvm::ELF::Elf64_Ehdr) + secNum * sizeof(llvm::ELF::Elf64_Shdr);
3404514f5e3Sopenharmony_ci    curSecOffset = AlignUp(curSecOffset, PageSize()); // not pagesize align will cause performance degradation
3414514f5e3Sopenharmony_ci    return curSecOffset;
3424514f5e3Sopenharmony_ci}
3434514f5e3Sopenharmony_ci
3444514f5e3Sopenharmony_ciElfSecName ElfBuilder::GetSegmentName(const ElfSecName &secName) const
3454514f5e3Sopenharmony_ci{
3464514f5e3Sopenharmony_ci    auto it = sectionToSegment_.find(secName);
3474514f5e3Sopenharmony_ci    ASSERT(it != sectionToSegment_.end());
3484514f5e3Sopenharmony_ci    ElfSecName segName = it->second;
3494514f5e3Sopenharmony_ci    return segName;
3504514f5e3Sopenharmony_ci}
3514514f5e3Sopenharmony_ci
3524514f5e3Sopenharmony_civoid ElfBuilder::MergeTextSections(std::ofstream &file,
3534514f5e3Sopenharmony_ci                                   std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
3544514f5e3Sopenharmony_ci                                   llvm::ELF::Elf64_Off &curSecOffset)
3554514f5e3Sopenharmony_ci{
3564514f5e3Sopenharmony_ci    for (size_t i = 0; i < des_.size(); ++i) {
3574514f5e3Sopenharmony_ci        ModuleSectionDes &des = des_[i];
3584514f5e3Sopenharmony_ci        ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
3594514f5e3Sopenharmony_ci        uint32_t curSecSize = des.GetSecSize(ElfSecName::TEXT);
3604514f5e3Sopenharmony_ci        uint64_t curSecAddr = des.GetSecAddr(ElfSecName::TEXT);
3614514f5e3Sopenharmony_ci        curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
3624514f5e3Sopenharmony_ci        file.seekp(curSecOffset);
3634514f5e3Sopenharmony_ci        auto curModuleSec = des.GetSectionsInfo();
3644514f5e3Sopenharmony_ci        uint64_t rodataAddrBeforeText = 0;
3654514f5e3Sopenharmony_ci        uint32_t rodataSizeBeforeText = 0;
3664514f5e3Sopenharmony_ci        uint64_t rodataAddrAfterText = 0;
3674514f5e3Sopenharmony_ci        uint32_t rodataSizeAfterText = 0;
3684514f5e3Sopenharmony_ci        std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) =
3694514f5e3Sopenharmony_ci            des.GetMergedRODataAddrAndSize(curSecAddr);
3704514f5e3Sopenharmony_ci        if (rodataSizeBeforeText != 0) {
3714514f5e3Sopenharmony_ci            file.write(reinterpret_cast<char *>(rodataAddrBeforeText), rodataSizeBeforeText);
3724514f5e3Sopenharmony_ci            curInfo.rodataSizeBeforeText = rodataSizeBeforeText;
3734514f5e3Sopenharmony_ci            curSecOffset += rodataSizeBeforeText;
3744514f5e3Sopenharmony_ci            curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN);
3754514f5e3Sopenharmony_ci            file.seekp(curSecOffset);
3764514f5e3Sopenharmony_ci        }
3774514f5e3Sopenharmony_ci        stubTextOffset_.emplace_back(curSecOffset);
3784514f5e3Sopenharmony_ci        file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
3794514f5e3Sopenharmony_ci        curInfo.textSize = curSecSize;
3804514f5e3Sopenharmony_ci        curSecOffset += curSecSize;
3814514f5e3Sopenharmony_ci        if (rodataSizeAfterText != 0) {
3824514f5e3Sopenharmony_ci            curSecOffset = AlignUp(curSecOffset, AOTFileInfo::DATA_SEC_ALIGN);
3834514f5e3Sopenharmony_ci            file.seekp(curSecOffset);
3844514f5e3Sopenharmony_ci            file.write(reinterpret_cast<char *>(rodataAddrAfterText), rodataSizeAfterText);
3854514f5e3Sopenharmony_ci            curInfo.rodataSizeAfterText = rodataSizeAfterText;
3864514f5e3Sopenharmony_ci            curSecOffset += rodataSizeAfterText;
3874514f5e3Sopenharmony_ci        }
3884514f5e3Sopenharmony_ci    }
3894514f5e3Sopenharmony_ci}
3904514f5e3Sopenharmony_ci
3914514f5e3Sopenharmony_civoid ElfBuilder::MergeStrtabSections(std::ofstream &file,
3924514f5e3Sopenharmony_ci                                     std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
3934514f5e3Sopenharmony_ci                                     llvm::ELF::Elf64_Off &curSecOffset)
3944514f5e3Sopenharmony_ci{
3954514f5e3Sopenharmony_ci    for (size_t i = 0; i < des_.size(); ++i) {
3964514f5e3Sopenharmony_ci        ModuleSectionDes &des = des_[i];
3974514f5e3Sopenharmony_ci        ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
3984514f5e3Sopenharmony_ci        uint32_t curSecSize = des.GetSecSize(ElfSecName::STRTAB);
3994514f5e3Sopenharmony_ci        uint64_t curSecAddr = des.GetSecAddr(ElfSecName::STRTAB);
4004514f5e3Sopenharmony_ci        curInfo.strtabSize = curSecSize;
4014514f5e3Sopenharmony_ci        file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
4024514f5e3Sopenharmony_ci        curSecOffset += curSecSize;
4034514f5e3Sopenharmony_ci        if (des.HasAsmStubStrTab()) {
4044514f5e3Sopenharmony_ci            uint32_t asmStubStrTabSize = AddAsmStubStrTab(file, des.GetAsmStubELFInfo());
4054514f5e3Sopenharmony_ci            curSecOffset += asmStubStrTabSize;
4064514f5e3Sopenharmony_ci            curInfo.strtabSize += asmStubStrTabSize;
4074514f5e3Sopenharmony_ci        }
4084514f5e3Sopenharmony_ci    }
4094514f5e3Sopenharmony_ci}
4104514f5e3Sopenharmony_ci
4114514f5e3Sopenharmony_civoid ElfBuilder::MergeSymtabSections(std::ofstream &file,
4124514f5e3Sopenharmony_ci                                     std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
4134514f5e3Sopenharmony_ci                                     llvm::ELF::Elf64_Off &curSecOffset,
4144514f5e3Sopenharmony_ci                                     llvm::ELF::Elf64_Off &asmStubOffset)
4154514f5e3Sopenharmony_ci{
4164514f5e3Sopenharmony_ci    using Elf64_Sym = llvm::ELF::Elf64_Sym;
4174514f5e3Sopenharmony_ci    uint32_t strTabSize = 0;
4184514f5e3Sopenharmony_ci    uint32_t textSecIndex = GetShIndex(ElfSecName::ARK_ASMSTUB);
4194514f5e3Sopenharmony_ci    for (size_t i = 0; i < des_.size(); ++i) {
4204514f5e3Sopenharmony_ci        ModuleSectionDes &des = des_[i];
4214514f5e3Sopenharmony_ci        ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
4224514f5e3Sopenharmony_ci        uint32_t curSecSize = des.GetSecSize(ElfSecName::SYMTAB);
4234514f5e3Sopenharmony_ci        uint64_t curSecAddr = des.GetSecAddr(ElfSecName::SYMTAB);
4244514f5e3Sopenharmony_ci        curInfo.symtabSize = curSecSize;
4254514f5e3Sopenharmony_ci        file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
4264514f5e3Sopenharmony_ci        curSecOffset += curSecSize;
4274514f5e3Sopenharmony_ci        strTabSize += des.GetSecSize(ElfSecName::STRTAB);
4284514f5e3Sopenharmony_ci        if (des.HasAsmStubStrTab()) {
4294514f5e3Sopenharmony_ci            const std::vector<std::pair<std::string, uint32_t>> &asmStubELFInfo = des.GetAsmStubELFInfo();
4304514f5e3Sopenharmony_ci            ASSERT(asmStubELFInfo.size() > 0);
4314514f5e3Sopenharmony_ci            uint32_t asmStubSymTabNum = asmStubELFInfo.size() - 1;
4324514f5e3Sopenharmony_ci            std::unique_ptr<Elf64_Sym []> syms = std::make_unique<Elf64_Sym []>(asmStubSymTabNum);
4334514f5e3Sopenharmony_ci            ASSERT(asmStubStrName_.size() == asmStubSymTabNum);
4344514f5e3Sopenharmony_ci            for (size_t idx = 0; idx < asmStubSymTabNum; ++idx) {
4354514f5e3Sopenharmony_ci                Elf64_Sym &sym = syms[idx];
4364514f5e3Sopenharmony_ci                sym.setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_FUNC);
4374514f5e3Sopenharmony_ci                sym.st_shndx = static_cast<uint16_t>(textSecIndex);
4384514f5e3Sopenharmony_ci                sym.st_value = asmStubELFInfo[idx].second + asmStubOffset;
4394514f5e3Sopenharmony_ci                sym.st_name = asmStubStrName_[idx];
4404514f5e3Sopenharmony_ci                sym.st_name += strTabSize;
4414514f5e3Sopenharmony_ci                sym.st_other = llvm::ELF::STV_DEFAULT;
4424514f5e3Sopenharmony_ci                sym.st_size = asmStubELFInfo[idx + 1].second - asmStubELFInfo[idx].second;
4434514f5e3Sopenharmony_ci            }
4444514f5e3Sopenharmony_ci            uint32_t asmStubSymTabSize = asmStubSymTabNum * sizeof(llvm::ELF::Elf64_Sym);
4454514f5e3Sopenharmony_ci            file.write(reinterpret_cast<char *>(syms.get()), asmStubSymTabSize);
4464514f5e3Sopenharmony_ci            curInfo.symtabSize += asmStubSymTabSize;
4474514f5e3Sopenharmony_ci            curSecOffset += asmStubSymTabSize;
4484514f5e3Sopenharmony_ci        }
4494514f5e3Sopenharmony_ci    }
4504514f5e3Sopenharmony_ci}
4514514f5e3Sopenharmony_ci
4524514f5e3Sopenharmony_civoid ElfBuilder::MergeArkStackMapSections(std::ofstream &file,
4534514f5e3Sopenharmony_ci                                          std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
4544514f5e3Sopenharmony_ci                                          llvm::ELF::Elf64_Off &curSecOffset)
4554514f5e3Sopenharmony_ci{
4564514f5e3Sopenharmony_ci    for (size_t i = 0; i < des_.size(); ++i) {
4574514f5e3Sopenharmony_ci        ModuleSectionDes &des = des_[i];
4584514f5e3Sopenharmony_ci        ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
4594514f5e3Sopenharmony_ci        uint32_t curSecSize = des.GetSecSize(ElfSecName::ARK_STACKMAP);
4604514f5e3Sopenharmony_ci        uint64_t curSecAddr = des.GetSecAddr(ElfSecName::ARK_STACKMAP);
4614514f5e3Sopenharmony_ci        uint32_t index = des.GetStartIndex();
4624514f5e3Sopenharmony_ci        uint32_t cnt = des.GetFuncCount();
4634514f5e3Sopenharmony_ci        curInfo.startIndex = index;
4644514f5e3Sopenharmony_ci        curInfo.funcCount = cnt;
4654514f5e3Sopenharmony_ci        curInfo.stackMapSize = curSecSize;
4664514f5e3Sopenharmony_ci        file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
4674514f5e3Sopenharmony_ci        curSecOffset += curSecSize;
4684514f5e3Sopenharmony_ci    }
4694514f5e3Sopenharmony_ci}
4704514f5e3Sopenharmony_ci
4714514f5e3Sopenharmony_civoid ElfBuilder::FixSymtab(llvm::ELF::Elf64_Shdr* shdr)
4724514f5e3Sopenharmony_ci{
4734514f5e3Sopenharmony_ci    using Elf64_Sym = llvm::ELF::Elf64_Sym;
4744514f5e3Sopenharmony_ci    ASSERT(stubTextOffset_.size() == des_.size());
4754514f5e3Sopenharmony_ci
4764514f5e3Sopenharmony_ci    uint32_t secNum = static_cast<uint32_t>(GetSecNum());
4774514f5e3Sopenharmony_ci    uint32_t shStrTabIndex = GetShIndex(ElfSecName::SHSTRTAB);
4784514f5e3Sopenharmony_ci    uint32_t strTabIndex = GetShIndex(ElfSecName::STRTAB);
4794514f5e3Sopenharmony_ci    uint32_t textSecIndex = GetShIndex(ElfSecName::TEXT);
4804514f5e3Sopenharmony_ci
4814514f5e3Sopenharmony_ci    uint32_t strTabSize = 0;
4824514f5e3Sopenharmony_ci    int firstGlobal = -1;
4834514f5e3Sopenharmony_ci    uint32_t count = 0;
4844514f5e3Sopenharmony_ci
4854514f5e3Sopenharmony_ci    for (size_t idx = 0; idx < des_.size(); ++idx) {
4864514f5e3Sopenharmony_ci        uint32_t secSize = des_[idx].GetSecSize(ElfSecName::SYMTAB);
4874514f5e3Sopenharmony_ci        uint64_t secAddr = des_[idx].GetSecAddr(ElfSecName::SYMTAB);
4884514f5e3Sopenharmony_ci        Elf64_Sym *syms = reinterpret_cast<Elf64_Sym*>(secAddr);
4894514f5e3Sopenharmony_ci        size_t n = secSize / sizeof(Elf64_Sym);
4904514f5e3Sopenharmony_ci        for (size_t i = 0; i < n; ++i) {
4914514f5e3Sopenharmony_ci            Elf64_Sym* sy = &syms[i];
4924514f5e3Sopenharmony_ci            if (sy->getBinding() == llvm::ELF::STB_GLOBAL && firstGlobal == -1) {
4934514f5e3Sopenharmony_ci                firstGlobal = static_cast<int>(count);
4944514f5e3Sopenharmony_ci            }
4954514f5e3Sopenharmony_ci            if (sy->getType() == llvm::ELF::STT_SECTION) {
4964514f5e3Sopenharmony_ci                sy->st_shndx = static_cast<uint16_t>(shStrTabIndex);
4974514f5e3Sopenharmony_ci            } else if (sy->getType() == llvm::ELF::STT_FUNC) {
4984514f5e3Sopenharmony_ci                sy->st_shndx = static_cast<uint16_t>(textSecIndex);
4994514f5e3Sopenharmony_ci                sy->st_value += stubTextOffset_[idx];
5004514f5e3Sopenharmony_ci            }
5014514f5e3Sopenharmony_ci            if (sy->st_shndx > secNum) {
5024514f5e3Sopenharmony_ci                sy->st_shndx = 0;
5034514f5e3Sopenharmony_ci            }
5044514f5e3Sopenharmony_ci            sy->st_name += strTabSize;
5054514f5e3Sopenharmony_ci            count++;
5064514f5e3Sopenharmony_ci        }
5074514f5e3Sopenharmony_ci        strTabSize += des_[idx].GetSecSize(ElfSecName::STRTAB);
5084514f5e3Sopenharmony_ci    }
5094514f5e3Sopenharmony_ci    shdr->sh_info = static_cast<uint32_t>(firstGlobal);
5104514f5e3Sopenharmony_ci    shdr->sh_link = strTabIndex;
5114514f5e3Sopenharmony_ci}
5124514f5e3Sopenharmony_ci
5134514f5e3Sopenharmony_ci/*
5144514f5e3Sopenharmony_ci
5154514f5e3Sopenharmony_cisection of aot.an layout as follows:
5164514f5e3Sopenharmony_ciThere are 7 section headers, starting at offset 0x40:
5174514f5e3Sopenharmony_ci
5184514f5e3Sopenharmony_ciSection Headers:
5194514f5e3Sopenharmony_ci  [Nr] Name              Type             Address           Offset    Size              EntSize          Flags  Link  Info  Align
5204514f5e3Sopenharmony_ci  [ 0]                   NULL             0000000000000000  00000000  0000000000000000  0000000000000000           0     0     0
5214514f5e3Sopenharmony_ci  [ 1] .text             PROGBITS         0000000000001000  00001000  0000000000000f61  0000000000000000  AX       0     0     16
5224514f5e3Sopenharmony_ci  [ 2] .strtab           STRTAB           0000000000002000  00002000  0000000000000187  0000000000000000   A       0     0     1
5234514f5e3Sopenharmony_ci  [ 3] .symtab           SYMTAB           0000000000002188  00002188  00000000000001c8  0000000000000018   A       1     0     8
5244514f5e3Sopenharmony_ci  [ 4] .shstrtab         STRTAB           0000000000002350  00002350  000000000000003f  0000000000000000   A       0     0     8
5254514f5e3Sopenharmony_ci  [ 5] .ark_funcentry    PROGBITS         0000000000002390  00002390  00000000000006c0  0000000000000000   A       0     0     8
5264514f5e3Sopenharmony_ci  [ 6] .ark_stackmaps    PROGBITS         0000000000002a50  00002a50  000000000000070e  0000000000000000   A       0     0     8
5274514f5e3Sopenharmony_ci
5284514f5e3Sopenharmony_cisection of stub.an layout as follows:
5294514f5e3Sopenharmony_ciThere are 7 section headers, starting at offset 0x40:
5304514f5e3Sopenharmony_ci
5314514f5e3Sopenharmony_ci  [Nr] Name              Type             Address           Offset    Size              EntSize          Flags  Link  Info  Align
5324514f5e3Sopenharmony_ci  [ 0]                   NULL             0000000000000000  00000000  0000000000000000  0000000000000000           0     0     0
5334514f5e3Sopenharmony_ci  [ 1] .text             PROGBITS         0000000000001000  00001000  000000000008225e  0000000000000000  AX       0     0     16
5344514f5e3Sopenharmony_ci  [ 2] .ark_asmstub      PROGBITS         0000000000083260  00083260  0000000000002dc0  0000000000000000  AX       0     0     8
5354514f5e3Sopenharmony_ci  [ 3] .shstrtab         STRTAB           0000000000087000  00087000  000000000000004c  0000000000000000   A       0     0     8
5364514f5e3Sopenharmony_ci  [ 4] .ark_funcentry    PROGBITS         0000000000087050  00087050  0000000000023ca0  0000000000000000   A       0     0     8
5374514f5e3Sopenharmony_ci  [ 5] .ark_stackmaps    PROGBITS         00000000000aacf0  000aacf0  0000000000011e90  0000000000000000   A       0     0     8
5384514f5e3Sopenharmony_ci  [ 6] .ark_moduleinfo   PROGBITS         00000000000bcb80  000bcb80  000000000000003c  0000000000000000   A       0     0     8
5394514f5e3Sopenharmony_ci
5404514f5e3Sopenharmony_ciKey to Flags:
5414514f5e3Sopenharmony_ci  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
5424514f5e3Sopenharmony_ci  L (link order), O (extra OS processing required), G (group), T (TLS),
5434514f5e3Sopenharmony_ci  C (compressed), x (unknown), o (OS specific), E (exclude),
5444514f5e3Sopenharmony_ci  D (mbind), l (large), p (processor specific)
5454514f5e3Sopenharmony_ci*/
5464514f5e3Sopenharmony_civoid ElfBuilder::PackELFSections(std::ofstream &file)
5474514f5e3Sopenharmony_ci{
5484514f5e3Sopenharmony_ci    uint32_t moduleNum = des_.size();
5494514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
5504514f5e3Sopenharmony_ci    uint32_t secNum = sections.size() + 1; // 1 : section id = 0 is null section
5514514f5e3Sopenharmony_ci    std::unique_ptr<llvm::ELF::Elf64_Shdr []> shdr;
5524514f5e3Sopenharmony_ci    AllocateShdr(shdr, secNum);
5534514f5e3Sopenharmony_ci    std::vector<ModuleSectionDes::ModuleRegionInfo> moduleInfo(moduleNum);
5544514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Off curSecOffset = ComputeEndAddrOfShdr(secNum);
5554514f5e3Sopenharmony_ci    file.seekp(curSecOffset);
5564514f5e3Sopenharmony_ci
5574514f5e3Sopenharmony_ci    int i = static_cast<int>(GetShIndex(ElfSecName::TEXT));
5584514f5e3Sopenharmony_ci    auto shStrTab = FindShStrTab();
5594514f5e3Sopenharmony_ci
5604514f5e3Sopenharmony_ci    for (auto const &[secName, secInfo] : sections) {
5614514f5e3Sopenharmony_ci        auto &curShdr = shdr[i];
5624514f5e3Sopenharmony_ci        ElfSection section = ElfSection(secName);
5634514f5e3Sopenharmony_ci        if (!section.ShouldDumpToAOTFile()) {
5644514f5e3Sopenharmony_ci            continue;
5654514f5e3Sopenharmony_ci        }
5664514f5e3Sopenharmony_ci        curShdr.sh_addralign = sectionToAlign_[secName];
5674514f5e3Sopenharmony_ci        curSecOffset = AlignUp(curSecOffset, curShdr.sh_addralign);
5684514f5e3Sopenharmony_ci        file.seekp(curSecOffset);
5694514f5e3Sopenharmony_ci        ElfSecName segName = GetSegmentName(secName);
5704514f5e3Sopenharmony_ci        segments_.insert(segName);
5714514f5e3Sopenharmony_ci        std::string secNameStr = ModuleSectionDes::GetSecName(secName);
5724514f5e3Sopenharmony_ci        // text section address needs 16 bytes alignment
5734514f5e3Sopenharmony_ci        if (secName == ElfSecName::TEXT) {
5744514f5e3Sopenharmony_ci            curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
5754514f5e3Sopenharmony_ci            file.seekp(curSecOffset);
5764514f5e3Sopenharmony_ci        }
5774514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Word shName = FindShName(secNameStr, shStrTab.first, shStrTab.second);
5784514f5e3Sopenharmony_ci        ASSERT(shName != static_cast<llvm::ELF::Elf64_Word>(-1));
5794514f5e3Sopenharmony_ci        curShdr.sh_name = shName;
5804514f5e3Sopenharmony_ci        curShdr.sh_type = section.Type();
5814514f5e3Sopenharmony_ci        curShdr.sh_flags = section.Flag();
5824514f5e3Sopenharmony_ci        curShdr.sh_addr = curSecOffset;
5834514f5e3Sopenharmony_ci        curShdr.sh_offset = static_cast<uint64_t>(curSecOffset);
5844514f5e3Sopenharmony_ci        curShdr.sh_info = 0;
5854514f5e3Sopenharmony_ci        curShdr.sh_link = static_cast<uint32_t>(section.Link());
5864514f5e3Sopenharmony_ci        sectionToFileOffset_[secName] = static_cast<uintptr_t>(file.tellp());
5874514f5e3Sopenharmony_ci        switch (secName) {
5884514f5e3Sopenharmony_ci            case ElfSecName::ARK_MODULEINFO: {
5894514f5e3Sopenharmony_ci                uint32_t curSecSize = sizeof(ModuleSectionDes::ModuleRegionInfo) * moduleInfo.size();
5904514f5e3Sopenharmony_ci                file.write(reinterpret_cast<char *>(moduleInfo.data()), curSecSize);
5914514f5e3Sopenharmony_ci                curSecOffset += curSecSize;
5924514f5e3Sopenharmony_ci                curShdr.sh_size = curSecSize;
5934514f5e3Sopenharmony_ci                break;
5944514f5e3Sopenharmony_ci            }
5954514f5e3Sopenharmony_ci            case ElfSecName::TEXT: {
5964514f5e3Sopenharmony_ci                uint32_t curSize = curSecOffset;
5974514f5e3Sopenharmony_ci                MergeTextSections(file, moduleInfo, curSecOffset);
5984514f5e3Sopenharmony_ci                curShdr.sh_size = curSecOffset - curSize;
5994514f5e3Sopenharmony_ci                break;
6004514f5e3Sopenharmony_ci            }
6014514f5e3Sopenharmony_ci            case ElfSecName::ARK_STACKMAP: {
6024514f5e3Sopenharmony_ci                uint32_t curSize = curSecOffset;
6034514f5e3Sopenharmony_ci                MergeArkStackMapSections(file, moduleInfo, curSecOffset);
6044514f5e3Sopenharmony_ci                curShdr.sh_size = curSecOffset - curSize;
6054514f5e3Sopenharmony_ci                break;
6064514f5e3Sopenharmony_ci            }
6074514f5e3Sopenharmony_ci            case ElfSecName::STRTAB: {
6084514f5e3Sopenharmony_ci                uint32_t curSize = curSecOffset;
6094514f5e3Sopenharmony_ci                MergeStrtabSections(file, moduleInfo, curSecOffset);
6104514f5e3Sopenharmony_ci                curShdr.sh_size = curSecOffset - curSize;
6114514f5e3Sopenharmony_ci                break;
6124514f5e3Sopenharmony_ci            }
6134514f5e3Sopenharmony_ci            case ElfSecName::SYMTAB: {
6144514f5e3Sopenharmony_ci                FixSymtab(&curShdr);
6154514f5e3Sopenharmony_ci                uint32_t curSize = curSecOffset;
6164514f5e3Sopenharmony_ci                uint32_t asmSecIndex = GetShIndex(ElfSecName::ARK_ASMSTUB);
6174514f5e3Sopenharmony_ci                MergeSymtabSections(file, moduleInfo, curSecOffset, shdr[asmSecIndex].sh_offset);
6184514f5e3Sopenharmony_ci                curShdr.sh_size = curSecOffset - curSize;
6194514f5e3Sopenharmony_ci                break;
6204514f5e3Sopenharmony_ci            }
6214514f5e3Sopenharmony_ci            case ElfSecName::SHSTRTAB:
6224514f5e3Sopenharmony_ci            case ElfSecName::ARK_FUNCENTRY:
6234514f5e3Sopenharmony_ci            case ElfSecName::ARK_ASMSTUB: {
6244514f5e3Sopenharmony_ci                uint32_t curSecSize = des_[FullSecIndex].GetSecSize(secName);
6254514f5e3Sopenharmony_ci                uint64_t curSecAddr = des_[FullSecIndex].GetSecAddr(secName);
6264514f5e3Sopenharmony_ci                file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
6274514f5e3Sopenharmony_ci                curSecOffset += curSecSize;
6284514f5e3Sopenharmony_ci                curShdr.sh_size = curSecSize;
6294514f5e3Sopenharmony_ci                break;
6304514f5e3Sopenharmony_ci            }
6314514f5e3Sopenharmony_ci            default: {
6324514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "this section should not dump to an file";
6334514f5e3Sopenharmony_ci                break;
6344514f5e3Sopenharmony_ci            }
6354514f5e3Sopenharmony_ci        }
6364514f5e3Sopenharmony_ci        if (secName == lastDataSection || secName == lastCodeSection) {
6374514f5e3Sopenharmony_ci            curSecOffset = AlignUp(curSecOffset, PageSize());
6384514f5e3Sopenharmony_ci            file.seekp(curSecOffset);
6394514f5e3Sopenharmony_ci        }
6404514f5e3Sopenharmony_ci        curShdr.sh_entsize = static_cast<uint64_t>(section.Entsize());
6414514f5e3Sopenharmony_ci        sectionToShdr_[secName] = curShdr;
6424514f5e3Sopenharmony_ci        LOG_COMPILER(DEBUG) << "  shdr[i].sh_entsize " << std::hex << curShdr.sh_entsize << std::endl;
6434514f5e3Sopenharmony_ci        ++i;
6444514f5e3Sopenharmony_ci    }
6454514f5e3Sopenharmony_ci    uint32_t secEnd = static_cast<uint32_t>(file.tellp());
6464514f5e3Sopenharmony_ci    file.seekp(sizeof(llvm::ELF::Elf64_Ehdr));
6474514f5e3Sopenharmony_ci    file.write(reinterpret_cast<char *>(shdr.get()), secNum * sizeof(llvm::ELF::Elf64_Shdr));
6484514f5e3Sopenharmony_ci    file.seekp(secEnd);
6494514f5e3Sopenharmony_ci}
6504514f5e3Sopenharmony_ci
6514514f5e3Sopenharmony_ciunsigned ElfBuilder::GetPFlag(ElfSecName segment) const
6524514f5e3Sopenharmony_ci{
6534514f5e3Sopenharmony_ci    return segmentToFlag_.at(segment);
6544514f5e3Sopenharmony_ci}
6554514f5e3Sopenharmony_ci
6564514f5e3Sopenharmony_ci/*
6574514f5e3Sopenharmony_cisegment layout as follows:
6584514f5e3Sopenharmony_ciAn Elf file
6594514f5e3Sopenharmony_ciEntry point 0x0
6604514f5e3Sopenharmony_ciThere are 2 program headers, starting at offset 16384
6614514f5e3Sopenharmony_ci
6624514f5e3Sopenharmony_ciProgram Headers:
6634514f5e3Sopenharmony_ci  Type           Offset             VirtAddr           PhysAddr           FileSiz            MemSiz              Flags  Align
6644514f5e3Sopenharmony_ci  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000f61 0x0000000000001000  R E    0x1000
6654514f5e3Sopenharmony_ci  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000 0x000000000000115e 0x0000000000002000  R      0x1000
6664514f5e3Sopenharmony_ci
6674514f5e3Sopenharmony_ci Section to Segment mapping:
6684514f5e3Sopenharmony_ci  Segment Sections...
6694514f5e3Sopenharmony_ci   00     .text
6704514f5e3Sopenharmony_ci   01     .strtab .symtab .shstrtab .ark_funcentry .ark_stackmaps
6714514f5e3Sopenharmony_ci------------------------------------------------------------------------------------------------------------------------------
6724514f5e3Sopenharmony_ciStub Elf file
6734514f5e3Sopenharmony_ciEntry point 0x0
6744514f5e3Sopenharmony_ciThere are 2 program headers, starting at offset 770048
6754514f5e3Sopenharmony_ci
6764514f5e3Sopenharmony_ciProgram Headers:
6774514f5e3Sopenharmony_ci  Type           Offset             VirtAddr           PhysAddr           FileSiz            MemSiz              Flags  Align
6784514f5e3Sopenharmony_ci  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000085020 0x0000000000086000  R E    0x1000
6794514f5e3Sopenharmony_ci  LOAD           0x0000000000087000 0x0000000000087000 0x0000000000087000 0x0000000000035bbc 0x0000000000036000  R      0x1000
6804514f5e3Sopenharmony_ci
6814514f5e3Sopenharmony_ci Section to Segment mapping:
6824514f5e3Sopenharmony_ci  Segment Sections...
6834514f5e3Sopenharmony_ci   00     .text .ark_asmstub
6844514f5e3Sopenharmony_ci   01     .shstrtab .ark_funcentry .ark_stackmaps .ark_moduleinfo
6854514f5e3Sopenharmony_ci*/
6864514f5e3Sopenharmony_civoid ElfBuilder::PackELFSegment(std::ofstream &file)
6874514f5e3Sopenharmony_ci{
6884514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Off e_phoff = static_cast<uint64_t>(file.tellp());
6894514f5e3Sopenharmony_ci    long phoff = (long)offsetof(struct llvm::ELF::Elf64_Ehdr, e_phoff);
6904514f5e3Sopenharmony_ci    // write Elf32_Off e_phoff
6914514f5e3Sopenharmony_ci    file.seekp(phoff);
6924514f5e3Sopenharmony_ci    file.write(reinterpret_cast<char *>(&e_phoff), sizeof(e_phoff));
6934514f5e3Sopenharmony_ci    file.seekp(static_cast<long>(e_phoff));
6944514f5e3Sopenharmony_ci
6954514f5e3Sopenharmony_ci    int segNum = GetSegmentNum();
6964514f5e3Sopenharmony_ci    auto phdrs = std::make_unique<llvm::ELF::Elf64_Phdr []>(segNum);
6974514f5e3Sopenharmony_ci    std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxOffset;
6984514f5e3Sopenharmony_ci    std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxAddress;
6994514f5e3Sopenharmony_ci    std::set<ElfSecName> segments;
7004514f5e3Sopenharmony_ci    // SecName -> addr & size
7014514f5e3Sopenharmony_ci    const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> &sections = GetFullSecInfo();
7024514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Off offset = e_phoff;
7034514f5e3Sopenharmony_ci    for (auto &s: sections) {
7044514f5e3Sopenharmony_ci        ElfSection section = ElfSection(s.first);
7054514f5e3Sopenharmony_ci        if (!section.ShouldDumpToAOTFile()) {
7064514f5e3Sopenharmony_ci            continue;
7074514f5e3Sopenharmony_ci        }
7084514f5e3Sopenharmony_ci        auto it = sectionToSegment_.find(s.first);
7094514f5e3Sopenharmony_ci        ASSERT(it != sectionToSegment_.end());
7104514f5e3Sopenharmony_ci        ElfSecName segName = it->second;
7114514f5e3Sopenharmony_ci        segments.insert(segName);
7124514f5e3Sopenharmony_ci        if (segmentToMaxOffset.find(segName) == segmentToMaxOffset.end()) {
7134514f5e3Sopenharmony_ci            segmentToMaxOffset[segName] = 0;
7144514f5e3Sopenharmony_ci        }
7154514f5e3Sopenharmony_ci        segmentToMaxOffset[segName] =
7164514f5e3Sopenharmony_ci            std::max(segmentToMaxOffset[segName], sectionToShdr_[s.first].sh_offset + sectionToShdr_[s.first].sh_size);
7174514f5e3Sopenharmony_ci        segmentToMaxAddress[segName] =
7184514f5e3Sopenharmony_ci            std::max(segmentToMaxAddress[segName], sectionToShdr_[s.first].sh_addr + sectionToShdr_[s.first].sh_size);
7194514f5e3Sopenharmony_ci        offset = std::min(offset, sectionToShdr_[s.first].sh_offset);
7204514f5e3Sopenharmony_ci    }
7214514f5e3Sopenharmony_ci    int phdrIndex = 0;
7224514f5e3Sopenharmony_ci    llvm::ELF::Elf64_Addr addr = offset;
7234514f5e3Sopenharmony_ci    for (auto &it: segments) {
7244514f5e3Sopenharmony_ci        ElfSecName name = it;
7254514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_align = PageSize();
7264514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_type = llvm::ELF::PT_LOAD;
7274514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_flags = GetPFlag(name);
7284514f5e3Sopenharmony_ci        offset = AlignUp(offset, PageSize());
7294514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_offset = offset;
7304514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_vaddr = addr % phdrs[phdrIndex].p_align == 0 ?
7314514f5e3Sopenharmony_ci            addr : (addr / phdrs[phdrIndex].p_align + 1) * phdrs[phdrIndex].p_align;
7324514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_paddr = phdrs[phdrIndex].p_vaddr;
7334514f5e3Sopenharmony_ci
7344514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_filesz = segmentToMaxOffset[name] - phdrs[phdrIndex].p_offset;
7354514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_memsz = segmentToMaxAddress[name] - phdrs[phdrIndex].p_vaddr;
7364514f5e3Sopenharmony_ci        phdrs[phdrIndex].p_memsz = AlignUp(phdrs[phdrIndex].p_memsz, PageSize());
7374514f5e3Sopenharmony_ci        addr = phdrs[phdrIndex].p_vaddr + phdrs[phdrIndex].p_memsz;
7384514f5e3Sopenharmony_ci        offset += phdrs[phdrIndex].p_filesz;
7394514f5e3Sopenharmony_ci        ++phdrIndex;
7404514f5e3Sopenharmony_ci    }
7414514f5e3Sopenharmony_ci    file.write(reinterpret_cast<char *>(phdrs.get()), sizeof(llvm::ELF::Elf64_Phdr) * segNum);
7424514f5e3Sopenharmony_ci}
7434514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
744