| 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 ShStrTab->add(Name); | 110 ShStrTab->add(Name); |
| 111 return NewSection; | 111 return NewSection; |
| 112 } | 112 } |
| 113 | 113 |
| 114 ELFRelocationSection * | 114 ELFRelocationSection * |
| 115 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) { | 115 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) { |
| 116 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in | 116 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in |
| 117 // practice we've only had .rela for elf64 (x86-64). In the future, the two | 117 // practice we've only had .rela for elf64 (x86-64). In the future, the two |
| 118 // properties may need to be decoupled and the ShEntSize can vary more. | 118 // properties may need to be decoupled and the ShEntSize can vary more. |
| 119 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL; | 119 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL; |
| 120 IceString RelPrefix = ELF64 ? ".rela" : ".rel"; | 120 const IceString RelPrefix = ELF64 ? ".rela" : ".rel"; |
| 121 IceString RelSectionName = RelPrefix + RelatedSection->getName(); | 121 const IceString RelSectionName = RelPrefix + RelatedSection->getName(); |
| 122 const Elf64_Xword ShAlign = ELF64 ? 8 : 4; | 122 const Elf64_Xword ShAlign = ELF64 ? 8 : 4; |
| 123 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); | 123 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); |
| 124 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, | 124 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, |
| 125 "Elf_Rel/Rela sizes cannot be derived from sizeof"); | 125 "Elf_Rel/Rela sizes cannot be derived from sizeof"); |
| 126 constexpr Elf64_Xword ShFlags = 0; | 126 constexpr Elf64_Xword ShFlags = 0; |
| 127 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>( | 127 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>( |
| 128 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); | 128 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); |
| 129 RelSection->setRelatedSection(RelatedSection); | 129 RelSection->setRelatedSection(RelatedSection); |
| 130 return RelSection; | 130 return RelSection; |
| 131 } | 131 } |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 // TODO(jvoung): Handle fdata-sections. | 327 // TODO(jvoung): Handle fdata-sections. |
| 328 void ELFObjectWriter::writeDataOfType(SectionType ST, | 328 void ELFObjectWriter::writeDataOfType(SectionType ST, |
| 329 const VariableDeclarationList &Vars, | 329 const VariableDeclarationList &Vars, |
| 330 FixupKind RelocationKind, | 330 FixupKind RelocationKind, |
| 331 const IceString &SectionSuffix, | 331 const IceString &SectionSuffix, |
| 332 bool IsPIC) { | 332 bool IsPIC) { |
| 333 if (Vars.empty()) | 333 if (Vars.empty()) |
| 334 return; | 334 return; |
| 335 ELFDataSection *Section; | 335 ELFDataSection *Section; |
| 336 ELFRelocationSection *RelSection; | 336 ELFRelocationSection *RelSection; |
| 337 IceString SectionName; | |
| 338 Elf64_Xword ShAddralign = 1; | 337 Elf64_Xword ShAddralign = 1; |
| 339 for (VariableDeclaration *Var : Vars) { | 338 for (VariableDeclaration *Var : Vars) { |
| 340 Elf64_Xword Align = Var->getAlignment(); | 339 Elf64_Xword Align = Var->getAlignment(); |
| 341 ShAddralign = std::max(ShAddralign, Align); | 340 ShAddralign = std::max(ShAddralign, Align); |
| 342 } | 341 } |
| 343 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size. | 342 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size. |
| 344 // Lift this out, so it can be re-used if we do fdata-sections? | 343 // Lift this out, so it can be re-used if we do fdata-sections? |
| 345 switch (ST) { | 344 switch (ST) { |
| 346 case ROData: { | 345 case ROData: { |
| 347 const IceString SectionName = | 346 const IceString SectionName = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 // entry will be created separately. | 385 // entry will be created separately. |
| 387 if (!Var->hasInitializer()) | 386 if (!Var->hasInitializer()) |
| 388 continue; | 387 continue; |
| 389 Elf64_Xword Align = Var->getAlignment(); | 388 Elf64_Xword Align = Var->getAlignment(); |
| 390 constexpr Elf64_Xword MinAlign = 1; | 389 constexpr Elf64_Xword MinAlign = 1; |
| 391 Align = std::max(Align, MinAlign); | 390 Align = std::max(Align, MinAlign); |
| 392 Section->padToAlignment(Str, Align); | 391 Section->padToAlignment(Str, Align); |
| 393 SizeT SymbolSize = Var->getNumBytes(); | 392 SizeT SymbolSize = Var->getNumBytes(); |
| 394 bool IsExternal = Var->isExternal() || Ctx.getFlags().getDisableInternal(); | 393 bool IsExternal = Var->isExternal() || Ctx.getFlags().getDisableInternal(); |
| 395 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; | 394 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; |
| 396 IceString MangledName = Var->mangleName(&Ctx); | 395 const IceString &Name = Var->getName(); |
| 397 SymTab->createDefinedSym(MangledName, SymbolType, SymbolBinding, Section, | 396 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section, |
| 398 Section->getCurrentSize(), SymbolSize); | 397 Section->getCurrentSize(), SymbolSize); |
| 399 StrTab->add(MangledName); | 398 StrTab->add(Name); |
| 400 if (!Var->hasNonzeroInitializer()) { | 399 if (!Var->hasNonzeroInitializer()) { |
| 401 assert(ST == BSS || ST == ROData); | 400 assert(ST == BSS || ST == ROData); |
| 402 if (ST == ROData) | 401 if (ST == ROData) |
| 403 Section->appendZeros(Str, SymbolSize); | 402 Section->appendZeros(Str, SymbolSize); |
| 404 else | 403 else |
| 405 Section->setSize(Section->getCurrentSize() + SymbolSize); | 404 Section->setSize(Section->getCurrentSize() + SymbolSize); |
| 406 } else { | 405 } else { |
| 407 assert(ST != BSS); | 406 assert(ST != BSS); |
| 408 for (const std::unique_ptr<VariableDeclaration::Initializer> &Init : | 407 for (const std::unique_ptr<VariableDeclaration::Initializer> &Init : |
| 409 Var->getInitializers()) { | 408 Var->getInitializers()) { |
| 410 switch (Init->getKind()) { | 409 switch (Init->getKind()) { |
| 411 case VariableDeclaration::Initializer::DataInitializerKind: { | 410 case VariableDeclaration::Initializer::DataInitializerKind: { |
| 412 const auto &Data = | 411 const auto &Data = |
| 413 llvm::cast<VariableDeclaration::DataInitializer>(Init.get()) | 412 llvm::cast<VariableDeclaration::DataInitializer>(Init.get()) |
| 414 ->getContents(); | 413 ->getContents(); |
| 415 Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); | 414 Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); |
| 416 break; | 415 break; |
| 417 } | 416 } |
| 418 case VariableDeclaration::Initializer::ZeroInitializerKind: | 417 case VariableDeclaration::Initializer::ZeroInitializerKind: |
| 419 Section->appendZeros(Str, Init->getNumBytes()); | 418 Section->appendZeros(Str, Init->getNumBytes()); |
| 420 break; | 419 break; |
| 421 case VariableDeclaration::Initializer::RelocInitializerKind: { | 420 case VariableDeclaration::Initializer::RelocInitializerKind: { |
| 422 const auto *Reloc = | 421 const auto *Reloc = |
| 423 llvm::cast<VariableDeclaration::RelocInitializer>(Init.get()); | 422 llvm::cast<VariableDeclaration::RelocInitializer>(Init.get()); |
| 424 AssemblerFixup NewFixup; | 423 AssemblerFixup NewFixup; |
| 425 NewFixup.set_position(Section->getCurrentSize()); | 424 NewFixup.set_position(Section->getCurrentSize()); |
| 426 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup() | 425 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup() |
| 427 : RelocationKind); | 426 : RelocationKind); |
| 428 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE); | 427 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE); |
| 429 constexpr bool SuppressMangling = true; | |
| 430 NewFixup.set_value(Ctx.getConstantSym( | 428 NewFixup.set_value(Ctx.getConstantSym( |
| 431 Reloc->getOffset(), Reloc->getDeclaration()->mangleName(&Ctx), | 429 Reloc->getOffset(), Reloc->getDeclaration()->getName())); |
| 432 SuppressMangling)); | |
| 433 RelSection->addRelocation(NewFixup); | 430 RelSection->addRelocation(NewFixup); |
| 434 Section->appendRelocationOffset(Str, RelSection->isRela(), | 431 Section->appendRelocationOffset(Str, RelSection->isRela(), |
| 435 Reloc->getOffset()); | 432 Reloc->getOffset()); |
| 436 break; | 433 break; |
| 437 } | 434 } |
| 438 } | 435 } |
| 439 } | 436 } |
| 440 } | 437 } |
| 441 } | 438 } |
| 442 } | 439 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 RandomShuffle(Pool.begin(), Pool.end(), | 537 RandomShuffle(Pool.begin(), Pool.end(), |
| 541 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | 538 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); |
| 542 } | 539 } |
| 543 // Write the data. | 540 // Write the data. |
| 544 for (Constant *C : Pool) { | 541 for (Constant *C : Pool) { |
| 545 if (!C->getShouldBePooled()) | 542 if (!C->getShouldBePooled()) |
| 546 continue; | 543 continue; |
| 547 auto *Const = llvm::cast<ConstType>(C); | 544 auto *Const = llvm::cast<ConstType>(C); |
| 548 std::string SymBuffer; | 545 std::string SymBuffer; |
| 549 llvm::raw_string_ostream SymStrBuf(SymBuffer); | 546 llvm::raw_string_ostream SymStrBuf(SymBuffer); |
| 550 Const->emitPoolLabel(SymStrBuf, &Ctx); | 547 Const->emitPoolLabel(SymStrBuf); |
| 551 std::string &SymName = SymStrBuf.str(); | 548 std::string &SymName = SymStrBuf.str(); |
| 552 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section, | 549 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section, |
| 553 OffsetInSection, SymbolSize); | 550 OffsetInSection, SymbolSize); |
| 554 StrTab->add(SymName); | 551 StrTab->add(SymName); |
| 555 typename ConstType::PrimType Value = Const->getValue(); | 552 typename ConstType::PrimType Value = Const->getValue(); |
| 556 memcpy(Buf, &Value, WriteAmt); | 553 memcpy(Buf, &Value, WriteAmt); |
| 557 Str.writeBytes(llvm::StringRef(Buf, WriteAmt)); | 554 Str.writeBytes(llvm::StringRef(Buf, WriteAmt)); |
| 558 OffsetInSection += WriteAmt; | 555 OffsetInSection += WriteAmt; |
| 559 } | 556 } |
| 560 Section->setSize(OffsetInSection); | 557 Section->setSize(OffsetInSection); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 588 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); | 585 IsPIC ? ".data.rel.ro" : ".rodata", JT.getFunctionName() + "$jumptable"); |
| 589 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, | 586 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, |
| 590 ShAddralign, ShEntsize); | 587 ShAddralign, ShEntsize); |
| 591 Section->setFileOffset(alignFileOffset(ShAddralign)); | 588 Section->setFileOffset(alignFileOffset(ShAddralign)); |
| 592 RODataSections.push_back(Section); | 589 RODataSections.push_back(Section); |
| 593 RelSection = createRelocationSection(Section); | 590 RelSection = createRelocationSection(Section); |
| 594 RelRODataSections.push_back(RelSection); | 591 RelRODataSections.push_back(RelSection); |
| 595 | 592 |
| 596 constexpr uint8_t SymbolType = STT_OBJECT; | 593 constexpr uint8_t SymbolType = STT_OBJECT; |
| 597 Section->padToAlignment(Str, PointerSize); | 594 Section->padToAlignment(Str, PointerSize); |
| 598 bool IsExternal = Ctx.getFlags().getDisableInternal(); | 595 const bool IsExternal = Ctx.getFlags().getDisableInternal(); |
| 599 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; | 596 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; |
| 600 IceString JumpTableName = | 597 const IceString JumpTableName = |
| 601 InstJumpTable::makeName(JT.getFunctionName(), JT.getId()); | 598 InstJumpTable::makeName(JT.getFunctionName(), JT.getId()); |
| 602 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section, | 599 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section, |
| 603 Section->getCurrentSize(), PointerSize); | 600 Section->getCurrentSize(), PointerSize); |
| 604 StrTab->add(JumpTableName); | 601 StrTab->add(JumpTableName); |
| 605 | 602 |
| 606 for (intptr_t TargetOffset : JT.getTargetOffsets()) { | 603 for (intptr_t TargetOffset : JT.getTargetOffsets()) { |
| 607 AssemblerFixup NewFixup; | 604 AssemblerFixup NewFixup; |
| 608 NewFixup.set_position(Section->getCurrentSize()); | 605 NewFixup.set_position(Section->getCurrentSize()); |
| 609 NewFixup.set_kind(RelocationKind); | 606 NewFixup.set_kind(RelocationKind); |
| 610 constexpr bool SuppressMangling = true; | 607 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName())); |
| 611 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName(), | |
| 612 SuppressMangling)); | |
| 613 RelSection->addRelocation(NewFixup); | 608 RelSection->addRelocation(NewFixup); |
| 614 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); | 609 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); |
| 615 } | 610 } |
| 616 } | 611 } |
| 617 | 612 |
| 618 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { | 613 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { |
| 619 for (const Constant *S : UndefSyms) { | 614 for (const Constant *S : UndefSyms) { |
| 620 const auto *Sym = llvm::cast<ConstantRelocatable>(S); | 615 const auto *Sym = llvm::cast<ConstantRelocatable>(S); |
| 621 const IceString &Name = Sym->getName(); | 616 const IceString &Name = Sym->getName(); |
| 622 bool BadIntrinsic; | 617 bool BadIntrinsic; |
| 623 const Intrinsics::FullIntrinsicInfo *Info = | 618 const Intrinsics::FullIntrinsicInfo *Info = |
| 624 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); | 619 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); |
| 625 if (Info) | 620 if (Info) |
| 626 continue; | 621 continue; |
| 627 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but | 622 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but |
| 628 // doesn't match a known intrinsic. If we want this to turn into an error, | 623 // doesn't match a known intrinsic. If we want this to turn into an error, |
| 629 // we should catch it early on. | 624 // we should catch it early on. |
| 630 assert(Sym->getOffset() == 0); | 625 assert(Sym->getOffset() == 0); |
| 631 assert(Sym->getSuppressMangling()); | |
| 632 SymTab->noteUndefinedSym(Name, NullSection); | 626 SymTab->noteUndefinedSym(Name, NullSection); |
| 633 StrTab->add(Name); | 627 StrTab->add(Name); |
| 634 } | 628 } |
| 635 } | 629 } |
| 636 | 630 |
| 637 void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) { | 631 void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) { |
| 638 for (ELFRelocationSection *RelSec : RelSections) { | 632 for (ELFRelocationSection *RelSec : RelSections) { |
| 639 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); | 633 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); |
| 640 RelSec->setFileOffset(Offset); | 634 RelSec->setFileOffset(Offset); |
| 641 RelSec->setSize(RelSec->getSectionDataSize()); | 635 RelSec->setSize(RelSec->getSectionDataSize()); |
| 642 if (ELF64) { | 636 if (ELF64) { |
| 643 RelSec->writeData<true>(Ctx, Str, SymTab); | 637 RelSec->writeData<true>(Str, SymTab); |
| 644 } else { | 638 } else { |
| 645 RelSec->writeData<false>(Ctx, Str, SymTab); | 639 RelSec->writeData<false>(Str, SymTab); |
| 646 } | 640 } |
| 647 } | 641 } |
| 648 } | 642 } |
| 649 | 643 |
| 650 void ELFObjectWriter::writeNonUserSections() { | 644 void ELFObjectWriter::writeNonUserSections() { |
| 651 // Write out the shstrtab now that all sections are known. | 645 // Write out the shstrtab now that all sections are known. |
| 652 ShStrTab->doLayout(); | 646 ShStrTab->doLayout(); |
| 653 ShStrTab->setSize(ShStrTab->getSectionDataSize()); | 647 ShStrTab->setSize(ShStrTab->getSectionDataSize()); |
| 654 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); | 648 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); |
| 655 ShStrTab->setFileOffset(ShStrTabOffset); | 649 ShStrTab->setFileOffset(ShStrTabOffset); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 if (ELF64) { | 684 if (ELF64) { |
| 691 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 685 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), |
| 692 AllSections.size()); | 686 AllSections.size()); |
| 693 } else { | 687 } else { |
| 694 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 688 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), |
| 695 AllSections.size()); | 689 AllSections.size()); |
| 696 } | 690 } |
| 697 } | 691 } |
| 698 | 692 |
| 699 } // end of namespace Ice | 693 } // end of namespace Ice |
| OLD | NEW |