OLD | NEW |
1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// | 1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 uint32_t getELFFlags(TargetArch Arch) { | 67 uint32_t getELFFlags(TargetArch Arch) { |
68 if (Arch < TargetArch_NUM) | 68 if (Arch < TargetArch_NUM) |
69 return ELFTargetInfo[Arch].ELFFlags; | 69 return ELFTargetInfo[Arch].ELFFlags; |
70 llvm_unreachable("Invalid target arch for getELFFlags"); | 70 llvm_unreachable("Invalid target arch for getELFFlags"); |
71 return 0; | 71 return 0; |
72 } | 72 } |
73 | 73 |
74 } // end of anonymous namespace | 74 } // end of anonymous namespace |
75 | 75 |
76 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out) | 76 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out) |
77 : Ctx(Ctx), Str(Out), ELF64(isELF64(Ctx.getFlags())) { | 77 : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) { |
78 // Create the special bookkeeping sections now. | 78 // Create the special bookkeeping sections now. |
79 constexpr char NullSectionName[] = ""; | 79 constexpr char NullSectionName[] = ""; |
80 NullSection = new (Ctx.allocate<ELFSection>()) | 80 NullSection = new (Ctx.allocate<ELFSection>()) |
81 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0); | 81 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0); |
82 | 82 |
83 constexpr char ShStrTabName[] = ".shstrtab"; | 83 constexpr char ShStrTabName[] = ".shstrtab"; |
84 ShStrTab = new (Ctx.allocate<ELFStringTableSection>()) | 84 ShStrTab = new (Ctx.allocate<ELFStringTableSection>()) |
85 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0); | 85 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0); |
86 ShStrTab->add(ShStrTabName); | 86 ShStrTab->add(ShStrTabName); |
87 | 87 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 return OffsetInFile; | 216 return OffsetInFile; |
217 } | 217 } |
218 | 218 |
219 void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal, | 219 void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal, |
220 Assembler *Asm) { | 220 Assembler *Asm) { |
221 assert(!SectionNumbersAssigned); | 221 assert(!SectionNumbersAssigned); |
222 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty()); | 222 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty()); |
223 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | 223 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
224 ELFTextSection *Section = nullptr; | 224 ELFTextSection *Section = nullptr; |
225 ELFRelocationSection *RelSection = nullptr; | 225 ELFRelocationSection *RelSection = nullptr; |
226 const bool FunctionSections = Ctx.getFlags().getFunctionSections(); | 226 const bool FunctionSections = getFlags().getFunctionSections(); |
227 if (TextSections.empty() || FunctionSections) { | 227 if (TextSections.empty() || FunctionSections) { |
228 std::string SectionName = ".text"; | 228 std::string SectionName = ".text"; |
229 if (FunctionSections) | 229 if (FunctionSections) |
230 SectionName += "." + FuncName; | 230 SectionName += "." + FuncName; |
231 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; | 231 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; |
232 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes(); | 232 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes(); |
233 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, | 233 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, |
234 ShAlign, 0); | 234 ShAlign, 0); |
235 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); | 235 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); |
236 Section->setFileOffset(OffsetInFile); | 236 Section->setFileOffset(OffsetInFile); |
237 TextSections.push_back(Section); | 237 TextSections.push_back(Section); |
238 RelSection = createRelocationSection(Section); | 238 RelSection = createRelocationSection(Section); |
239 RelTextSections.push_back(RelSection); | 239 RelTextSections.push_back(RelSection); |
240 } else { | 240 } else { |
241 Section = TextSections[0]; | 241 Section = TextSections[0]; |
242 RelSection = RelTextSections[0]; | 242 RelSection = RelTextSections[0]; |
243 } | 243 } |
244 const RelocOffsetT OffsetInSection = Section->getCurrentSize(); | 244 const RelocOffsetT OffsetInSection = Section->getCurrentSize(); |
245 // Function symbols are set to 0 size in the symbol table, in contrast to | 245 // Function symbols are set to 0 size in the symbol table, in contrast to |
246 // data symbols which have a proper size. | 246 // data symbols which have a proper size. |
247 constexpr SizeT SymbolSize = 0; | 247 constexpr SizeT SymbolSize = 0; |
248 uint8_t SymbolType; | 248 uint8_t SymbolType; |
249 uint8_t SymbolBinding; | 249 uint8_t SymbolBinding; |
250 if (IsInternal && !Ctx.getFlags().getDisableInternal()) { | 250 if (IsInternal && !getFlags().getDisableInternal()) { |
251 SymbolType = STT_NOTYPE; | 251 SymbolType = STT_NOTYPE; |
252 SymbolBinding = STB_LOCAL; | 252 SymbolBinding = STB_LOCAL; |
253 } else { | 253 } else { |
254 SymbolType = STT_FUNC; | 254 SymbolType = STT_FUNC; |
255 SymbolBinding = STB_GLOBAL; | 255 SymbolBinding = STB_GLOBAL; |
256 } | 256 } |
257 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, | 257 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, |
258 OffsetInSection, SymbolSize); | 258 OffsetInSection, SymbolSize); |
259 StrTab->add(FuncName); | 259 StrTab->add(FuncName); |
260 | 260 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 303 |
304 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, | 304 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, |
305 FixupKind RelocationKind, | 305 FixupKind RelocationKind, |
306 const std::string &SectionSuffix, | 306 const std::string &SectionSuffix, |
307 bool IsPIC) { | 307 bool IsPIC) { |
308 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); | 308 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); |
309 assert(!SectionNumbersAssigned); | 309 assert(!SectionNumbersAssigned); |
310 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes]; | 310 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes]; |
311 for (auto &SectionList : VarsBySection) | 311 for (auto &SectionList : VarsBySection) |
312 SectionList.reserve(Vars.size()); | 312 SectionList.reserve(Vars.size()); |
313 partitionGlobalsBySection(Vars, VarsBySection, | 313 partitionGlobalsBySection(Vars, VarsBySection, getFlags().getTranslateOnly()); |
314 Ctx.getFlags().getTranslateOnly()); | |
315 size_t I = 0; | 314 size_t I = 0; |
316 for (auto &SectionList : VarsBySection) { | 315 for (auto &SectionList : VarsBySection) { |
317 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind, | 316 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind, |
318 SectionSuffix, IsPIC); | 317 SectionSuffix, IsPIC); |
319 } | 318 } |
320 } | 319 } |
321 | 320 |
322 namespace { | 321 namespace { |
323 std::string MangleSectionName(const char Base[], const std::string &Suffix) { | 322 std::string MangleSectionName(const char Base[], const std::string &Suffix) { |
324 if (Suffix.empty()) | 323 if (Suffix.empty()) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 constexpr uint8_t SymbolType = STT_OBJECT; | 384 constexpr uint8_t SymbolType = STT_OBJECT; |
386 for (VariableDeclaration *Var : Vars) { | 385 for (VariableDeclaration *Var : Vars) { |
387 // If the variable declaration does not have an initializer, its symtab | 386 // If the variable declaration does not have an initializer, its symtab |
388 // entry will be created separately. | 387 // entry will be created separately. |
389 if (!Var->hasInitializer()) | 388 if (!Var->hasInitializer()) |
390 continue; | 389 continue; |
391 constexpr Elf64_Xword MinAlign = 1; | 390 constexpr Elf64_Xword MinAlign = 1; |
392 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment()); | 391 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment()); |
393 Section->padToAlignment(Str, Align); | 392 Section->padToAlignment(Str, Align); |
394 SizeT SymbolSize = Var->getNumBytes(); | 393 SizeT SymbolSize = Var->getNumBytes(); |
395 bool IsExternal = Var->isExternal() || Ctx.getFlags().getDisableInternal(); | 394 bool IsExternal = Var->isExternal() || getFlags().getDisableInternal(); |
396 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; | 395 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; |
397 GlobalString Name = Var->getName(); | 396 GlobalString Name = Var->getName(); |
398 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section, | 397 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section, |
399 Section->getCurrentSize(), SymbolSize); | 398 Section->getCurrentSize(), SymbolSize); |
400 StrTab->add(Name); | 399 StrTab->add(Name); |
401 if (!Var->hasNonzeroInitializer()) { | 400 if (!Var->hasNonzeroInitializer()) { |
402 assert(ST == BSS || ST == ROData); | 401 assert(ST == BSS || ST == ROData); |
403 if (ST == ROData) | 402 if (ST == ROData) |
404 Section->appendZeros(Str, SymbolSize); | 403 Section->appendZeros(Str, SymbolSize); |
405 else | 404 else |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 Str.write8(ELF_ABIVersion); | 468 Str.write8(ELF_ABIVersion); |
470 Str.writeZeroPadding(EI_NIDENT - EI_PAD); | 469 Str.writeZeroPadding(EI_NIDENT - EI_PAD); |
471 | 470 |
472 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc: | 471 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc: |
473 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should | 472 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should |
474 // be 0 and then actual number of sections is stored in the sh_size member of | 473 // be 0 and then actual number of sections is stored in the sh_size member of |
475 // the 0th section. | 474 // the 0th section. |
476 assert(NumSections < SHN_LORESERVE); | 475 assert(NumSections < SHN_LORESERVE); |
477 assert(SectHeaderStrIndex < SHN_LORESERVE); | 476 assert(SectHeaderStrIndex < SHN_LORESERVE); |
478 | 477 |
479 const TargetArch Arch = Ctx.getFlags().getTargetArch(); | 478 const TargetArch Arch = getFlags().getTargetArch(); |
480 // Write the rest of the file header, which does depend on byte order and ELF | 479 // Write the rest of the file header, which does depend on byte order and ELF |
481 // class. | 480 // class. |
482 Str.writeLE16(ET_REL); // e_type | 481 Str.writeLE16(ET_REL); // e_type |
483 Str.writeLE16(getELFMachine(Ctx.getFlags().getTargetArch())); // e_machine | 482 Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine |
484 Str.writeELFWord<IsELF64>(1); // e_version | 483 Str.writeELFWord<IsELF64>(1); // e_version |
485 // Since this is for a relocatable object, there is no entry point, and no | 484 // Since this is for a relocatable object, there is no entry point, and no |
486 // program headers. | 485 // program headers. |
487 Str.writeAddrOrOffset<IsELF64>(0); // e_entry | 486 Str.writeAddrOrOffset<IsELF64>(0); // e_entry |
488 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff | 487 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff |
489 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff | 488 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff |
490 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags | 489 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags |
491 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize | 490 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize |
492 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52, | 491 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52, |
493 "Elf_Ehdr sizes cannot be derived from sizeof"); | 492 "Elf_Ehdr sizes cannot be derived from sizeof"); |
494 Str.writeLE16(0); // e_phentsize | 493 Str.writeLE16(0); // e_phentsize |
(...skipping 29 matching lines...) Expand all Loading... |
524 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt); | 523 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt); |
525 RODataSections.push_back(Section); | 524 RODataSections.push_back(Section); |
526 SizeT OffsetInSection = 0; | 525 SizeT OffsetInSection = 0; |
527 // The symbol table entry doesn't need to know the defined symbol's size | 526 // The symbol table entry doesn't need to know the defined symbol's size |
528 // since this is in a section with a fixed Entry Size. | 527 // since this is in a section with a fixed Entry Size. |
529 constexpr SizeT SymbolSize = 0; | 528 constexpr SizeT SymbolSize = 0; |
530 Section->setFileOffset(alignFileOffset(Align)); | 529 Section->setFileOffset(alignFileOffset(Align)); |
531 | 530 |
532 // If the -reorder-pooled-constant option is set to true, we should shuffle | 531 // If the -reorder-pooled-constant option is set to true, we should shuffle |
533 // the constants before we emit them. | 532 // the constants before we emit them. |
534 if (Ctx.getFlags().getReorderPooledConstants() && !Pool.empty()) { | 533 if (getFlags().getReorderPooledConstants() && !Pool.empty()) { |
535 // Use the constant's kind value as the salt for creating random number | 534 // Use the constant's kind value as the salt for creating random number |
536 // generator. | 535 // generator. |
537 Operand::OperandKind K = (*Pool.begin())->getKind(); | 536 Operand::OperandKind K = (*Pool.begin())->getKind(); |
538 RandomNumberGenerator RNG(Ctx.getFlags().getRandomSeed(), | 537 RandomNumberGenerator RNG(getFlags().getRandomSeed(), |
539 RPE_PooledConstantReordering, K); | 538 RPE_PooledConstantReordering, K); |
540 RandomShuffle(Pool.begin(), Pool.end(), | 539 RandomShuffle(Pool.begin(), Pool.end(), |
541 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | 540 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); |
542 } | 541 } |
543 // Write the data. | 542 // Write the data. |
544 for (Constant *C : Pool) { | 543 for (Constant *C : Pool) { |
545 if (!C->getShouldBePooled()) | 544 if (!C->getShouldBePooled()) |
546 continue; | 545 continue; |
547 auto *Const = llvm::cast<ConstType>(C); | 546 auto *Const = llvm::cast<ConstType>(C); |
548 GlobalString SymName = Const->getLabelName(); | 547 GlobalString SymName = Const->getLabelName(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 "$jumptable"); | 589 "$jumptable"); |
591 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, | 590 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, |
592 ShAddralign, ShEntsize); | 591 ShAddralign, ShEntsize); |
593 Section->setFileOffset(alignFileOffset(ShAddralign)); | 592 Section->setFileOffset(alignFileOffset(ShAddralign)); |
594 RODataSections.push_back(Section); | 593 RODataSections.push_back(Section); |
595 RelSection = createRelocationSection(Section); | 594 RelSection = createRelocationSection(Section); |
596 RelRODataSections.push_back(RelSection); | 595 RelRODataSections.push_back(RelSection); |
597 | 596 |
598 constexpr uint8_t SymbolType = STT_OBJECT; | 597 constexpr uint8_t SymbolType = STT_OBJECT; |
599 Section->padToAlignment(Str, PointerSize); | 598 Section->padToAlignment(Str, PointerSize); |
600 const bool IsExternal = Ctx.getFlags().getDisableInternal(); | 599 const bool IsExternal = getFlags().getDisableInternal(); |
601 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; | 600 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; |
602 GlobalString JumpTableName = Ctx.getGlobalString( | 601 GlobalString JumpTableName = Ctx.getGlobalString( |
603 InstJumpTable::makeName(JT.getFunctionName(), JT.getId())); | 602 InstJumpTable::makeName(JT.getFunctionName(), JT.getId())); |
604 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section, | 603 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section, |
605 Section->getCurrentSize(), PointerSize); | 604 Section->getCurrentSize(), PointerSize); |
606 StrTab->add(JumpTableName); | 605 StrTab->add(JumpTableName); |
607 | 606 |
608 for (intptr_t TargetOffset : JT.getTargetOffsets()) { | 607 for (intptr_t TargetOffset : JT.getTargetOffsets()) { |
609 AssemblerFixup NewFixup; | 608 AssemblerFixup NewFixup; |
610 NewFixup.set_position(Section->getCurrentSize()); | 609 NewFixup.set_position(Section->getCurrentSize()); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 if (ELF64) { | 692 if (ELF64) { |
694 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 693 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), |
695 AllSections.size()); | 694 AllSections.size()); |
696 } else { | 695 } else { |
697 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 696 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), |
698 AllSections.size()); | 697 AllSections.size()); |
699 } | 698 } |
700 } | 699 } |
701 | 700 |
702 } // end of namespace Ice | 701 } // end of namespace Ice |
OLD | NEW |