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
18 namespace panda::ecmascript {
19
Initx86ElfHeader()20 void 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
InitArmElfHeader()47 void 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
UpdateSectionOffset(Section §ion)74 void JsJitDumpElf::UpdateSectionOffset(Section §ion)
75 {
76 if (section.GetType() != SHT_NOBITS) {
77 section.SetOffset(globalOffset);
78 } else {
79 section.SetOffset(0);
80 }
81 }
82
UpdateGlobalOffset(Section §ion)83 void JsJitDumpElf::UpdateGlobalOffset(Section §ion)
84 {
85 if (section.GetType() != SHT_NOBITS) {
86 globalOffset += section.GetSectionSize();
87 }
88 }
89
LayoutSections()90 void 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
RegisterSection(Section §ion)114 void JsJitDumpElf::RegisterSection(Section §ion)
115 {
116 sections.push_back(§ion);
117 section.SetIndex(static_cast<maplebe::SectionIndex>(sections.size() - 1));
118 }
119
Init()120 void 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
AppendData(std::vector<uint8> &codeBuff)132 void JsJitDumpElf::AppendData(std::vector<uint8> &codeBuff)
133 {
134 textSection->AppendData(codeBuff.data(), codeBuff.size());
135 }
136
AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx)137 void JsJitDumpElf::AddSymToSymTab(const maplebe::Symbol &symbol, int64 symIdx)
138 {
139 localSymTab.push_back(std::make_pair(symbol, symIdx));
140 }
141
AppendGlobalSymsToSymTabSec()142 void 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
AppendSymbolToSymTab(int64 symIdx, uint64 funcSymValue, uint64 funcSymSize, const std::string &symbolName)152 void 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
SetFileOffset(int fd, uint64 offset)162 void JsJitDumpElf::SetFileOffset(int fd, uint64 offset)
163 {
164 lseek(fd, offset, SEEK_SET);
165 }
166
WriteJitElfFile(int fd)167 void 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
ClearData()190 void 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