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
164514f5e3Sopenharmony_ci#include "ecmascript/dfx/dump_code/jit_dump_elf.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript {
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_civoid JsJitDumpElf::Initx86ElfHeader()
214514f5e3Sopenharmony_ci{
224514f5e3Sopenharmony_ci    header.e_ident[EI_MAG0] = ELFMAG0;
234514f5e3Sopenharmony_ci    header.e_ident[EI_MAG1] = ELFMAG1;
244514f5e3Sopenharmony_ci    header.e_ident[EI_MAG2] = ELFMAG2;
254514f5e3Sopenharmony_ci    header.e_ident[EI_MAG3] = ELFMAG3;
264514f5e3Sopenharmony_ci    header.e_ident[EI_CLASS] = ELFCLASS64;
274514f5e3Sopenharmony_ci    header.e_ident[EI_DATA] = ELFDATA2LSB;
284514f5e3Sopenharmony_ci    header.e_ident[EI_VERSION] = EV_CURRENT;
294514f5e3Sopenharmony_ci    header.e_ident[EI_OSABI] = ELFOSABI_NONE; /* ELFOSABI_NONE represents UNIX System V */
304514f5e3Sopenharmony_ci    header.e_ident[EI_ABIVERSION] = 0;
314514f5e3Sopenharmony_ci    (void)std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0);
324514f5e3Sopenharmony_ci    header.e_type = ET_REL;
334514f5e3Sopenharmony_ci    header.e_machine = EM_X86_64;
344514f5e3Sopenharmony_ci    header.e_version = EV_CURRENT;
354514f5e3Sopenharmony_ci    header.e_entry = 0;
364514f5e3Sopenharmony_ci    header.e_phoff = 0;
374514f5e3Sopenharmony_ci    header.e_shoff = 0; /* later get */
384514f5e3Sopenharmony_ci    header.e_flags = 0; /* The Intel architecture defines no flags; so this member contains zero. */
394514f5e3Sopenharmony_ci    header.e_ehsize = sizeof(maplebe::FileHeader);
404514f5e3Sopenharmony_ci    header.e_phentsize = 0;
414514f5e3Sopenharmony_ci    header.e_phnum = 0;
424514f5e3Sopenharmony_ci    header.e_shentsize = sizeof(maplebe::SectionHeader);
434514f5e3Sopenharmony_ci    header.e_shnum = static_cast<uint16>(sections.size());
444514f5e3Sopenharmony_ci    header.e_shstrndx = strTabSection->GetIndex();
454514f5e3Sopenharmony_ci}
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_civoid JsJitDumpElf::InitArmElfHeader()
484514f5e3Sopenharmony_ci{
494514f5e3Sopenharmony_ci    header.e_ident[EI_MAG0] = ELFMAG0;
504514f5e3Sopenharmony_ci    header.e_ident[EI_MAG1] = ELFMAG1;
514514f5e3Sopenharmony_ci    header.e_ident[EI_MAG2] = ELFMAG2;
524514f5e3Sopenharmony_ci    header.e_ident[EI_MAG3] = ELFMAG3;
534514f5e3Sopenharmony_ci    header.e_ident[EI_CLASS] = ELFCLASS64;
544514f5e3Sopenharmony_ci    header.e_ident[EI_DATA] = ELFDATA2LSB;
554514f5e3Sopenharmony_ci    header.e_ident[EI_VERSION] = EV_CURRENT;
564514f5e3Sopenharmony_ci    header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
574514f5e3Sopenharmony_ci    header.e_ident[EI_ABIVERSION] = 0;
584514f5e3Sopenharmony_ci    std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0);
594514f5e3Sopenharmony_ci    header.e_type = ET_REL;
604514f5e3Sopenharmony_ci    header.e_version = 1;
614514f5e3Sopenharmony_ci    header.e_machine = EM_AARCH64;
624514f5e3Sopenharmony_ci    header.e_flags = 0;
634514f5e3Sopenharmony_ci    header.e_entry = 0;
644514f5e3Sopenharmony_ci    header.e_ehsize = sizeof(maplebe::FileHeader);
654514f5e3Sopenharmony_ci    header.e_phentsize = sizeof(maplebe::SegmentHeader);
664514f5e3Sopenharmony_ci    header.e_shentsize = sizeof(maplebe::SectionHeader);
674514f5e3Sopenharmony_ci    header.e_shstrndx = strTabSection->GetIndex();
684514f5e3Sopenharmony_ci    header.e_shoff = 0;
694514f5e3Sopenharmony_ci    header.e_phoff = 0;
704514f5e3Sopenharmony_ci    header.e_shnum = sections.size();
714514f5e3Sopenharmony_ci    header.e_phnum = 0;
724514f5e3Sopenharmony_ci}
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_civoid JsJitDumpElf::UpdateSectionOffset(Section &section)
754514f5e3Sopenharmony_ci{
764514f5e3Sopenharmony_ci    if (section.GetType() != SHT_NOBITS) {
774514f5e3Sopenharmony_ci        section.SetOffset(globalOffset);
784514f5e3Sopenharmony_ci    } else {
794514f5e3Sopenharmony_ci        section.SetOffset(0);
804514f5e3Sopenharmony_ci    }
814514f5e3Sopenharmony_ci}
824514f5e3Sopenharmony_ci
834514f5e3Sopenharmony_civoid JsJitDumpElf::UpdateGlobalOffset(Section &section)
844514f5e3Sopenharmony_ci{
854514f5e3Sopenharmony_ci    if (section.GetType() != SHT_NOBITS) {
864514f5e3Sopenharmony_ci        globalOffset += section.GetSectionSize();
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci}
894514f5e3Sopenharmony_ci
904514f5e3Sopenharmony_civoid JsJitDumpElf::LayoutSections()
914514f5e3Sopenharmony_ci{
924514f5e3Sopenharmony_ci    globalOffset = sizeof(maplebe::FileHeader);
934514f5e3Sopenharmony_ci    globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, k8Bits);
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci    for (auto *section : sections) {
964514f5e3Sopenharmony_ci        section->SetSectionHeaderNameIndex(static_cast<maplebe::Word>(strTabSection->AddString(section->GetName())));
974514f5e3Sopenharmony_ci    }
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    for (auto *section : sections) {
1004514f5e3Sopenharmony_ci        globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, section->GetAlign());
1014514f5e3Sopenharmony_ci        /* lay out section */
1024514f5e3Sopenharmony_ci        UpdateSectionOffset(*section);
1034514f5e3Sopenharmony_ci        if (section->GetType() != SHT_NOBITS) {
1044514f5e3Sopenharmony_ci            section->GenerateData();
1054514f5e3Sopenharmony_ci        }
1064514f5e3Sopenharmony_ci        UpdateGlobalOffset(*section);
1074514f5e3Sopenharmony_ci    }
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci    globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, 16U);
1104514f5e3Sopenharmony_ci    header.e_shoff = globalOffset;
1114514f5e3Sopenharmony_ci    header.e_shnum = static_cast<uint16>(sections.size());
1124514f5e3Sopenharmony_ci}
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_civoid JsJitDumpElf::RegisterSection(Section &section)
1154514f5e3Sopenharmony_ci{
1164514f5e3Sopenharmony_ci    sections.push_back(&section);
1174514f5e3Sopenharmony_ci    section.SetIndex(static_cast<maplebe::SectionIndex>(sections.size() - 1));
1184514f5e3Sopenharmony_ci}
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_civoid JsJitDumpElf::Init()
1214514f5e3Sopenharmony_ci{
1224514f5e3Sopenharmony_ci    DataSection *nullDataSection = new DataSection(" ", SHT_NULL, 0, 0);
1234514f5e3Sopenharmony_ci    RegisterSection(*nullDataSection);
1244514f5e3Sopenharmony_ci    strTabSection = new StringSection(".strtab", SHT_STRTAB, 0, 1);
1254514f5e3Sopenharmony_ci    RegisterSection(*strTabSection);
1264514f5e3Sopenharmony_ci    textSection = new DataSection(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, k8Bits);
1274514f5e3Sopenharmony_ci    RegisterSection(*textSection);
1284514f5e3Sopenharmony_ci    symbolTabSection = new SymbolSection(".symtab", SHT_SYMTAB, 0, k8Bits, *strTabSection);
1294514f5e3Sopenharmony_ci    RegisterSection(*symbolTabSection);
1304514f5e3Sopenharmony_ci}
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_civoid JsJitDumpElf::AppendData(std::vector<uint8> &codeBuff)
1334514f5e3Sopenharmony_ci{
1344514f5e3Sopenharmony_ci    textSection->AppendData(codeBuff.data(), codeBuff.size());
1354514f5e3Sopenharmony_ci}
1364514f5e3Sopenharmony_ci
1374514f5e3Sopenharmony_civoid JsJitDumpElf::AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx)
1384514f5e3Sopenharmony_ci{
1394514f5e3Sopenharmony_ci    localSymTab.push_back(std::make_pair(symbol, symIdx));
1404514f5e3Sopenharmony_ci}
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_civoid JsJitDumpElf::AppendGlobalSymsToSymTabSec()
1434514f5e3Sopenharmony_ci{
1444514f5e3Sopenharmony_ci    for (auto elem : localSymTab) {
1454514f5e3Sopenharmony_ci        const maplebe::Symbol &symbol = elem.first;
1464514f5e3Sopenharmony_ci        int64 symIdx = elem.second;
1474514f5e3Sopenharmony_ci        symbolTabSection->AppendSymbol(symbol);
1484514f5e3Sopenharmony_ci        symbolTabSection->AppendIdxInSymbols(symIdx);
1494514f5e3Sopenharmony_ci    }
1504514f5e3Sopenharmony_ci}
1514514f5e3Sopenharmony_ci
1524514f5e3Sopenharmony_civoid JsJitDumpElf::AppendSymbolToSymTab(int64 symIdx, uint64 funcSymValue, uint64 funcSymSize,
1534514f5e3Sopenharmony_ci                                        const std::string &symbolName)
1544514f5e3Sopenharmony_ci{
1554514f5e3Sopenharmony_ci    uint8 funcSymType = STB_GLOBAL;
1564514f5e3Sopenharmony_ci    auto nameIndex = strTabSection->AddString(symbolName);
1574514f5e3Sopenharmony_ci    AddSymToSymTab({static_cast<maplebe::Word>(nameIndex),
1584514f5e3Sopenharmony_ci        static_cast<uint8>((funcSymType << kLeftShift4Bits) + (STT_FUNC & 0xf)), 0, textSection->GetIndex(),
1594514f5e3Sopenharmony_ci        funcSymValue, funcSymSize}, symIdx);
1604514f5e3Sopenharmony_ci}
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_civoid JsJitDumpElf::SetFileOffset(int fd, uint64 offset)
1634514f5e3Sopenharmony_ci{
1644514f5e3Sopenharmony_ci    lseek(fd, offset, SEEK_SET);
1654514f5e3Sopenharmony_ci}
1664514f5e3Sopenharmony_ci
1674514f5e3Sopenharmony_civoid JsJitDumpElf::WriteJitElfFile(int fd)
1684514f5e3Sopenharmony_ci{
1694514f5e3Sopenharmony_ci    AppendGlobalSymsToSymTabSec();
1704514f5e3Sopenharmony_ci    /* Init elf file header */
1714514f5e3Sopenharmony_ci    InitArmElfHeader();
1724514f5e3Sopenharmony_ci    LayoutSections();
1734514f5e3Sopenharmony_ci    /* write header */
1744514f5e3Sopenharmony_ci    (void)write(fd, reinterpret_cast<const char *>(&header), sizeof(header));
1754514f5e3Sopenharmony_ci    /* write sections */
1764514f5e3Sopenharmony_ci    for (auto *section : sections) {
1774514f5e3Sopenharmony_ci        if (section->GetType() == SHT_NOBITS) {
1784514f5e3Sopenharmony_ci            continue;
1794514f5e3Sopenharmony_ci        }
1804514f5e3Sopenharmony_ci        SetFileOffset(fd, section->GetOffset());
1814514f5e3Sopenharmony_ci        section->WriteSection(fd);
1824514f5e3Sopenharmony_ci    }
1834514f5e3Sopenharmony_ci    SetFileOffset(fd, header.e_shoff);
1844514f5e3Sopenharmony_ci    /* write section table */
1854514f5e3Sopenharmony_ci    for (auto *section : sections) {
1864514f5e3Sopenharmony_ci        (void)write(fd, &section->GetSectionHeader(), sizeof(section->GetSectionHeader()));
1874514f5e3Sopenharmony_ci    }
1884514f5e3Sopenharmony_ci}
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_civoid JsJitDumpElf::ClearData()
1914514f5e3Sopenharmony_ci{
1924514f5e3Sopenharmony_ci    localSymTab.clear();
1934514f5e3Sopenharmony_ci    globalOffset = 0;
1944514f5e3Sopenharmony_ci    textSection->ClearData();
1954514f5e3Sopenharmony_ci    symbolTabSection->ClearData();
1964514f5e3Sopenharmony_ci    strTabSection->ClearData();
1974514f5e3Sopenharmony_ci    sections.clear();
1984514f5e3Sopenharmony_ci}
1994514f5e3Sopenharmony_ci
2004514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
201