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#ifndef ECMASCRIPT_JIT_DUMP_ELF_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_JIT_DUMP_ELF_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <vector>
204514f5e3Sopenharmony_ci#include <string>
214514f5e3Sopenharmony_ci#include <unistd.h>
224514f5e3Sopenharmony_ci#include <unordered_map>
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_ci#include "ecmascript/compiler/codegen/maple/maple_be/include/cg/elf_types.h"
254514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_cinamespace panda::ecmascript {
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_ciusing uint8 = uint8_t;
304514f5e3Sopenharmony_ciusing uint16 = uint16_t;
314514f5e3Sopenharmony_ciusing uint32 = uint32_t;
324514f5e3Sopenharmony_ciusing uint64 = uint64_t;
334514f5e3Sopenharmony_ciusing int8 = int8_t;
344514f5e3Sopenharmony_ciusing int16 = int16_t;
354514f5e3Sopenharmony_ciusing int32 = int32_t;
364514f5e3Sopenharmony_ciusing int64 = int64_t;
374514f5e3Sopenharmony_ciusing uintptr = uintptr_t;
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_ciconst uint8 kLeftShift4Bits = 4;
404514f5e3Sopenharmony_cistatic const uint8 k8Bits = 8;
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ciclass Section {
434514f5e3Sopenharmony_cipublic:
444514f5e3Sopenharmony_ci    Section(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align) : name(name)
454514f5e3Sopenharmony_ci    {
464514f5e3Sopenharmony_ci        sectionHeader.sh_type = type;
474514f5e3Sopenharmony_ci        sectionHeader.sh_flags = flags;
484514f5e3Sopenharmony_ci        sectionHeader.sh_addralign = align;
494514f5e3Sopenharmony_ci    }
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ci    virtual ~Section() = default;
524514f5e3Sopenharmony_ci    virtual void GenerateData() = 0;
534514f5e3Sopenharmony_ci    virtual void WriteSection(int fd) = 0;
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ci    virtual void ClearData()
564514f5e3Sopenharmony_ci    {
574514f5e3Sopenharmony_ci        return;
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    void SetIndex(maplebe::SectionIndex idx)
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        sectionIndex = idx;
634514f5e3Sopenharmony_ci    }
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci    maplebe::SectionIndex GetIndex() const
664514f5e3Sopenharmony_ci    {
674514f5e3Sopenharmony_ci        return sectionIndex;
684514f5e3Sopenharmony_ci    }
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    void SetInfo(maplebe::Word value)
714514f5e3Sopenharmony_ci    {
724514f5e3Sopenharmony_ci        sectionHeader.sh_info = value;
734514f5e3Sopenharmony_ci    }
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_ci    void SetLink(const Section &section)
764514f5e3Sopenharmony_ci    {
774514f5e3Sopenharmony_ci        sectionHeader.sh_link = static_cast<maplebe::Word>(section.GetIndex());
784514f5e3Sopenharmony_ci    }
794514f5e3Sopenharmony_ci
804514f5e3Sopenharmony_ci    void SetEntSize(maplebe::Xword value)
814514f5e3Sopenharmony_ci    {
824514f5e3Sopenharmony_ci        sectionHeader.sh_entsize = value;
834514f5e3Sopenharmony_ci    }
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci    void SetSectionSize(maplebe::Xword size)
864514f5e3Sopenharmony_ci    {
874514f5e3Sopenharmony_ci        sectionHeader.sh_size = size;
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci
904514f5e3Sopenharmony_ci    virtual maplebe::Xword GetSectionSize()
914514f5e3Sopenharmony_ci    {
924514f5e3Sopenharmony_ci        return sectionHeader.sh_size;
934514f5e3Sopenharmony_ci    }
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci    void SetAddr(maplebe::Address addr)
964514f5e3Sopenharmony_ci    {
974514f5e3Sopenharmony_ci        sectionHeader.sh_addr = addr;
984514f5e3Sopenharmony_ci    }
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    maplebe::Address GetAddr() const
1014514f5e3Sopenharmony_ci    {
1024514f5e3Sopenharmony_ci        return sectionHeader.sh_addr;
1034514f5e3Sopenharmony_ci    }
1044514f5e3Sopenharmony_ci
1054514f5e3Sopenharmony_ci    maplebe::Xword GetFlags() const
1064514f5e3Sopenharmony_ci    {
1074514f5e3Sopenharmony_ci        return sectionHeader.sh_flags;
1084514f5e3Sopenharmony_ci    }
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ci    void SetOffset(maplebe::Offset value)
1114514f5e3Sopenharmony_ci    {
1124514f5e3Sopenharmony_ci        sectionHeader.sh_offset = value;
1134514f5e3Sopenharmony_ci    }
1144514f5e3Sopenharmony_ci
1154514f5e3Sopenharmony_ci    maplebe::Offset GetOffset() const
1164514f5e3Sopenharmony_ci    {
1174514f5e3Sopenharmony_ci        return sectionHeader.sh_offset;
1184514f5e3Sopenharmony_ci    }
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_ci    maplebe::Xword GetAlign() const
1214514f5e3Sopenharmony_ci    {
1224514f5e3Sopenharmony_ci        return sectionHeader.sh_addralign;
1234514f5e3Sopenharmony_ci    }
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_ci    const std::string &GetName() const
1264514f5e3Sopenharmony_ci    {
1274514f5e3Sopenharmony_ci        return name;
1284514f5e3Sopenharmony_ci    }
1294514f5e3Sopenharmony_ci
1304514f5e3Sopenharmony_ci    void SetSectionHeaderNameIndex(maplebe::Word index)
1314514f5e3Sopenharmony_ci    {
1324514f5e3Sopenharmony_ci        sectionHeader.sh_name = index;
1334514f5e3Sopenharmony_ci    }
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci    maplebe::Word GetType() const
1364514f5e3Sopenharmony_ci    {
1374514f5e3Sopenharmony_ci        return sectionHeader.sh_type;
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ci    const maplebe::SectionHeader &GetSectionHeader() const
1414514f5e3Sopenharmony_ci    {
1424514f5e3Sopenharmony_ci        return sectionHeader;
1434514f5e3Sopenharmony_ci    }
1444514f5e3Sopenharmony_ci
1454514f5e3Sopenharmony_ciprivate:
1464514f5e3Sopenharmony_ci    std::string name;
1474514f5e3Sopenharmony_ci    maplebe::SectionIndex sectionIndex {};
1484514f5e3Sopenharmony_ci    maplebe::SectionHeader sectionHeader {};
1494514f5e3Sopenharmony_ci}; /* class Section */
1504514f5e3Sopenharmony_ci
1514514f5e3Sopenharmony_ciclass RelaSection : public Section {
1524514f5e3Sopenharmony_cipublic:
1534514f5e3Sopenharmony_ci    RelaSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Word info,
1544514f5e3Sopenharmony_ci        maplebe::Xword align, const Section &link) : Section(name, type, flags, align)
1554514f5e3Sopenharmony_ci    {
1564514f5e3Sopenharmony_ci        SetEntSize(sizeof(maplebe::Rela));
1574514f5e3Sopenharmony_ci        SetInfo(info);
1584514f5e3Sopenharmony_ci        SetLink(link);
1594514f5e3Sopenharmony_ci    }
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ci    ~RelaSection() = default;
1624514f5e3Sopenharmony_ci
1634514f5e3Sopenharmony_ci    void GenerateData() override
1644514f5e3Sopenharmony_ci    {
1654514f5e3Sopenharmony_ci        SetSectionSize(relas.size() * sizeof(maplebe::Rela));
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ci    void WriteSection(int fd) override
1694514f5e3Sopenharmony_ci    {
1704514f5e3Sopenharmony_ci        (void)write(fd, reinterpret_cast<const char *>(relas.data()), relas.size() * sizeof(maplebe::Rela));
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci
1734514f5e3Sopenharmony_ci    void AppendRela(maplebe::Rela rela)
1744514f5e3Sopenharmony_ci    {
1754514f5e3Sopenharmony_ci        relas.push_back(rela);
1764514f5e3Sopenharmony_ci    }
1774514f5e3Sopenharmony_ci
1784514f5e3Sopenharmony_ciprivate:
1794514f5e3Sopenharmony_ci    std::vector<maplebe::Rela> relas;
1804514f5e3Sopenharmony_ci}; /* class RelaSection */
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ciclass SymbolSection : public Section {
1834514f5e3Sopenharmony_cipublic:
1844514f5e3Sopenharmony_ci    SymbolSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align,
1854514f5e3Sopenharmony_ci        const Section &link) : Section(name, type, flags, align)
1864514f5e3Sopenharmony_ci    {
1874514f5e3Sopenharmony_ci        SetEntSize(sizeof(maplebe::Symbol));
1884514f5e3Sopenharmony_ci        SetLink(link);
1894514f5e3Sopenharmony_ci        SetInfo(1);
1904514f5e3Sopenharmony_ci        AppendSymbol({0, 0, 0, 0, 0, 0});
1914514f5e3Sopenharmony_ci    }
1924514f5e3Sopenharmony_ci
1934514f5e3Sopenharmony_ci    ~SymbolSection() = default;
1944514f5e3Sopenharmony_ci
1954514f5e3Sopenharmony_ci    void GenerateData() override
1964514f5e3Sopenharmony_ci    {
1974514f5e3Sopenharmony_ci        SetSectionSize(symbols.size() * sizeof(maplebe::Symbol));
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci
2004514f5e3Sopenharmony_ci    void WriteSection(int fd) override
2014514f5e3Sopenharmony_ci    {
2024514f5e3Sopenharmony_ci        (void)write(fd, reinterpret_cast<const char *>(symbols.data()), symbols.size() * sizeof(maplebe::Symbol));
2034514f5e3Sopenharmony_ci    }
2044514f5e3Sopenharmony_ci
2054514f5e3Sopenharmony_ci    void AppendSymbol(const maplebe::Symbol &symbol)
2064514f5e3Sopenharmony_ci    {
2074514f5e3Sopenharmony_ci        symbols.push_back(symbol);
2084514f5e3Sopenharmony_ci    }
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ci    uint32 GetSymbolsSize() const
2114514f5e3Sopenharmony_ci    {
2124514f5e3Sopenharmony_ci        return symbols.size();
2134514f5e3Sopenharmony_ci    }
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ci    uint64 GetIdxInSymbols(int64 symIdx) const
2164514f5e3Sopenharmony_ci    {
2174514f5e3Sopenharmony_ci        return symbolIdxMap.at(symIdx);
2184514f5e3Sopenharmony_ci    }
2194514f5e3Sopenharmony_ci
2204514f5e3Sopenharmony_ci    void AppendIdxInSymbols(int64 symIdx)
2214514f5e3Sopenharmony_ci    {
2224514f5e3Sopenharmony_ci        symbolIdxMap[symIdx] = static_cast<uint64>(GetSymbolsSize() - 1);
2234514f5e3Sopenharmony_ci    }
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci    bool ExistSymInSymbols(int64 symIdx)
2264514f5e3Sopenharmony_ci    {
2274514f5e3Sopenharmony_ci        return symbolIdxMap.count(symIdx) != 0;
2284514f5e3Sopenharmony_ci    }
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_ci    uint32 GetDataSize() const
2314514f5e3Sopenharmony_ci    {
2324514f5e3Sopenharmony_ci        return symbols.size() * sizeof(maplebe::Symbol);
2334514f5e3Sopenharmony_ci    }
2344514f5e3Sopenharmony_ci
2354514f5e3Sopenharmony_ci    const char *GetAddr()
2364514f5e3Sopenharmony_ci    {
2374514f5e3Sopenharmony_ci        return reinterpret_cast<const char*>(symbols.data());
2384514f5e3Sopenharmony_ci    }
2394514f5e3Sopenharmony_ci
2404514f5e3Sopenharmony_ci    void ClearData() override
2414514f5e3Sopenharmony_ci    {
2424514f5e3Sopenharmony_ci        symbols.clear();
2434514f5e3Sopenharmony_ci        symbolIdxMap.clear();
2444514f5e3Sopenharmony_ci    }
2454514f5e3Sopenharmony_ci
2464514f5e3Sopenharmony_ciprivate:
2474514f5e3Sopenharmony_ci    std::vector<maplebe::Symbol> symbols;
2484514f5e3Sopenharmony_ci    std::unordered_map<int64, uint64> symbolIdxMap;
2494514f5e3Sopenharmony_ci}; /* class SymbolSection */
2504514f5e3Sopenharmony_ci
2514514f5e3Sopenharmony_ciclass DataSection : public Section {
2524514f5e3Sopenharmony_cipublic:
2534514f5e3Sopenharmony_ci    DataSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align)
2544514f5e3Sopenharmony_ci        : Section(name, type, flags, align) {}
2554514f5e3Sopenharmony_ci
2564514f5e3Sopenharmony_ci    ~DataSection() = default;
2574514f5e3Sopenharmony_ci
2584514f5e3Sopenharmony_ci    virtual void GenerateData() override
2594514f5e3Sopenharmony_ci    {
2604514f5e3Sopenharmony_ci        SetSectionSize(data.size());
2614514f5e3Sopenharmony_ci    }
2624514f5e3Sopenharmony_ci
2634514f5e3Sopenharmony_ci    virtual void WriteSection(int fd) override
2644514f5e3Sopenharmony_ci    {
2654514f5e3Sopenharmony_ci        (void)write(fd, reinterpret_cast<const char *>(data.data()), data.size());
2664514f5e3Sopenharmony_ci    }
2674514f5e3Sopenharmony_ci
2684514f5e3Sopenharmony_ci    void AppendData(const void *value, size_t size)
2694514f5e3Sopenharmony_ci    {
2704514f5e3Sopenharmony_ci        auto pdata = reinterpret_cast<const uint8 *>(value);
2714514f5e3Sopenharmony_ci        data.insert(data.end(), pdata, pdata + size);
2724514f5e3Sopenharmony_ci    }
2734514f5e3Sopenharmony_ci
2744514f5e3Sopenharmony_ci    void AppendData(int64 value, size_t size)
2754514f5e3Sopenharmony_ci    {
2764514f5e3Sopenharmony_ci        for (size_t i = 0; i < size; i++) {
2774514f5e3Sopenharmony_ci            auto pdata = static_cast<uint8>(value >> (i * k8Bits));
2784514f5e3Sopenharmony_ci            data.push_back(pdata);
2794514f5e3Sopenharmony_ci        }
2804514f5e3Sopenharmony_ci    }
2814514f5e3Sopenharmony_ci
2824514f5e3Sopenharmony_ci    void ClearData() override
2834514f5e3Sopenharmony_ci    {
2844514f5e3Sopenharmony_ci        data.clear();
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci
2874514f5e3Sopenharmony_ci    uint32 GetDataSize() const
2884514f5e3Sopenharmony_ci    {
2894514f5e3Sopenharmony_ci        return data.size();
2904514f5e3Sopenharmony_ci    }
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_ci    const std::vector<uint8> &GetData() const
2934514f5e3Sopenharmony_ci    {
2944514f5e3Sopenharmony_ci        return data;
2954514f5e3Sopenharmony_ci    }
2964514f5e3Sopenharmony_ci
2974514f5e3Sopenharmony_ciprotected:
2984514f5e3Sopenharmony_ci    std::vector<uint8> data;
2994514f5e3Sopenharmony_ci}; /* class DataSection */
3004514f5e3Sopenharmony_ci
3014514f5e3Sopenharmony_ciclass StringSection : public DataSection {
3024514f5e3Sopenharmony_cipublic:
3034514f5e3Sopenharmony_ci    StringSection(const std::string &name, maplebe::Word type, maplebe::Xword flags, maplebe::Xword align)
3044514f5e3Sopenharmony_ci        : DataSection(name, type, flags, align)
3054514f5e3Sopenharmony_ci    {
3064514f5e3Sopenharmony_ci        AddString("\0");
3074514f5e3Sopenharmony_ci    }
3084514f5e3Sopenharmony_ci
3094514f5e3Sopenharmony_ci    ~StringSection() = default;
3104514f5e3Sopenharmony_ci
3114514f5e3Sopenharmony_ci    size_t AddString(const std::string &str)
3124514f5e3Sopenharmony_ci    {
3134514f5e3Sopenharmony_ci        size_t pos = data.size();
3144514f5e3Sopenharmony_ci        AppendData(str.c_str(), str.size() + 1);
3154514f5e3Sopenharmony_ci        return pos;
3164514f5e3Sopenharmony_ci    }
3174514f5e3Sopenharmony_ci}; /* class StringSection */
3184514f5e3Sopenharmony_ci
3194514f5e3Sopenharmony_ciclass Alignment {
3204514f5e3Sopenharmony_cipublic:
3214514f5e3Sopenharmony_ci    template <typename T>
3224514f5e3Sopenharmony_ci    static T Align(T offset, T align)
3234514f5e3Sopenharmony_ci    {
3244514f5e3Sopenharmony_ci        if (align <= 1) {
3254514f5e3Sopenharmony_ci            return offset;
3264514f5e3Sopenharmony_ci        }
3274514f5e3Sopenharmony_ci        return (offset + align - 1) & (~(align - 1));
3284514f5e3Sopenharmony_ci    }
3294514f5e3Sopenharmony_ci}; /* class Alignment */
3304514f5e3Sopenharmony_ci
3314514f5e3Sopenharmony_ciclass JsJitDumpElf {
3324514f5e3Sopenharmony_cipublic:
3334514f5e3Sopenharmony_ci    void Init();
3344514f5e3Sopenharmony_ci    void SetFileOffset(int fd, uint64 offset);
3354514f5e3Sopenharmony_ci    void Initx86ElfHeader();
3364514f5e3Sopenharmony_ci    void InitArmElfHeader();
3374514f5e3Sopenharmony_ci    void WriteJitElfFile(int fd);
3384514f5e3Sopenharmony_ci    void LayoutSections();
3394514f5e3Sopenharmony_ci    void UpdateSectionOffset(Section &section);
3404514f5e3Sopenharmony_ci    void UpdateGlobalOffset(Section &section);
3414514f5e3Sopenharmony_ci    void RegisterSection(Section &section);
3424514f5e3Sopenharmony_ci    void AppendData(std::vector<uint8> &codeBuff);
3434514f5e3Sopenharmony_ci    void AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx);
3444514f5e3Sopenharmony_ci    void AppendGlobalSymsToSymTabSec();
3454514f5e3Sopenharmony_ci    void AppendSymbolToSymTab(int64 symIdx, uint64 funcSymValue, uint64 funcSymSize, const std::string &symbolName);
3464514f5e3Sopenharmony_ci    void ClearData();
3474514f5e3Sopenharmony_ciprivate:
3484514f5e3Sopenharmony_ci    std::vector<std::pair<maplebe::Symbol, int64>> localSymTab;
3494514f5e3Sopenharmony_ci    DataSection *textSection = nullptr;
3504514f5e3Sopenharmony_ci    SymbolSection *symbolTabSection = nullptr;
3514514f5e3Sopenharmony_ci    maplebe::FileHeader header {};
3524514f5e3Sopenharmony_ci    StringSection *strTabSection = nullptr;
3534514f5e3Sopenharmony_ci    std::vector<Section *> sections;
3544514f5e3Sopenharmony_ci    maplebe::Offset globalOffset = 0; /* global offset of the elf file */
3554514f5e3Sopenharmony_ci};
3564514f5e3Sopenharmony_ci
3574514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
3584514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_JIT_DUMP_ELF_H
359