1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/dfx/dump_code/jit_dump_elf.h" 17 18namespace panda::ecmascript { 19 20void JsJitDumpElf::Initx86ElfHeader() 21{ 22 header.e_ident[EI_MAG0] = ELFMAG0; 23 header.e_ident[EI_MAG1] = ELFMAG1; 24 header.e_ident[EI_MAG2] = ELFMAG2; 25 header.e_ident[EI_MAG3] = ELFMAG3; 26 header.e_ident[EI_CLASS] = ELFCLASS64; 27 header.e_ident[EI_DATA] = ELFDATA2LSB; 28 header.e_ident[EI_VERSION] = EV_CURRENT; 29 header.e_ident[EI_OSABI] = ELFOSABI_NONE; /* ELFOSABI_NONE represents UNIX System V */ 30 header.e_ident[EI_ABIVERSION] = 0; 31 (void)std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0); 32 header.e_type = ET_REL; 33 header.e_machine = EM_X86_64; 34 header.e_version = EV_CURRENT; 35 header.e_entry = 0; 36 header.e_phoff = 0; 37 header.e_shoff = 0; /* later get */ 38 header.e_flags = 0; /* The Intel architecture defines no flags; so this member contains zero. */ 39 header.e_ehsize = sizeof(maplebe::FileHeader); 40 header.e_phentsize = 0; 41 header.e_phnum = 0; 42 header.e_shentsize = sizeof(maplebe::SectionHeader); 43 header.e_shnum = static_cast<uint16>(sections.size()); 44 header.e_shstrndx = strTabSection->GetIndex(); 45} 46 47void JsJitDumpElf::InitArmElfHeader() 48{ 49 header.e_ident[EI_MAG0] = ELFMAG0; 50 header.e_ident[EI_MAG1] = ELFMAG1; 51 header.e_ident[EI_MAG2] = ELFMAG2; 52 header.e_ident[EI_MAG3] = ELFMAG3; 53 header.e_ident[EI_CLASS] = ELFCLASS64; 54 header.e_ident[EI_DATA] = ELFDATA2LSB; 55 header.e_ident[EI_VERSION] = EV_CURRENT; 56 header.e_ident[EI_OSABI] = ELFOSABI_LINUX; 57 header.e_ident[EI_ABIVERSION] = 0; 58 std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0); 59 header.e_type = ET_REL; 60 header.e_version = 1; 61 header.e_machine = EM_AARCH64; 62 header.e_flags = 0; 63 header.e_entry = 0; 64 header.e_ehsize = sizeof(maplebe::FileHeader); 65 header.e_phentsize = sizeof(maplebe::SegmentHeader); 66 header.e_shentsize = sizeof(maplebe::SectionHeader); 67 header.e_shstrndx = strTabSection->GetIndex(); 68 header.e_shoff = 0; 69 header.e_phoff = 0; 70 header.e_shnum = sections.size(); 71 header.e_phnum = 0; 72} 73 74void JsJitDumpElf::UpdateSectionOffset(Section §ion) 75{ 76 if (section.GetType() != SHT_NOBITS) { 77 section.SetOffset(globalOffset); 78 } else { 79 section.SetOffset(0); 80 } 81} 82 83void JsJitDumpElf::UpdateGlobalOffset(Section §ion) 84{ 85 if (section.GetType() != SHT_NOBITS) { 86 globalOffset += section.GetSectionSize(); 87 } 88} 89 90void JsJitDumpElf::LayoutSections() 91{ 92 globalOffset = sizeof(maplebe::FileHeader); 93 globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, k8Bits); 94 95 for (auto *section : sections) { 96 section->SetSectionHeaderNameIndex(static_cast<maplebe::Word>(strTabSection->AddString(section->GetName()))); 97 } 98 99 for (auto *section : sections) { 100 globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, section->GetAlign()); 101 /* lay out section */ 102 UpdateSectionOffset(*section); 103 if (section->GetType() != SHT_NOBITS) { 104 section->GenerateData(); 105 } 106 UpdateGlobalOffset(*section); 107 } 108 109 globalOffset = Alignment::Align<maplebe::Offset>(globalOffset, 16U); 110 header.e_shoff = globalOffset; 111 header.e_shnum = static_cast<uint16>(sections.size()); 112} 113 114void JsJitDumpElf::RegisterSection(Section §ion) 115{ 116 sections.push_back(§ion); 117 section.SetIndex(static_cast<maplebe::SectionIndex>(sections.size() - 1)); 118} 119 120void JsJitDumpElf::Init() 121{ 122 DataSection *nullDataSection = new DataSection(" ", SHT_NULL, 0, 0); 123 RegisterSection(*nullDataSection); 124 strTabSection = new StringSection(".strtab", SHT_STRTAB, 0, 1); 125 RegisterSection(*strTabSection); 126 textSection = new DataSection(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, k8Bits); 127 RegisterSection(*textSection); 128 symbolTabSection = new SymbolSection(".symtab", SHT_SYMTAB, 0, k8Bits, *strTabSection); 129 RegisterSection(*symbolTabSection); 130} 131 132void JsJitDumpElf::AppendData(std::vector<uint8> &codeBuff) 133{ 134 textSection->AppendData(codeBuff.data(), codeBuff.size()); 135} 136 137void JsJitDumpElf::AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx) 138{ 139 localSymTab.push_back(std::make_pair(symbol, symIdx)); 140} 141 142void JsJitDumpElf::AppendGlobalSymsToSymTabSec() 143{ 144 for (auto elem : localSymTab) { 145 const maplebe::Symbol &symbol = elem.first; 146 int64 symIdx = elem.second; 147 symbolTabSection->AppendSymbol(symbol); 148 symbolTabSection->AppendIdxInSymbols(symIdx); 149 } 150} 151 152void JsJitDumpElf::AppendSymbolToSymTab(int64 symIdx, uint64 funcSymValue, uint64 funcSymSize, 153 const std::string &symbolName) 154{ 155 uint8 funcSymType = STB_GLOBAL; 156 auto nameIndex = strTabSection->AddString(symbolName); 157 AddSymToSymTab({static_cast<maplebe::Word>(nameIndex), 158 static_cast<uint8>((funcSymType << kLeftShift4Bits) + (STT_FUNC & 0xf)), 0, textSection->GetIndex(), 159 funcSymValue, funcSymSize}, symIdx); 160} 161 162void JsJitDumpElf::SetFileOffset(int fd, uint64 offset) 163{ 164 lseek(fd, offset, SEEK_SET); 165} 166 167void JsJitDumpElf::WriteJitElfFile(int fd) 168{ 169 AppendGlobalSymsToSymTabSec(); 170 /* Init elf file header */ 171 InitArmElfHeader(); 172 LayoutSections(); 173 /* write header */ 174 (void)write(fd, reinterpret_cast<const char *>(&header), sizeof(header)); 175 /* write sections */ 176 for (auto *section : sections) { 177 if (section->GetType() == SHT_NOBITS) { 178 continue; 179 } 180 SetFileOffset(fd, section->GetOffset()); 181 section->WriteSection(fd); 182 } 183 SetFileOffset(fd, header.e_shoff); 184 /* write section table */ 185 for (auto *section : sections) { 186 (void)write(fd, §ion->GetSectionHeader(), sizeof(section->GetSectionHeader())); 187 } 188} 189 190void JsJitDumpElf::ClearData() 191{ 192 localSymTab.clear(); 193 globalOffset = 0; 194 textSection->ClearData(); 195 symbolTabSection->ClearData(); 196 strTabSection->ClearData(); 197 sections.clear(); 198} 199 200} // namespace panda::ecmascript 201