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/compiler/aot_file/gdb_jit.h"
174514f5e3Sopenharmony_ci#include "llvm/BinaryFormat/ELF.h"
184514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ci#include <vector>
214514f5e3Sopenharmony_ci#include <cstring>
224514f5e3Sopenharmony_ci#include <securec.h>
234514f5e3Sopenharmony_ci#include <mutex>
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci#ifndef PANDA_TARGET_MACOS
264514f5e3Sopenharmony_ci// Keep in sync with gdb/gdb/jit.h
274514f5e3Sopenharmony_ciextern "C" {
284514f5e3Sopenharmony_citypedef enum {
294514f5e3Sopenharmony_ci    JIT_NOACTION = 0,
304514f5e3Sopenharmony_ci    JIT_REGISTER_FN,
314514f5e3Sopenharmony_ci    JIT_UNREGISTER_FN
324514f5e3Sopenharmony_ci} jit_actions_t;
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_cistruct jit_code_entry {
354514f5e3Sopenharmony_ci    struct jit_code_entry *next_entry;
364514f5e3Sopenharmony_ci    struct jit_code_entry *prev_entry;
374514f5e3Sopenharmony_ci    const char *symfile_addr;
384514f5e3Sopenharmony_ci    uint64_t symfile_size;
394514f5e3Sopenharmony_ci    const char *file_addr; // extend the standard
404514f5e3Sopenharmony_ci};
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_cistruct jit_descriptor {
434514f5e3Sopenharmony_ci    uint32_t version;
444514f5e3Sopenharmony_ci    // This should be jit_actions_t, but we want to be specific about the
454514f5e3Sopenharmony_ci    // bit-width.
464514f5e3Sopenharmony_ci    uint32_t action_flag;
474514f5e3Sopenharmony_ci    struct jit_code_entry *relevant_entry;
484514f5e3Sopenharmony_ci    struct jit_code_entry *first_entry;
494514f5e3Sopenharmony_ci};
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ci// We put information about the JITed function in this global, which the
524514f5e3Sopenharmony_ci// debugger reads.  Make sure to specify the version statically, because the
534514f5e3Sopenharmony_ci// debugger checks the version before we can set it during runtime.
544514f5e3Sopenharmony_cistruct jit_descriptor __jit_debug_descriptor = {
554514f5e3Sopenharmony_ci    1, JIT_NOACTION, nullptr, nullptr
564514f5e3Sopenharmony_ci};
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci// Debuggers puts a breakpoint in this function.
594514f5e3Sopenharmony_civoid __attribute__((noinline)) __jit_debug_register_code()
604514f5e3Sopenharmony_ci{
614514f5e3Sopenharmony_ci    LOG_COMPILER(INFO) << "__jit_debug_register_code() is called.";
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci}
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_cistd::mutex g_descMutex;
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_cinamespace panda::ecmascript {
684514f5e3Sopenharmony_cinamespace jit_debug {
694514f5e3Sopenharmony_ciusing namespace llvm::ELF;
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_cistatic bool RegisterStubAnToDebuggerImpl(const char *fileAddr);
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_civoid RegisterStubAnToDebugger(const char *fileAddr)
744514f5e3Sopenharmony_ci{
754514f5e3Sopenharmony_ci    std::lock_guard<std::mutex> guard(g_descMutex);
764514f5e3Sopenharmony_ci    auto entry = __jit_debug_descriptor.first_entry;
774514f5e3Sopenharmony_ci    while (entry != nullptr && entry->file_addr != fileAddr) {
784514f5e3Sopenharmony_ci        entry = entry->next_entry;
794514f5e3Sopenharmony_ci    }
804514f5e3Sopenharmony_ci    if (entry != nullptr) {
814514f5e3Sopenharmony_ci        return;
824514f5e3Sopenharmony_ci    }
834514f5e3Sopenharmony_ci    if (RegisterStubAnToDebuggerImpl(fileAddr)) {
844514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "success to register stub.an to debugger.";
854514f5e3Sopenharmony_ci    } else {
864514f5e3Sopenharmony_ci        LOG_COMPILER(ERROR) << "Can't register stub.an to debugger.";
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci}
894514f5e3Sopenharmony_ci
904514f5e3Sopenharmony_civoid UnregisterStubAnFromDebugger(const char *fileAddr)
914514f5e3Sopenharmony_ci{
924514f5e3Sopenharmony_ci    std::lock_guard<std::mutex> guard(g_descMutex);
934514f5e3Sopenharmony_ci    auto entry = __jit_debug_descriptor.first_entry;
944514f5e3Sopenharmony_ci    while (entry != nullptr && entry->file_addr != fileAddr) {
954514f5e3Sopenharmony_ci        entry = entry->next_entry;
964514f5e3Sopenharmony_ci    }
974514f5e3Sopenharmony_ci    if (entry == nullptr) {
984514f5e3Sopenharmony_ci        return;
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci    if (entry->prev_entry != nullptr) {
1014514f5e3Sopenharmony_ci        entry->prev_entry->next_entry = entry->next_entry;
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    if (entry->next_entry != nullptr) {
1044514f5e3Sopenharmony_ci        entry->next_entry->prev_entry = entry->prev_entry;
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci    __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
1074514f5e3Sopenharmony_ci    __jit_debug_descriptor.relevant_entry = entry;
1084514f5e3Sopenharmony_ci    __jit_debug_register_code();
1094514f5e3Sopenharmony_ci    __jit_debug_descriptor.relevant_entry = nullptr;
1104514f5e3Sopenharmony_ci    delete entry->symfile_addr;
1114514f5e3Sopenharmony_ci    delete entry;
1124514f5e3Sopenharmony_ci}
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_citemplate<typename T, typename U>
1154514f5e3Sopenharmony_ciinline T OffsetAlignUp(U *addr, uint64_t offset, uint32_t align)
1164514f5e3Sopenharmony_ci{
1174514f5e3Sopenharmony_ci    auto value = reinterpret_cast<uint64_t>(addr) + offset;
1184514f5e3Sopenharmony_ci    auto result = value;
1194514f5e3Sopenharmony_ci    if (align != 0 && (value % align != 0)) {
1204514f5e3Sopenharmony_ci        result = value + (align - (value % align));
1214514f5e3Sopenharmony_ci    }
1224514f5e3Sopenharmony_ci    return reinterpret_cast<T>(result);
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_cistruct StubAnInfo {
1264514f5e3Sopenharmony_ci    uintptr_t fileAddr;
1274514f5e3Sopenharmony_ci    Elf64_Ehdr *ehdr;
1284514f5e3Sopenharmony_ci    Elf64_Shdr *shdrTab;
1294514f5e3Sopenharmony_ci    uint32_t shStrIdx;
1304514f5e3Sopenharmony_ci    Elf64_Shdr *shStrHdr;
1314514f5e3Sopenharmony_ci    Elf64_Shdr *textHdr;
1324514f5e3Sopenharmony_ci    Elf64_Shdr *asmstubHdr;
1334514f5e3Sopenharmony_ci    Elf64_Shdr *symtabHdr;
1344514f5e3Sopenharmony_ci    Elf64_Shdr *strtabHdr;
1354514f5e3Sopenharmony_ci    uint64_t bcStubBegin;
1364514f5e3Sopenharmony_ci    uint64_t bcStubEnd;
1374514f5e3Sopenharmony_ci    uint32_t symCnt;
1384514f5e3Sopenharmony_ci};
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ci/*
1414514f5e3Sopenharmony_ci * [0] file header
1424514f5e3Sopenharmony_ci * [1] program header
1434514f5e3Sopenharmony_ci * [2] shstrtab
1444514f5e3Sopenharmony_ci * [3] strtab
1454514f5e3Sopenharmony_ci * [4] symtab
1464514f5e3Sopenharmony_ci * [5] .eh_frame
1474514f5e3Sopenharmony_ci * [6] empty header
1484514f5e3Sopenharmony_ci * [7] shstrtab-header
1494514f5e3Sopenharmony_ci * [8] strtab-header
1504514f5e3Sopenharmony_ci * [9] symtab-header
1514514f5e3Sopenharmony_ci * [10] text-header
1524514f5e3Sopenharmony_ci * [11] .eh_frame header
1534514f5e3Sopenharmony_ci */
1544514f5e3Sopenharmony_ciconst char SHSTR[] = "\0.shstrtab\0.strtab\0.symtab\0.text\0.eh_frame";
1554514f5e3Sopenharmony_ciconst uint32_t SHSTRTAB_NAME = 1;
1564514f5e3Sopenharmony_ciconst uint32_t STRTAB_NAME = SHSTRTAB_NAME + strlen(".shstrtab") + 1;
1574514f5e3Sopenharmony_ciconst uint32_t SYMTAB_NAME = STRTAB_NAME + strlen(".strtab") + 1;
1584514f5e3Sopenharmony_ciconst uint32_t TEXT_NAME = SYMTAB_NAME + strlen(".symtab") + 1;
1594514f5e3Sopenharmony_ciconst uint32_t EH_FRAME_NAME = TEXT_NAME + strlen(".text") + 1;
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ciconst uint32_t SHSTRTAB_HDR_IDX = 1;
1624514f5e3Sopenharmony_ciconst uint32_t STRTAB_HDR_IDX = 2;
1634514f5e3Sopenharmony_ciconst uint32_t SYMTAB_HDR_IDX = 3;
1644514f5e3Sopenharmony_ciconst uint32_t TEXT_HDR_IDX = 4;
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ciconst uint32_t HEADER_CNT = 6;
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ciinline int InfoGetBind(unsigned char info)
1694514f5e3Sopenharmony_ci{
1704514f5e3Sopenharmony_ci    const uint32_t shift = 4;
1714514f5e3Sopenharmony_ci    return info >> shift;
1724514f5e3Sopenharmony_ci}
1734514f5e3Sopenharmony_ci
1744514f5e3Sopenharmony_ciStubAnInfo CollectStubAnInfo(uintptr_t fileAddr)
1754514f5e3Sopenharmony_ci{
1764514f5e3Sopenharmony_ci    auto *ehdr = reinterpret_cast<Elf64_Ehdr *>(fileAddr);
1774514f5e3Sopenharmony_ci    auto *shdrTab = reinterpret_cast<Elf64_Shdr *>(fileAddr + ehdr->e_shoff);
1784514f5e3Sopenharmony_ci    uint32_t shStrIdx = ehdr->e_shstrndx;
1794514f5e3Sopenharmony_ci    Elf64_Shdr *shStrHdr = &shdrTab[shStrIdx];
1804514f5e3Sopenharmony_ci    const char *shstrtab = reinterpret_cast<const char *>(fileAddr + shStrHdr->sh_offset);
1814514f5e3Sopenharmony_ci    Elf64_Shdr *textHdr = nullptr;
1824514f5e3Sopenharmony_ci    Elf64_Shdr *asmstubHdr = nullptr;
1834514f5e3Sopenharmony_ci    Elf64_Shdr *symtabHdr = nullptr;
1844514f5e3Sopenharmony_ci    Elf64_Shdr *strtabHdr = nullptr;
1854514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < ehdr->e_shnum; i++) {
1864514f5e3Sopenharmony_ci        Elf64_Shdr *shdr = &shdrTab[i];
1874514f5e3Sopenharmony_ci        const char *name = &shstrtab[shdr->sh_name];
1884514f5e3Sopenharmony_ci        if (strcmp(name, ".text") == 0) {
1894514f5e3Sopenharmony_ci            textHdr = shdr;
1904514f5e3Sopenharmony_ci        } else if (strcmp(name, ".ark_asmstub") == 0) {
1914514f5e3Sopenharmony_ci            asmstubHdr = shdr;
1924514f5e3Sopenharmony_ci        } else if (strcmp(name, ".symtab") == 0) {
1934514f5e3Sopenharmony_ci            symtabHdr = shdr;
1944514f5e3Sopenharmony_ci        } else if (strcmp(name, ".strtab") == 0) {
1954514f5e3Sopenharmony_ci            strtabHdr = shdr;
1964514f5e3Sopenharmony_ci        }
1974514f5e3Sopenharmony_ci    }
1984514f5e3Sopenharmony_ci    ASSERT(symtabHdr != nullptr);
1994514f5e3Sopenharmony_ci    Elf64_Sym *symtab = reinterpret_cast<Elf64_Sym *>(fileAddr + symtabHdr->sh_offset);
2004514f5e3Sopenharmony_ci    const char *strtab = reinterpret_cast<const char *>(fileAddr + strtabHdr->sh_offset);
2014514f5e3Sopenharmony_ci    uint32_t symCnt = 2;
2024514f5e3Sopenharmony_ci    uint64_t bcStubBegin = UINT64_MAX;
2034514f5e3Sopenharmony_ci    uint64_t bcStubEnd = 0;
2044514f5e3Sopenharmony_ci    for (uint32_t symIdx = 0; symIdx < symtabHdr->sh_size / symtabHdr->sh_entsize; symIdx++) {
2054514f5e3Sopenharmony_ci        Elf64_Sym *sym = symtab + symIdx;
2064514f5e3Sopenharmony_ci        if (InfoGetBind(sym->st_info) != STB_GLOBAL) {
2074514f5e3Sopenharmony_ci            continue;
2084514f5e3Sopenharmony_ci        }
2094514f5e3Sopenharmony_ci        if (strncmp(&strtab[sym->st_name], "BCStub", strlen("BCStub")) != 0) {
2104514f5e3Sopenharmony_ci            symCnt++;
2114514f5e3Sopenharmony_ci        } else {
2124514f5e3Sopenharmony_ci            if (sym->st_value < bcStubBegin) {
2134514f5e3Sopenharmony_ci                bcStubBegin = sym->st_value;
2144514f5e3Sopenharmony_ci            }
2154514f5e3Sopenharmony_ci            if (sym->st_value + sym->st_size > bcStubEnd) {
2164514f5e3Sopenharmony_ci                bcStubEnd = sym->st_value + sym->st_size;
2174514f5e3Sopenharmony_ci            }
2184514f5e3Sopenharmony_ci        }
2194514f5e3Sopenharmony_ci    }
2204514f5e3Sopenharmony_ci    return StubAnInfo {
2214514f5e3Sopenharmony_ci        fileAddr, ehdr, shdrTab, shStrIdx, shStrHdr, textHdr, asmstubHdr, symtabHdr, strtabHdr,
2224514f5e3Sopenharmony_ci        bcStubBegin, bcStubEnd, symCnt
2234514f5e3Sopenharmony_ci    };
2244514f5e3Sopenharmony_ci}
2254514f5e3Sopenharmony_ci
2264514f5e3Sopenharmony_cibool CopyStrTab(uintptr_t baseAddr, const StubAnInfo &info)
2274514f5e3Sopenharmony_ci{
2284514f5e3Sopenharmony_ci    Elf64_Ehdr *newEhdr = reinterpret_cast<Elf64_Ehdr *>(baseAddr);
2294514f5e3Sopenharmony_ci    Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
2304514f5e3Sopenharmony_ci    char *shStrBuff = reinterpret_cast<char *>(newPhdr + 1);
2314514f5e3Sopenharmony_ci    if (memcpy_s(shStrBuff, sizeof(SHSTR), SHSTR, sizeof(SHSTR)) != EOK) {
2324514f5e3Sopenharmony_ci        return false;
2334514f5e3Sopenharmony_ci    }
2344514f5e3Sopenharmony_ci    char *newStrtab = shStrBuff + sizeof(SHSTR);
2354514f5e3Sopenharmony_ci    if (memcpy_s(newStrtab, info.strtabHdr->sh_size,
2364514f5e3Sopenharmony_ci        reinterpret_cast<void *>(info.fileAddr + info.strtabHdr->sh_offset), info.strtabHdr->sh_size) != EOK) {
2374514f5e3Sopenharmony_ci        return false;
2384514f5e3Sopenharmony_ci    }
2394514f5e3Sopenharmony_ci    const char bcStubName[] = "BCStubInterpreterRoutine";
2404514f5e3Sopenharmony_ci    if (memcpy_s((newStrtab + 1), sizeof(bcStubName), bcStubName, sizeof(bcStubName)) != EOK) {
2414514f5e3Sopenharmony_ci        return false;
2424514f5e3Sopenharmony_ci    }
2434514f5e3Sopenharmony_ci    return true;
2444514f5e3Sopenharmony_ci}
2454514f5e3Sopenharmony_ci
2464514f5e3Sopenharmony_civoid ConstructSymTab(Elf64_Sym *newSymtab, const StubAnInfo &info)
2474514f5e3Sopenharmony_ci{
2484514f5e3Sopenharmony_ci    Elf64_Sym *symtab = reinterpret_cast<Elf64_Sym *>(info.fileAddr + info.symtabHdr->sh_offset);
2494514f5e3Sopenharmony_ci    const char *strtab = reinterpret_cast<const char *>(info.fileAddr + info.strtabHdr->sh_offset);
2504514f5e3Sopenharmony_ci    memset_s(newSymtab, sizeof(Elf64_Sym), 0, sizeof(Elf64_Sym));
2514514f5e3Sopenharmony_ci    uint32_t newSymIdx = 1;
2524514f5e3Sopenharmony_ci    for (uint32_t symIdx = 0; symIdx < info.symtabHdr->sh_size / info.symtabHdr->sh_entsize; symIdx++) {
2534514f5e3Sopenharmony_ci        Elf64_Sym *src = symtab + symIdx;
2544514f5e3Sopenharmony_ci        if (InfoGetBind(src->st_info) == STB_GLOBAL
2554514f5e3Sopenharmony_ci            && strncmp(&strtab[src->st_name], "BCStub", strlen("BCStub")) != 0) {
2564514f5e3Sopenharmony_ci            auto dst = newSymtab + newSymIdx;
2574514f5e3Sopenharmony_ci            newSymIdx++;
2584514f5e3Sopenharmony_ci            *dst = *src;
2594514f5e3Sopenharmony_ci            dst->st_shndx = TEXT_HDR_IDX;
2604514f5e3Sopenharmony_ci            dst->st_value -= info.textHdr->sh_offset;
2614514f5e3Sopenharmony_ci        }
2624514f5e3Sopenharmony_ci    }
2634514f5e3Sopenharmony_ci    auto bcSym = newSymtab + newSymIdx;
2644514f5e3Sopenharmony_ci    bcSym->st_name = 1;
2654514f5e3Sopenharmony_ci    bcSym->st_info = newSymtab[1].st_info;
2664514f5e3Sopenharmony_ci    bcSym->st_other = newSymtab[1].st_other;
2674514f5e3Sopenharmony_ci    bcSym->st_shndx = TEXT_HDR_IDX;
2684514f5e3Sopenharmony_ci    bcSym->st_value = info.bcStubBegin - info.textHdr->sh_offset;
2694514f5e3Sopenharmony_ci    ASSERT(info.bcStubEnd >= info.bcStubBegin);
2704514f5e3Sopenharmony_ci    bcSym->st_size = info.bcStubEnd - info.bcStubBegin;
2714514f5e3Sopenharmony_ci}
2724514f5e3Sopenharmony_ci
2734514f5e3Sopenharmony_civoid ConstructEhdrAndPhdr(Elf64_Ehdr *newEhdr, Elf64_Shdr *newShdrtab, uintptr_t baseAddr, const StubAnInfo &info)
2744514f5e3Sopenharmony_ci{
2754514f5e3Sopenharmony_ci    Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
2764514f5e3Sopenharmony_ci    {
2774514f5e3Sopenharmony_ci        *newEhdr = *info.ehdr;
2784514f5e3Sopenharmony_ci        newEhdr->e_flags = info.ehdr->e_flags;
2794514f5e3Sopenharmony_ci        newEhdr->e_machine = info.ehdr->e_machine;
2804514f5e3Sopenharmony_ci        if (memcpy_s(newEhdr->e_ident, sizeof(info.ehdr->e_ident),
2814514f5e3Sopenharmony_ci                     info.ehdr->e_ident, sizeof(info.ehdr->e_ident)) != EOK) {
2824514f5e3Sopenharmony_ci            return;
2834514f5e3Sopenharmony_ci        }
2844514f5e3Sopenharmony_ci        newEhdr->e_version = 1;
2854514f5e3Sopenharmony_ci        newEhdr->e_phoff = sizeof(Elf64_Ehdr);
2864514f5e3Sopenharmony_ci        newEhdr->e_shoff = reinterpret_cast<uintptr_t>(newShdrtab) - baseAddr;
2874514f5e3Sopenharmony_ci        newEhdr->e_ehsize = sizeof(Elf64_Ehdr);
2884514f5e3Sopenharmony_ci        newEhdr->e_phentsize = sizeof(Elf64_Phdr);
2894514f5e3Sopenharmony_ci        newEhdr->e_phnum = 1;
2904514f5e3Sopenharmony_ci        newEhdr->e_shentsize = sizeof(Elf64_Shdr);
2914514f5e3Sopenharmony_ci        newEhdr->e_shnum = HEADER_CNT;
2924514f5e3Sopenharmony_ci        newEhdr->e_shstrndx = SHSTRTAB_HDR_IDX;
2934514f5e3Sopenharmony_ci        newEhdr->e_type = ET_REL;
2944514f5e3Sopenharmony_ci        newEhdr->e_entry = 0;
2954514f5e3Sopenharmony_ci    }
2964514f5e3Sopenharmony_ci    uintptr_t textAddr = info.textHdr->sh_offset + info.fileAddr;
2974514f5e3Sopenharmony_ci    uint64_t textSize = info.asmstubHdr->sh_offset + info.asmstubHdr->sh_size - info.textHdr->sh_offset;
2984514f5e3Sopenharmony_ci    {
2994514f5e3Sopenharmony_ci        newPhdr->p_type = PT_LOAD;
3004514f5e3Sopenharmony_ci        newPhdr->p_flags = PF_X | PF_R;
3014514f5e3Sopenharmony_ci        newPhdr->p_offset = textAddr - info.fileAddr;
3024514f5e3Sopenharmony_ci        newPhdr->p_vaddr = textAddr;
3034514f5e3Sopenharmony_ci        newPhdr->p_paddr = textAddr;
3044514f5e3Sopenharmony_ci        newPhdr->p_filesz = textSize;
3054514f5e3Sopenharmony_ci        newPhdr->p_memsz = textSize;
3064514f5e3Sopenharmony_ci        newPhdr->p_align = 0x1000;
3074514f5e3Sopenharmony_ci    }
3084514f5e3Sopenharmony_ci}
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_civoid ConstructShdrTab(Elf64_Shdr *newShdrTab, Elf64_Sym *newSymtab, uintptr_t baseAddr, void *ehFrame,
3114514f5e3Sopenharmony_ci                      uint32_t ehFrameSize, const StubAnInfo &info)
3124514f5e3Sopenharmony_ci{
3134514f5e3Sopenharmony_ci    Elf64_Shdr hdr{};
3144514f5e3Sopenharmony_ci    Elf64_Shdr *emptyShdr = newShdrTab;
3154514f5e3Sopenharmony_ci    Elf64_Shdr *newShstrHdr = emptyShdr + 1;
3164514f5e3Sopenharmony_ci    Elf64_Shdr *newStrtabHdr = newShstrHdr + 1;
3174514f5e3Sopenharmony_ci    Elf64_Shdr *newSymHdr = newStrtabHdr + 1;
3184514f5e3Sopenharmony_ci    Elf64_Shdr *newTextHdr = newSymHdr + 1;
3194514f5e3Sopenharmony_ci    Elf64_Shdr *ehFrameHdr = newTextHdr + 1;
3204514f5e3Sopenharmony_ci    *emptyShdr = hdr;
3214514f5e3Sopenharmony_ci
3224514f5e3Sopenharmony_ci    newShstrHdr->sh_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr);
3234514f5e3Sopenharmony_ci    newShstrHdr->sh_size = sizeof(SHSTR);
3244514f5e3Sopenharmony_ci    newShstrHdr->sh_name = SHSTRTAB_NAME;
3254514f5e3Sopenharmony_ci    newShstrHdr->sh_addr = newStrtabHdr->sh_offset + baseAddr;
3264514f5e3Sopenharmony_ci    newShstrHdr->sh_type = SHT_STRTAB;
3274514f5e3Sopenharmony_ci    newShstrHdr->sh_flags = SHF_ALLOC;
3284514f5e3Sopenharmony_ci
3294514f5e3Sopenharmony_ci    newStrtabHdr->sh_offset = newShstrHdr->sh_offset + newShstrHdr->sh_size;
3304514f5e3Sopenharmony_ci    newStrtabHdr->sh_size = info.strtabHdr->sh_size;
3314514f5e3Sopenharmony_ci    newStrtabHdr->sh_name = STRTAB_NAME;
3324514f5e3Sopenharmony_ci    newStrtabHdr->sh_addr = newStrtabHdr->sh_offset + baseAddr;
3334514f5e3Sopenharmony_ci    newStrtabHdr->sh_addralign = 1;
3344514f5e3Sopenharmony_ci    newStrtabHdr->sh_type = SHT_STRTAB;
3354514f5e3Sopenharmony_ci    newStrtabHdr->sh_flags = SHF_ALLOC;
3364514f5e3Sopenharmony_ci    newStrtabHdr->sh_link = SHSTRTAB_HDR_IDX;
3374514f5e3Sopenharmony_ci
3384514f5e3Sopenharmony_ci    *newSymHdr = *info.symtabHdr;
3394514f5e3Sopenharmony_ci    newSymHdr->sh_offset = reinterpret_cast<uintptr_t>(newSymtab) - baseAddr;
3404514f5e3Sopenharmony_ci    newSymHdr->sh_size = info.symCnt * info.symtabHdr->sh_entsize;
3414514f5e3Sopenharmony_ci    newSymHdr->sh_entsize = info.symtabHdr->sh_entsize;
3424514f5e3Sopenharmony_ci    newSymHdr->sh_addralign = info.symtabHdr->sh_addralign;
3434514f5e3Sopenharmony_ci    newSymHdr->sh_name = SYMTAB_NAME;
3444514f5e3Sopenharmony_ci    newSymHdr->sh_addr = reinterpret_cast<uintptr_t>(newSymtab);
3454514f5e3Sopenharmony_ci    newSymHdr->sh_link = STRTAB_HDR_IDX;
3464514f5e3Sopenharmony_ci
3474514f5e3Sopenharmony_ci    newTextHdr->sh_offset = 0;
3484514f5e3Sopenharmony_ci    newTextHdr->sh_size = info.asmstubHdr->sh_offset + info.asmstubHdr->sh_size - info.textHdr->sh_offset;
3494514f5e3Sopenharmony_ci    newTextHdr->sh_name = TEXT_NAME;
3504514f5e3Sopenharmony_ci    newTextHdr->sh_addr = info.fileAddr + info.textHdr->sh_offset;
3514514f5e3Sopenharmony_ci    newTextHdr->sh_addralign = sizeof(uint32_t);
3524514f5e3Sopenharmony_ci    newTextHdr->sh_type = SHT_NOBITS;
3534514f5e3Sopenharmony_ci    newTextHdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
3544514f5e3Sopenharmony_ci    newTextHdr->sh_link = SYMTAB_HDR_IDX;
3554514f5e3Sopenharmony_ci
3564514f5e3Sopenharmony_ci    ehFrameHdr->sh_offset = reinterpret_cast<uintptr_t>(ehFrame) - baseAddr;
3574514f5e3Sopenharmony_ci    ehFrameHdr->sh_size = ehFrameSize;
3584514f5e3Sopenharmony_ci    ehFrameHdr->sh_name = EH_FRAME_NAME;
3594514f5e3Sopenharmony_ci    ehFrameHdr->sh_addr = reinterpret_cast<uintptr_t>(ehFrame);
3604514f5e3Sopenharmony_ci    ehFrameHdr->sh_addralign = sizeof(uintptr_t);
3614514f5e3Sopenharmony_ci    ehFrameHdr->sh_type = SHT_PROGBITS;
3624514f5e3Sopenharmony_ci    ehFrameHdr->sh_flags = SHF_ALLOC;
3634514f5e3Sopenharmony_ci    ehFrameHdr->sh_link = TEXT_HDR_IDX;
3644514f5e3Sopenharmony_ci}
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_cibool CreateDebuggerElf(uintptr_t fileAddr, void **result, uint64_t *elfSize)
3674514f5e3Sopenharmony_ci{
3684514f5e3Sopenharmony_ci    auto info = CollectStubAnInfo(fileAddr);
3694514f5e3Sopenharmony_ci    std::vector<uint8_t> ehFrame {
3704514f5e3Sopenharmony_ci            0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x78, 0x1e, 0x0, 0x0, 0x0,
3714514f5e3Sopenharmony_ci            0x0, 0x0, 0x0, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x73, 0xab,
3724514f5e3Sopenharmony_ci            0xff, 0xff, 0x0, 0x0, 0x30, 0x2c, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1d, 0x0, 0x10,
3734514f5e3Sopenharmony_ci            0x1e, 0x17, 0x8d, 0x0, 0x12, 0x8, 0x18, 0x1c, 0x6, 0x8, 0x0, 0x29, 0x28, 0x7, 0x0, 0x8,
3744514f5e3Sopenharmony_ci            0x10, 0x1c, 0x6, 0x2f, 0xee, 0xff, 0x8, 0x8, 0x22, 0x10, 0x1d, 0x17, 0x8d, 0x0, 0x12, 0x8,
3754514f5e3Sopenharmony_ci            0x18, 0x1c, 0x6, 0x8, 0x0, 0x29, 0x28, 0x7, 0x0, 0x8, 0x10, 0x1c, 0x6, 0x2f, 0xee, 0xff,
3764514f5e3Sopenharmony_ci            0x8, 0x0, 0x22,
3774514f5e3Sopenharmony_ci    };
3784514f5e3Sopenharmony_ci    const uint32_t addrOff = 28;
3794514f5e3Sopenharmony_ci    const uint32_t lenOff = 36;
3804514f5e3Sopenharmony_ci    auto writeU64 = [&ehFrame](uint32_t idx, uint64_t data) {
3814514f5e3Sopenharmony_ci        for (uint32_t i = 0; i < sizeof(uint64_t); i++) {
3824514f5e3Sopenharmony_ci            ehFrame[idx + i] = (data >> (8 * i)) & 0xff;
3834514f5e3Sopenharmony_ci        }
3844514f5e3Sopenharmony_ci    };
3854514f5e3Sopenharmony_ci    writeU64(addrOff, info.bcStubBegin + fileAddr);
3864514f5e3Sopenharmony_ci    ASSERT(info.bcStubEnd >= info.bcStubBegin);
3874514f5e3Sopenharmony_ci    writeU64(lenOff, info.bcStubEnd - info.bcStubBegin);
3884514f5e3Sopenharmony_ci
3894514f5e3Sopenharmony_ci    uint32_t totalSize = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) + sizeof(SHSTR) + info.strtabHdr->sh_size;
3904514f5e3Sopenharmony_ci    totalSize += info.symtabHdr->sh_entsize * info.symCnt + sizeof(Elf64_Sym); // for align
3914514f5e3Sopenharmony_ci    totalSize += ehFrame.size() + sizeof(uintptr_t);
3924514f5e3Sopenharmony_ci    totalSize += sizeof(Elf64_Shdr) * HEADER_CNT + sizeof(Elf64_Shdr); // for align
3934514f5e3Sopenharmony_ci
3944514f5e3Sopenharmony_ci    char *buffer = new char[totalSize];
3954514f5e3Sopenharmony_ci    Elf64_Ehdr *newEhdr = reinterpret_cast<Elf64_Ehdr *>(buffer);
3964514f5e3Sopenharmony_ci    Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
3974514f5e3Sopenharmony_ci    const char *shStrBuff = reinterpret_cast<const char *>(newPhdr + 1);
3984514f5e3Sopenharmony_ci    const char *newStrtab = shStrBuff + sizeof(SHSTR);
3994514f5e3Sopenharmony_ci    if (!CopyStrTab(reinterpret_cast<uintptr_t>(buffer), info)) {
4004514f5e3Sopenharmony_ci        delete[] buffer;
4014514f5e3Sopenharmony_ci        return false;
4024514f5e3Sopenharmony_ci    }
4034514f5e3Sopenharmony_ci
4044514f5e3Sopenharmony_ci    auto newSymtab = OffsetAlignUp<Elf64_Sym *>(newStrtab, info.strtabHdr->sh_size, info.symtabHdr->sh_addralign);
4054514f5e3Sopenharmony_ci    ConstructSymTab(newSymtab, info);
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_ci    auto ehFrameBuffer = OffsetAlignUp<char *>(newSymtab, info.symtabHdr->sh_entsize * info.symCnt, sizeof(uintptr_t));
4084514f5e3Sopenharmony_ci    if (memcpy_s(ehFrameBuffer, ehFrame.size(), ehFrame.data(), ehFrame.size()) != EOK) {
4094514f5e3Sopenharmony_ci        delete[] buffer;
4104514f5e3Sopenharmony_ci        return false;
4114514f5e3Sopenharmony_ci    }
4124514f5e3Sopenharmony_ci
4134514f5e3Sopenharmony_ci    auto newShdrtab = OffsetAlignUp<Elf64_Shdr *>(ehFrameBuffer, ehFrame.size(), sizeof(uintptr_t));
4144514f5e3Sopenharmony_ci    ConstructEhdrAndPhdr(newEhdr, newShdrtab, reinterpret_cast<uintptr_t>(buffer), info);
4154514f5e3Sopenharmony_ci    ConstructShdrTab(newShdrtab, newSymtab, reinterpret_cast<uintptr_t>(buffer), ehFrameBuffer, ehFrame.size(), info);
4164514f5e3Sopenharmony_ci
4174514f5e3Sopenharmony_ci    *result = reinterpret_cast<void *>(buffer);
4184514f5e3Sopenharmony_ci    *elfSize = totalSize;
4194514f5e3Sopenharmony_ci    return true;
4204514f5e3Sopenharmony_ci}
4214514f5e3Sopenharmony_ci
4224514f5e3Sopenharmony_cistatic bool RegisterStubAnToDebuggerImpl(const char *fileAddr)
4234514f5e3Sopenharmony_ci{
4244514f5e3Sopenharmony_ci    auto *entry = new jit_code_entry;
4254514f5e3Sopenharmony_ci    if (!CreateDebuggerElf(reinterpret_cast<uintptr_t>(fileAddr),
4264514f5e3Sopenharmony_ci        reinterpret_cast<void **>(const_cast<char **>(&entry->symfile_addr)), &entry->symfile_size)) {
4274514f5e3Sopenharmony_ci        delete entry;
4284514f5e3Sopenharmony_ci        return false;
4294514f5e3Sopenharmony_ci    }
4304514f5e3Sopenharmony_ci    entry->prev_entry = nullptr;
4314514f5e3Sopenharmony_ci    entry->file_addr = fileAddr;
4324514f5e3Sopenharmony_ci
4334514f5e3Sopenharmony_ci    // Insert this entry at the head of the list.
4344514f5e3Sopenharmony_ci    jit_code_entry *nextEntry = __jit_debug_descriptor.first_entry;
4354514f5e3Sopenharmony_ci    entry->next_entry = nextEntry;
4364514f5e3Sopenharmony_ci    if (nextEntry) {
4374514f5e3Sopenharmony_ci        nextEntry->prev_entry = entry;
4384514f5e3Sopenharmony_ci    }
4394514f5e3Sopenharmony_ci
4404514f5e3Sopenharmony_ci    __jit_debug_descriptor.first_entry = entry;
4414514f5e3Sopenharmony_ci    __jit_debug_descriptor.relevant_entry = entry;
4424514f5e3Sopenharmony_ci    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
4434514f5e3Sopenharmony_ci    __jit_debug_register_code();
4444514f5e3Sopenharmony_ci    return true;
4454514f5e3Sopenharmony_ci}
4464514f5e3Sopenharmony_ci
4474514f5e3Sopenharmony_ci}
4484514f5e3Sopenharmony_ci}
4494514f5e3Sopenharmony_ci#else
4504514f5e3Sopenharmony_cinamespace panda::ecmascript {
4514514f5e3Sopenharmony_cinamespace jit_debug {
4524514f5e3Sopenharmony_civoid RegisterStubAnToDebugger(const char *fileAddr)
4534514f5e3Sopenharmony_ci{
4544514f5e3Sopenharmony_ci    LOG_COMPILER(INFO) << "MACOS doesn't support RegisterStubAnToDebugger, fileAddr is" << fileAddr;
4554514f5e3Sopenharmony_ci}
4564514f5e3Sopenharmony_ci
4574514f5e3Sopenharmony_civoid UnregisterStubAnFromDebugger(const char *fileAddr)
4584514f5e3Sopenharmony_ci{
4594514f5e3Sopenharmony_ci    LOG_COMPILER(INFO) << "MACOS doesn't support RegisterStubAnToDebugger, fileAddr is" << fileAddr;
4604514f5e3Sopenharmony_ci}
4614514f5e3Sopenharmony_ci}
4624514f5e3Sopenharmony_ci}
4634514f5e3Sopenharmony_ci#endif
464