1 /*
2 * Copyright (c) 2023 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/compiler/aot_file/elf_builder.h"
17
18 #include "ecmascript/ecma_macros.h"
19 #include "securec.h"
20
21 namespace panda::ecmascript {
AddShStrTabSection()22 void ElfBuilder::AddShStrTabSection()
23 {
24 std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions =
25 des_[ShStrTableModuleDesIndex].GetSectionsInfo();
26
27 uint32_t size = 1;
28 for (auto &s : sections_) {
29 std::string str = ModuleSectionDes::GetSecName(s);
30 size = size + str.size() + 1;
31 }
32
33 shStrTabPtr_ = std::make_unique<char []>(size);
34 char *dst = shStrTabPtr_.get();
35 dst[0] = 0x0;
36 uint32_t i = 1;
37 for (auto &s: sections_) {
38 std::string str = ModuleSectionDes::GetSecName(s);
39 uint32_t copySize = str.size();
40 if (copySize == 0) {
41 UNREACHABLE();
42 }
43 if ((copySize != 0) && ((memcpy_s(dst + i, size - i + 1, str.data(), copySize)) != EOK)) {
44 UNREACHABLE();
45 }
46 dst[i + copySize] = 0x0;
47 i = i + copySize + 1;
48 }
49 if (sections.find(ElfSecName::SHSTRTAB) != sections.end()) {
50 sections.erase(ElfSecName::SHSTRTAB);
51 }
52 sections[ElfSecName::SHSTRTAB] = std::make_pair(reinterpret_cast<uint64_t>(shStrTabPtr_.get()), size);
53 if (enableSecDump_) {
54 DumpSection();
55 }
56 }
57
DumpSection() const58 void ElfBuilder::DumpSection() const
59 {
60 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
61 // dump
62 for (auto &s : sections) {
63 ElfSection section = ElfSection(s.first);
64 if (!section.ShouldDumpToAOTFile()) {
65 continue;
66 }
67 LOG_COMPILER(INFO) << "secname :" << std::dec << static_cast<int>(s.first)
68 << " addr:0x" << std::hex << s.second.first << " size:0x" << s.second.second << std::endl;
69 }
70 }
71
ElfBuilder(const std::vector<ModuleSectionDes> & des,const std::vector<ElfSecName> & sections)72 ElfBuilder::ElfBuilder(const std::vector<ModuleSectionDes> &des,
73 const std::vector<ElfSecName> §ions): des_(des), sections_(sections)
74 {
75 Initialize();
76 AddShStrTabSection();
77 RemoveNotNeedSection();
78 }
79
Initialize()80 void ElfBuilder::Initialize()
81 {
82 for (size_t i = 0; i < des_.size(); i++) {
83 des_[i].AddArkStackMapSection();
84 }
85 sectionToAlign_ = {
86 {ElfSecName::TEXT, AOTFileInfo::PAGE_ALIGN},
87 {ElfSecName::STRTAB, 1},
88 {ElfSecName::SYMTAB, AOTFileInfo::DATA_SEC_ALIGN},
89 {ElfSecName::SHSTRTAB, AOTFileInfo::DATA_SEC_ALIGN},
90 {ElfSecName::ARK_STACKMAP, AOTFileInfo::DATA_SEC_ALIGN},
91 {ElfSecName::ARK_FUNCENTRY, AOTFileInfo::DATA_SEC_ALIGN},
92 {ElfSecName::ARK_ASMSTUB, AOTFileInfo::DATA_SEC_ALIGN},
93 {ElfSecName::ARK_MODULEINFO, AOTFileInfo::DATA_SEC_ALIGN},
94 };
95
96 sectionToSegment_ = {
97 {ElfSecName::RODATA, ElfSecName::TEXT},
98 {ElfSecName::RODATA_CST4, ElfSecName::TEXT},
99 {ElfSecName::RODATA_CST8, ElfSecName::TEXT},
100 {ElfSecName::RODATA_CST16, ElfSecName::TEXT},
101 {ElfSecName::RODATA_CST32, ElfSecName::TEXT},
102 {ElfSecName::TEXT, ElfSecName::TEXT},
103 {ElfSecName::STRTAB, ElfSecName::DATA},
104 {ElfSecName::SYMTAB, ElfSecName::DATA},
105 {ElfSecName::SHSTRTAB, ElfSecName::DATA},
106 {ElfSecName::ARK_STACKMAP, ElfSecName::DATA},
107 {ElfSecName::ARK_FUNCENTRY, ElfSecName::DATA},
108 {ElfSecName::ARK_ASMSTUB, ElfSecName::TEXT},
109 {ElfSecName::ARK_MODULEINFO, ElfSecName::DATA},
110 };
111
112 segmentToFlag_ = {
113 {ElfSecName::TEXT, llvm::ELF::PF_X | llvm::ELF::PF_R},
114 {ElfSecName::DATA, llvm::ELF::PF_R},
115 };
116
117 SetLastSection();
118 }
119
RemoveNotNeedSection()120 void ElfBuilder::RemoveNotNeedSection()
121 {
122 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
123 for (size_t i = 0; i < sections_.size();) {
124 if (sections.find(sections_[i]) == sections.end()) {
125 auto it = sections_.begin() + i;
126 sections_.erase(it);
127 continue;
128 }
129 i++;
130 }
131 }
132
~ElfBuilder()133 ElfBuilder::~ElfBuilder()
134 {
135 shStrTabPtr_ = nullptr;
136 }
137
GetShIndex(ElfSecName section) const138 uint32_t ElfBuilder::GetShIndex(ElfSecName section) const
139 {
140 std::set<ElfSecName> secSet(sections_.begin(), sections_.end());
141 uint32_t idx = 1;
142 for (ElfSecName sec : secSet) {
143 if (sec == section) {
144 return idx;
145 }
146 idx++;
147 }
148 return -1;
149 }
150
GetSecNum() const151 int ElfBuilder::GetSecNum() const
152 {
153 return sections_.size() + 1; // add first empty section.
154 }
155
156 /*
157 ELF Header as follow:
158 ELF Header:
159 Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
160 Class: ELF64
161 Data: 2's complement, little endian
162 Version: 1 (current)
163 OS/ABI: UNIX - System V
164 ABI Version: 0
165 Type: DYN (Shared object file)
166 Machine: Advanced Micro Devices X86-64
167 Version: 0x4000001
168 Entry point address: 0x0
169 Start of program headers: 16384 (bytes into file)
170 Start of section headers: 64 (bytes into file)
171 Flags: 0x0
172 Size of this header: 64 (bytes)
173 Size of program headers: 56 (bytes)
174 Number of program headers: 2
175 Size of section headers: 64 (bytes)
176 Number of section headers: 7
177 Section header string table index: 3
178 */
PackELFHeader(llvm::ELF::Elf64_Ehdr & header,uint32_t version,Triple triple)179 void ElfBuilder::PackELFHeader(llvm::ELF::Elf64_Ehdr &header, uint32_t version, Triple triple)
180 {
181 if (memset_s(reinterpret_cast<void *>(&header), sizeof(llvm::ELF::Elf64_Ehdr), 0,
182 sizeof(llvm::ELF::Elf64_Ehdr)) != EOK) {
183 UNREACHABLE();
184 }
185 header.e_ident[llvm::ELF::EI_MAG0] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG0];
186 header.e_ident[llvm::ELF::EI_MAG1] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG1];
187 header.e_ident[llvm::ELF::EI_MAG2] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG2];
188 header.e_ident[llvm::ELF::EI_MAG3] = llvm::ELF::ElfMagic[llvm::ELF::EI_MAG3];
189 header.e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
190 header.e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
191 header.e_ident[llvm::ELF::EI_VERSION] = 1;
192
193 header.e_type = llvm::ELF::ET_DYN;
194 switch (triple) {
195 case Triple::TRIPLE_AMD64:
196 header.e_machine = llvm::ELF::EM_X86_64;
197 break;
198 case Triple::TRIPLE_ARM32:
199 header.e_machine = llvm::ELF::EM_ARM;
200 break;
201 case Triple::TRIPLE_AARCH64:
202 header.e_machine = llvm::ELF::EM_AARCH64;
203 break;
204 default:
205 UNREACHABLE();
206 break;
207 }
208 header.e_version = version;
209 // start of section headers
210 header.e_shoff = sizeof(llvm::ELF::Elf64_Ehdr);
211 // size of ehdr
212 header.e_ehsize = sizeof(llvm::ELF::Elf64_Ehdr);
213 // size of section headers
214 header.e_shentsize = sizeof(llvm::ELF::Elf64_Shdr);
215 // number of section headers
216 header.e_shnum = GetSecNum();
217 // section header string table index
218 header.e_shstrndx = static_cast<llvm::ELF::Elf64_Half>(GetShIndex(ElfSecName::SHSTRTAB));
219 // section header stub sec info index
220 header.e_flags = static_cast<llvm::ELF::Elf64_Word>(GetShIndex(ElfSecName::ARK_MODULEINFO));
221 // phr
222 header.e_phentsize = sizeof(llvm::ELF::Elf64_Phdr);
223 header.e_phnum = GetSegmentNum();
224 }
225
GetSegmentNum() const226 int ElfBuilder::GetSegmentNum() const
227 {
228 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
229 std::set<ElfSecName> segments;
230 for (auto &s: sections) {
231 ElfSection section = ElfSection(s.first);
232 if (!section.ShouldDumpToAOTFile()) {
233 continue;
234 }
235 auto it = sectionToSegment_.find(s.first);
236 ASSERT(it != sectionToSegment_.end());
237 ElfSecName name = it->second;
238 segments.insert(name);
239 }
240 return segments.size();
241 }
242
SetLastSection()243 void ElfBuilder::SetLastSection()
244 {
245 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
246 for (auto &s: sections) {
247 ElfSection section = ElfSection(s.first);
248 if (!section.ShouldDumpToAOTFile()) {
249 continue;
250 }
251 auto it = sectionToSegment_.find(s.first);
252 ASSERT(it != sectionToSegment_.end());
253 ElfSecName name = it->second;
254 if (name == ElfSecName::TEXT) {
255 lastCodeSection = std::max(lastCodeSection, s.first);
256 } else {
257 lastDataSection = std::max(lastDataSection, s.first);
258 }
259 }
260 }
261
FindShName(std::string name,uintptr_t strTabPtr,int strTabSize)262 llvm::ELF::Elf64_Word ElfBuilder::FindShName(std::string name, uintptr_t strTabPtr, int strTabSize)
263 {
264 llvm::ELF::Elf64_Word ans = -1;
265 int len = static_cast<int>(name.size());
266 if (strTabSize < len + 1) {
267 return ans;
268 }
269 LOG_ECMA(DEBUG) << " FindShName name:" << name.c_str() << std::endl;
270 for (int i = 0; i < strTabSize - len + 1; ++i) {
271 char *dst = reinterpret_cast<char *>(strTabPtr) + i;
272 if (name.compare(dst) == 0) {
273 return i;
274 }
275 }
276 return ans;
277 }
278
FindShStrTab() const279 std::pair<uint64_t, uint32_t> ElfBuilder::FindShStrTab() const
280 {
281 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
282 uint64_t shStrTabAddr = 0;
283 uint32_t shStrTabSize = 0;
284 for (auto &s: sections) {
285 uint32_t curSecSize = des_[ShStrTableModuleDesIndex].GetSecSize(s.first);
286 uint64_t curSecAddr = des_[ShStrTableModuleDesIndex].GetSecAddr(s.first);
287 if (s.first == ElfSecName::SHSTRTAB) {
288 shStrTabSize = curSecSize;
289 shStrTabAddr = curSecAddr;
290 break;
291 }
292 }
293 return std::make_pair(shStrTabAddr, shStrTabSize);
294 }
295
AllocateShdr(std::unique_ptr<llvm::ELF::Elf64_Shdr[]> & shdr,const uint32_t & secNum)296 void ElfBuilder::AllocateShdr(std::unique_ptr<llvm::ELF::Elf64_Shdr []> &shdr, const uint32_t &secNum)
297 {
298 shdr = std::make_unique<llvm::ELF::Elf64_Shdr []>(secNum);
299 if (memset_s(reinterpret_cast<void *>(&shdr[0]),
300 sizeof(llvm::ELF::Elf64_Shdr),
301 0,
302 sizeof(llvm::ELF::Elf64_Shdr)) != EOK) {
303 UNREACHABLE();
304 }
305 }
306
ComputeEndAddrOfShdr(const uint32_t & secNum) const307 llvm::ELF::Elf64_Off ElfBuilder::ComputeEndAddrOfShdr(const uint32_t &secNum) const
308 {
309 llvm::ELF::Elf64_Off curSecOffset = sizeof(llvm::ELF::Elf64_Ehdr) + secNum * sizeof(llvm::ELF::Elf64_Shdr);
310 curSecOffset = AlignUp(curSecOffset, PageSize()); // not pagesize align will cause performance degradation
311 return curSecOffset;
312 }
313
GetSegmentName(const ElfSecName & secName) const314 ElfSecName ElfBuilder::GetSegmentName(const ElfSecName &secName) const
315 {
316 auto it = sectionToSegment_.find(secName);
317 ASSERT(it != sectionToSegment_.end());
318 ElfSecName segName = it->second;
319 return segName;
320 }
321
MergeTextSections(std::ofstream & file,std::vector<ModuleSectionDes::ModuleRegionInfo> & moduleInfo,llvm::ELF::Elf64_Off & curSecOffset)322 void ElfBuilder::MergeTextSections(std::ofstream &file,
323 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
324 llvm::ELF::Elf64_Off &curSecOffset)
325 {
326 for (size_t i = 0; i < des_.size(); ++i) {
327 ModuleSectionDes &des = des_[i];
328 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
329 uint32_t curSecSize = des.GetSecSize(ElfSecName::TEXT);
330 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::TEXT);
331 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
332 file.seekp(curSecOffset);
333 auto curModuleSec = des.GetSectionsInfo();
334 uint64_t rodataAddrBeforeText = 0;
335 uint32_t rodataSizeBeforeText = 0;
336 uint64_t rodataAddrAfterText = 0;
337 uint32_t rodataSizeAfterText = 0;
338 std::tie(rodataAddrBeforeText, rodataSizeBeforeText, rodataAddrAfterText, rodataSizeAfterText) =
339 des.GetMergedRODataAddrAndSize(curSecAddr);
340 if (rodataSizeBeforeText != 0) {
341 file.write(reinterpret_cast<char *>(rodataAddrBeforeText), rodataSizeBeforeText);
342 curInfo.rodataSizeBeforeText = rodataSizeBeforeText;
343 curSecOffset += rodataSizeBeforeText;
344 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::TEXT_SEC_ALIGN);
345 file.seekp(curSecOffset);
346 }
347 stubTextOffset_.emplace_back(curSecOffset);
348 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
349 curInfo.textSize = curSecSize;
350 curSecOffset += curSecSize;
351 if (rodataSizeAfterText != 0) {
352 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::DATA_SEC_ALIGN);
353 file.seekp(curSecOffset);
354 file.write(reinterpret_cast<char *>(rodataAddrAfterText), rodataSizeAfterText);
355 curInfo.rodataSizeAfterText = rodataSizeAfterText;
356 curSecOffset += rodataSizeAfterText;
357 }
358 }
359 }
360
MergeStrtabSections(std::ofstream & file,std::vector<ModuleSectionDes::ModuleRegionInfo> & moduleInfo,llvm::ELF::Elf64_Off & curSecOffset)361 void ElfBuilder::MergeStrtabSections(std::ofstream &file,
362 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
363 llvm::ELF::Elf64_Off &curSecOffset)
364 {
365 for (size_t i = 0; i < des_.size(); ++i) {
366 ModuleSectionDes &des = des_[i];
367 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
368 uint32_t curSecSize = des.GetSecSize(ElfSecName::STRTAB);
369 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::STRTAB);
370 curInfo.strtabSize = curSecSize;
371 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
372 curSecOffset += curSecSize;
373 }
374 }
375
MergeSymtabSections(std::ofstream & file,std::vector<ModuleSectionDes::ModuleRegionInfo> & moduleInfo,llvm::ELF::Elf64_Off & curSecOffset)376 void ElfBuilder::MergeSymtabSections(std::ofstream &file,
377 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
378 llvm::ELF::Elf64_Off &curSecOffset)
379 {
380 for (size_t i = 0; i < des_.size(); ++i) {
381 ModuleSectionDes &des = des_[i];
382 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
383 uint32_t curSecSize = des.GetSecSize(ElfSecName::SYMTAB);
384 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::SYMTAB);
385 curInfo.symtabSize = curSecSize;
386 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
387 curSecOffset += curSecSize;
388 }
389 }
390
MergeArkStackMapSections(std::ofstream & file,std::vector<ModuleSectionDes::ModuleRegionInfo> & moduleInfo,llvm::ELF::Elf64_Off & curSecOffset)391 void ElfBuilder::MergeArkStackMapSections(std::ofstream &file,
392 std::vector<ModuleSectionDes::ModuleRegionInfo> &moduleInfo,
393 llvm::ELF::Elf64_Off &curSecOffset)
394 {
395 for (size_t i = 0; i < des_.size(); ++i) {
396 ModuleSectionDes &des = des_[i];
397 ModuleSectionDes::ModuleRegionInfo &curInfo = moduleInfo[i];
398 uint32_t curSecSize = des.GetSecSize(ElfSecName::ARK_STACKMAP);
399 uint64_t curSecAddr = des.GetSecAddr(ElfSecName::ARK_STACKMAP);
400 uint32_t index = des.GetStartIndex();
401 uint32_t cnt = des.GetFuncCount();
402 curInfo.startIndex = index;
403 curInfo.funcCount = cnt;
404 curInfo.stackMapSize = curSecSize;
405 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
406 curSecOffset += curSecSize;
407 }
408 }
409
FixSymtab(llvm::ELF::Elf64_Shdr * shdr)410 void ElfBuilder::FixSymtab(llvm::ELF::Elf64_Shdr* shdr)
411 {
412 using Elf64_Sym = llvm::ELF::Elf64_Sym;
413 ASSERT(stubTextOffset_.size() == des_.size());
414
415 uint32_t secNum = static_cast<uint32_t>(GetSecNum());
416 uint32_t shStrTabIndex = GetShIndex(ElfSecName::SHSTRTAB);
417 uint32_t strTabIndex = GetShIndex(ElfSecName::STRTAB);
418 uint32_t textSecIndex = GetShIndex(ElfSecName::TEXT);
419
420 uint32_t strTabSize = 0;
421 int firstGlobal = -1;
422 uint32_t count = 0;
423
424 for (size_t idx = 0; idx < des_.size(); ++idx) {
425 uint32_t secSize = des_[idx].GetSecSize(ElfSecName::SYMTAB);
426 uint64_t secAddr = des_[idx].GetSecAddr(ElfSecName::SYMTAB);
427 Elf64_Sym *syms = reinterpret_cast<Elf64_Sym*>(secAddr);
428 size_t n = secSize / sizeof(Elf64_Sym);
429 for (size_t i = 0; i < n; ++i) {
430 Elf64_Sym* sy = &syms[i];
431 if (sy->getBinding() == llvm::ELF::STB_GLOBAL && firstGlobal == -1) {
432 firstGlobal = static_cast<int>(count);
433 }
434 if (sy->getType() == llvm::ELF::STT_SECTION) {
435 sy->st_shndx = static_cast<uint16_t>(shStrTabIndex);
436 } else if (sy->getType() == llvm::ELF::STT_FUNC) {
437 sy->st_shndx = static_cast<uint16_t>(textSecIndex);
438 sy->st_value += stubTextOffset_[idx];
439 }
440 if (sy->st_shndx > secNum) {
441 sy->st_shndx = 0;
442 }
443 sy->st_name += strTabSize;
444 count++;
445 }
446 strTabSize += des_[idx].GetSecSize(ElfSecName::STRTAB);
447 }
448 shdr->sh_info = static_cast<uint32_t>(firstGlobal);
449 shdr->sh_link = strTabIndex;
450 }
451
452 /*
453
454 section of aot.an layout as follows:
455 There are 7 section headers, starting at offset 0x40:
456
457 Section Headers:
458 [Nr] Name Type Address Offset Size EntSize Flags Link Info Align
459 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
460 [ 1] .text PROGBITS 0000000000001000 00001000 0000000000000f61 0000000000000000 AX 0 0 16
461 [ 2] .strtab STRTAB 0000000000002000 00002000 0000000000000187 0000000000000000 A 0 0 1
462 [ 3] .symtab SYMTAB 0000000000002188 00002188 00000000000001c8 0000000000000018 A 1 0 8
463 [ 4] .shstrtab STRTAB 0000000000002350 00002350 000000000000003f 0000000000000000 A 0 0 8
464 [ 5] .ark_funcentry PROGBITS 0000000000002390 00002390 00000000000006c0 0000000000000000 A 0 0 8
465 [ 6] .ark_stackmaps PROGBITS 0000000000002a50 00002a50 000000000000070e 0000000000000000 A 0 0 8
466
467 section of stub.an layout as follows:
468 There are 7 section headers, starting at offset 0x40:
469
470 [Nr] Name Type Address Offset Size EntSize Flags Link Info Align
471 [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
472 [ 1] .text PROGBITS 0000000000001000 00001000 000000000008225e 0000000000000000 AX 0 0 16
473 [ 2] .ark_asmstub PROGBITS 0000000000083260 00083260 0000000000002dc0 0000000000000000 AX 0 0 8
474 [ 3] .shstrtab STRTAB 0000000000087000 00087000 000000000000004c 0000000000000000 A 0 0 8
475 [ 4] .ark_funcentry PROGBITS 0000000000087050 00087050 0000000000023ca0 0000000000000000 A 0 0 8
476 [ 5] .ark_stackmaps PROGBITS 00000000000aacf0 000aacf0 0000000000011e90 0000000000000000 A 0 0 8
477 [ 6] .ark_moduleinfo PROGBITS 00000000000bcb80 000bcb80 000000000000003c 0000000000000000 A 0 0 8
478
479 Key to Flags:
480 W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
481 L (link order), O (extra OS processing required), G (group), T (TLS),
482 C (compressed), x (unknown), o (OS specific), E (exclude),
483 D (mbind), l (large), p (processor specific)
484 */
PackELFSections(std::ofstream & file)485 void ElfBuilder::PackELFSections(std::ofstream &file)
486 {
487 uint32_t moduleNum = des_.size();
488 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
489 uint32_t secNum = sections.size() + 1; // 1 : section id = 0 is null section
490 std::unique_ptr<llvm::ELF::Elf64_Shdr []> shdr;
491 AllocateShdr(shdr, secNum);
492 std::vector<ModuleSectionDes::ModuleRegionInfo> moduleInfo(moduleNum);
493 llvm::ELF::Elf64_Off curSecOffset = ComputeEndAddrOfShdr(secNum);
494 file.seekp(curSecOffset);
495
496 int i = static_cast<int>(GetShIndex(ElfSecName::TEXT));
497 auto shStrTab = FindShStrTab();
498
499 for (auto const &[secName, secInfo] : sections) {
500 auto &curShdr = shdr[i];
501 ElfSection section = ElfSection(secName);
502 if (!section.ShouldDumpToAOTFile()) {
503 continue;
504 }
505 curShdr.sh_addralign = sectionToAlign_[secName];
506 curSecOffset = AlignUp(curSecOffset, curShdr.sh_addralign);
507 file.seekp(curSecOffset);
508 ElfSecName segName = GetSegmentName(secName);
509 segments_.insert(segName);
510 std::string secNameStr = ModuleSectionDes::GetSecName(secName);
511 // text section address needs 16 bytes alignment
512 if (secName == ElfSecName::TEXT) {
513 curSecOffset = AlignUp(curSecOffset, AOTFileInfo::PAGE_ALIGN);
514 file.seekp(curSecOffset);
515 }
516 llvm::ELF::Elf64_Word shName = FindShName(secNameStr, shStrTab.first, shStrTab.second);
517 ASSERT(shName != static_cast<llvm::ELF::Elf64_Word>(-1));
518 curShdr.sh_name = shName;
519 curShdr.sh_type = section.Type();
520 curShdr.sh_flags = section.Flag();
521 curShdr.sh_addr = curSecOffset;
522 curShdr.sh_offset = static_cast<uint64_t>(curSecOffset);
523 curShdr.sh_info = 0;
524 curShdr.sh_link = static_cast<uint32_t>(section.Link());
525 sectionToFileOffset_[secName] = static_cast<uintptr_t>(file.tellp());
526 switch (secName) {
527 case ElfSecName::ARK_MODULEINFO: {
528 uint32_t curSecSize = sizeof(ModuleSectionDes::ModuleRegionInfo) * moduleInfo.size();
529 file.write(reinterpret_cast<char *>(moduleInfo.data()), curSecSize);
530 curSecOffset += curSecSize;
531 curShdr.sh_size = curSecSize;
532 break;
533 }
534 case ElfSecName::TEXT: {
535 uint32_t curSize = curSecOffset;
536 MergeTextSections(file, moduleInfo, curSecOffset);
537 curShdr.sh_size = curSecOffset - curSize;
538 break;
539 }
540 case ElfSecName::ARK_STACKMAP: {
541 uint32_t curSize = curSecOffset;
542 MergeArkStackMapSections(file, moduleInfo, curSecOffset);
543 curShdr.sh_size = curSecOffset - curSize;
544 break;
545 }
546 case ElfSecName::STRTAB: {
547 uint32_t curSize = curSecOffset;
548 MergeStrtabSections(file, moduleInfo, curSecOffset);
549 curShdr.sh_size = curSecOffset - curSize;
550 break;
551 }
552 case ElfSecName::SYMTAB: {
553 FixSymtab(&curShdr);
554 uint32_t curSize = curSecOffset;
555 MergeSymtabSections(file, moduleInfo, curSecOffset);
556 curShdr.sh_size = curSecOffset - curSize;
557 break;
558 }
559 case ElfSecName::SHSTRTAB:
560 case ElfSecName::ARK_FUNCENTRY:
561 case ElfSecName::ARK_ASMSTUB: {
562 uint32_t curSecSize = des_[FullSecIndex].GetSecSize(secName);
563 uint64_t curSecAddr = des_[FullSecIndex].GetSecAddr(secName);
564 file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
565 curSecOffset += curSecSize;
566 curShdr.sh_size = curSecSize;
567 break;
568 }
569 default: {
570 LOG_ECMA(FATAL) << "this section should not dump to an file";
571 break;
572 }
573 }
574 if (secName == lastDataSection || secName == lastCodeSection) {
575 curSecOffset = AlignUp(curSecOffset, PageSize());
576 file.seekp(curSecOffset);
577 }
578 curShdr.sh_entsize = static_cast<uint64_t>(section.Entsize());
579 sectionToShdr_[secName] = curShdr;
580 LOG_COMPILER(DEBUG) << " shdr[i].sh_entsize " << std::hex << curShdr.sh_entsize << std::endl;
581 ++i;
582 }
583 uint32_t secEnd = static_cast<uint32_t>(file.tellp());
584 file.seekp(sizeof(llvm::ELF::Elf64_Ehdr));
585 file.write(reinterpret_cast<char *>(shdr.get()), secNum * sizeof(llvm::ELF::Elf64_Shdr));
586 file.seekp(secEnd);
587 }
588
GetPFlag(ElfSecName segment) const589 unsigned ElfBuilder::GetPFlag(ElfSecName segment) const
590 {
591 return segmentToFlag_.at(segment);
592 }
593
594 /*
595 segment layout as follows:
596 An Elf file
597 Entry point 0x0
598 There are 2 program headers, starting at offset 16384
599
600 Program Headers:
601 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align
602 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000000f61 0x0000000000001000 R E 0x1000
603 LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000 0x000000000000115e 0x0000000000002000 R 0x1000
604
605 Section to Segment mapping:
606 Segment Sections...
607 00 .text
608 01 .strtab .symtab .shstrtab .ark_funcentry .ark_stackmaps
609 ------------------------------------------------------------------------------------------------------------------------------
610 Stub Elf file
611 Entry point 0x0
612 There are 2 program headers, starting at offset 770048
613
614 Program Headers:
615 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align
616 LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 0x0000000000085020 0x0000000000086000 R E 0x1000
617 LOAD 0x0000000000087000 0x0000000000087000 0x0000000000087000 0x0000000000035bbc 0x0000000000036000 R 0x1000
618
619 Section to Segment mapping:
620 Segment Sections...
621 00 .text .ark_asmstub
622 01 .shstrtab .ark_funcentry .ark_stackmaps .ark_moduleinfo
623 */
PackELFSegment(std::ofstream & file)624 void ElfBuilder::PackELFSegment(std::ofstream &file)
625 {
626 llvm::ELF::Elf64_Off e_phoff = static_cast<uint64_t>(file.tellp());
627 long phoff = (long)offsetof(struct llvm::ELF::Elf64_Ehdr, e_phoff);
628 // write Elf32_Off e_phoff
629 file.seekp(phoff);
630 file.write(reinterpret_cast<char *>(&e_phoff), sizeof(e_phoff));
631 file.seekp(static_cast<long>(e_phoff));
632
633 int segNum = GetSegmentNum();
634 auto phdrs = std::make_unique<llvm::ELF::Elf64_Phdr []>(segNum);
635 std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxOffset;
636 std::map<ElfSecName, llvm::ELF::Elf64_Off> segmentToMaxAddress;
637 std::set<ElfSecName> segments;
638 // SecName -> addr & size
639 const std::map<ElfSecName, std::pair<uint64_t, uint32_t>> §ions = GetFullSecInfo();
640 llvm::ELF::Elf64_Off offset = e_phoff;
641 for (auto &s: sections) {
642 ElfSection section = ElfSection(s.first);
643 if (!section.ShouldDumpToAOTFile()) {
644 continue;
645 }
646 auto it = sectionToSegment_.find(s.first);
647 ASSERT(it != sectionToSegment_.end());
648 ElfSecName segName = it->second;
649 segments.insert(segName);
650 if (segmentToMaxOffset.find(segName) == segmentToMaxOffset.end()) {
651 segmentToMaxOffset[segName] = 0;
652 }
653 segmentToMaxOffset[segName] =
654 std::max(segmentToMaxOffset[segName], sectionToShdr_[s.first].sh_offset + sectionToShdr_[s.first].sh_size);
655 segmentToMaxAddress[segName] =
656 std::max(segmentToMaxAddress[segName], sectionToShdr_[s.first].sh_addr + sectionToShdr_[s.first].sh_size);
657 offset = std::min(offset, sectionToShdr_[s.first].sh_offset);
658 }
659 int phdrIndex = 0;
660 llvm::ELF::Elf64_Addr addr = offset;
661 for (auto &it: segments) {
662 ElfSecName name = it;
663 phdrs[phdrIndex].p_align = PageSize();
664 phdrs[phdrIndex].p_type = llvm::ELF::PT_LOAD;
665 phdrs[phdrIndex].p_flags = GetPFlag(name);
666 offset = AlignUp(offset, PageSize());
667 phdrs[phdrIndex].p_offset = offset;
668 phdrs[phdrIndex].p_vaddr = addr % phdrs[phdrIndex].p_align == 0 ?
669 addr : (addr / phdrs[phdrIndex].p_align + 1) * phdrs[phdrIndex].p_align;
670 phdrs[phdrIndex].p_paddr = phdrs[phdrIndex].p_vaddr;
671
672 phdrs[phdrIndex].p_filesz = segmentToMaxOffset[name] - phdrs[phdrIndex].p_offset;
673 phdrs[phdrIndex].p_memsz = segmentToMaxAddress[name] - phdrs[phdrIndex].p_vaddr;
674 phdrs[phdrIndex].p_memsz = AlignUp(phdrs[phdrIndex].p_memsz, PageSize());
675 addr = phdrs[phdrIndex].p_vaddr + phdrs[phdrIndex].p_memsz;
676 offset += phdrs[phdrIndex].p_filesz;
677 ++phdrIndex;
678 }
679 file.write(reinterpret_cast<char *>(phdrs.get()), sizeof(llvm::ELF::Elf64_Phdr) * segNum);
680 }
681 } // namespace panda::ecmascript
682