From: Jordan Rupprecht Date: Thu, 3 Jan 2019 17:45:30 +0000 (+0000) Subject: [llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8dbe072cd59b0b0f7ae23074bde5c4d1c5789878;p=llvm [llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout. Summary: Fix EntrySize, Size, and Align before doing layout calculation. As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that. This unblocks a cleaner implementation of handling the -O flag. See D53667 for a previous attempt. Actual implementation of the -O flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before). Reviewers: jakehehrlich, jhenderson, alexshap, espindola Reviewed By: jhenderson Subscribers: emaste, arichardson, llvm-commits Differential Revision: https://reviews.llvm.org/D56211 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350336 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/llvm-objcopy/ELF/binary-input.test b/test/tools/llvm-objcopy/ELF/binary-input.test index ff1d381c3fa..3e9b1bad112 100644 --- a/test/tools/llvm-objcopy/ELF/binary-input.test +++ b/test/tools/llvm-objcopy/ELF/binary-input.test @@ -45,7 +45,7 @@ # CHECK-NEXT: Size: # CHECK-NEXT: Link: 1 # CHECK-NEXT: Info: 1 -# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: AddressAlignment: 8 # CHECK-NEXT: EntrySize: 24 # CHECK-NEXT: } # CHECK-NEXT: Section { diff --git a/tools/llvm-objcopy/ELF/Object.cpp b/tools/llvm-objcopy/ELF/Object.cpp index 39794a32229..d77e03c2a8e 100644 --- a/tools/llvm-objcopy/ELF/Object.cpp +++ b/tools/llvm-objcopy/ELF/Object.cpp @@ -71,7 +71,47 @@ template void ELFWriter::writeShdr(const SectionBase &Sec) { Shdr.sh_entsize = Sec.EntrySize; } -SectionVisitor::~SectionVisitor() {} +template void ELFSectionSizer::visit(Section &Sec) {} + +template +void ELFSectionSizer::visit(OwnedDataSection &Sec) {} + +template +void ELFSectionSizer::visit(StringTableSection &Sec) {} + +template +void ELFSectionSizer::visit(DynamicRelocationSection &Sec) {} + +template +void ELFSectionSizer::visit(SymbolTableSection &Sec) { + Sec.EntrySize = sizeof(Elf_Sym); + Sec.Size = Sec.Symbols.size() * Sec.EntrySize; + // Align to the larget field in Elf_Sym. + Sec.Align = sizeof(Elf_Sym::st_size); +} + +template +void ELFSectionSizer::visit(RelocationSection &Sec) { + Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela); + Sec.Size = Sec.Relocations.size() * Sec.EntrySize; + // Align to the larget field in Elf_Rel(a). + Sec.Align = + Sec.Type == SHT_REL ? sizeof(Elf_Rel::r_info) : sizeof(Elf_Rela::r_info); +} + +template +void ELFSectionSizer::visit(GnuDebugLinkSection &Sec) {} + +template void ELFSectionSizer::visit(GroupSection &Sec) {} + +template +void ELFSectionSizer::visit(SectionIndexSection &Sec) {} + +template +void ELFSectionSizer::visit(CompressedSection &Sec) {} + +template +void ELFSectionSizer::visit(DecompressedSection &Sec) {} void BinarySectionWriter::visit(const SectionIndexSection &Sec) { error("Cannot write symbol section index table '" + Sec.Name + "' "); @@ -102,6 +142,8 @@ void SectionWriter::visit(const Section &Sec) { void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void Section::accept(MutableSectionVisitor &Visitor) { Visitor.visit(*this); } + void SectionWriter::visit(const OwnedDataSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; llvm::copy(Sec.Data, Buf); @@ -164,10 +206,18 @@ void DecompressedSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void DecompressedSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + void OwnedDataSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void OwnedDataSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + void BinarySectionWriter::visit(const CompressedSection &Sec) { error("Cannot write compressed section '" + Sec.Name + "' "); } @@ -246,6 +296,10 @@ void CompressedSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void CompressedSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); Size = StrTabBuilder.getSize(); @@ -265,6 +319,10 @@ void StringTableSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void StringTableSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + template void ELFSectionWriter::visit(const SectionIndexSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; @@ -288,6 +346,10 @@ void SectionIndexSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void SectionIndexSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) { switch (Index) { case SHN_ABS: @@ -470,6 +532,10 @@ void SymbolTableSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void SymbolTableSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + template void RelocSectionWithSymtabBase::removeSectionReferences( const SectionBase *Sec) { @@ -540,6 +606,10 @@ void RelocationSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void RelocationSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + void RelocationSection::removeSymbols( function_ref ToRemove) { for (const Relocation &Reloc : Relocations) @@ -562,6 +632,10 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + void Section::removeSectionReferences(const SectionBase *Sec) { if (LinkSection == Sec) { error("Section " + LinkSection->Name + @@ -648,6 +722,10 @@ void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + template void ELFSectionWriter::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = @@ -661,6 +739,10 @@ void GroupSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +void GroupSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + // Returns true IFF a section is wholly inside the range of a segment static bool sectionWithinSegment(const SectionBase &Section, const Segment &Segment) { @@ -700,7 +782,7 @@ static bool compareSegmentsByPAddr(const Segment *A, const Segment *B) { return A->Index < B->Index; } -template void BinaryELFBuilder::initFileHeader() { +void BinaryELFBuilder::initFileHeader() { Obj->Flags = 0x0; Obj->Type = ET_REL; Obj->OSABI = ELFOSABI_NONE; @@ -710,11 +792,9 @@ template void BinaryELFBuilder::initFileHeader() { Obj->Version = 1; } -template void BinaryELFBuilder::initHeaderSegment() { - Obj->ElfHdrSegment.Index = 0; -} +void BinaryELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; } -template StringTableSection *BinaryELFBuilder::addStrTab() { +StringTableSection *BinaryELFBuilder::addStrTab() { auto &StrTab = Obj->addSection(); StrTab.Name = ".strtab"; @@ -722,15 +802,11 @@ template StringTableSection *BinaryELFBuilder::addStrTab() { return &StrTab; } -template -SymbolTableSection * -BinaryELFBuilder::addSymTab(StringTableSection *StrTab) { +SymbolTableSection *BinaryELFBuilder::addSymTab(StringTableSection *StrTab) { auto &SymTab = Obj->addSection(); SymTab.Name = ".symtab"; SymTab.Link = StrTab->Index; - // TODO: Factor out dependence on ElfType here. - SymTab.EntrySize = sizeof(Elf_Sym); // The symbol table always needs a null symbol SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0); @@ -739,8 +815,7 @@ BinaryELFBuilder::addSymTab(StringTableSection *StrTab) { return &SymTab; } -template -void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { +void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { auto Data = ArrayRef( reinterpret_cast(MemBuf->getBufferStart()), MemBuf->getBufferSize()); @@ -763,13 +838,13 @@ void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { /*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0); } -template void BinaryELFBuilder::initSections() { +void BinaryELFBuilder::initSections() { for (auto &Section : Obj->sections()) { Section.initialize(Obj->sections()); } } -template std::unique_ptr BinaryELFBuilder::build() { +std::unique_ptr BinaryELFBuilder::build() { initFileHeader(); initHeaderSegment(); StringTableSection *StrTab = addStrTab(); @@ -1122,14 +1197,7 @@ Writer::~Writer() {} Reader::~Reader() {} std::unique_ptr BinaryReader::create() const { - if (MInfo.Is64Bit) - return MInfo.IsLittleEndian - ? BinaryELFBuilder(MInfo.EMachine, MemBuf).build() - : BinaryELFBuilder(MInfo.EMachine, MemBuf).build(); - else - return MInfo.IsLittleEndian - ? BinaryELFBuilder(MInfo.EMachine, MemBuf).build() - : BinaryELFBuilder(MInfo.EMachine, MemBuf).build(); + return BinaryELFBuilder(MInfo.EMachine, MemBuf).build(); } std::unique_ptr ELFReader::create() const { @@ -1483,10 +1551,16 @@ template void ELFWriter::finalize() { } initEhdrSegment(); + // Before we can prepare for layout the indexes need to be finalized. + // Also, the output arch may not be the same as the input arch, so fix up + // size-related fields before doing layout calculations. uint64_t Index = 0; - for (auto &Sec : Obj.sections()) + auto SecSizer = llvm::make_unique>(); + for (auto &Sec : Obj.sections()) { Sec.Index = Index++; + Sec.accept(*SecSizer); + } // The symbol table does not update all other sections on update. For // instance, symbol names are not added as new symbols are added. This means @@ -1607,11 +1681,6 @@ void BinaryWriter::finalize() { SecWriter = llvm::make_unique(Buf); } -template class BinaryELFBuilder; -template class BinaryELFBuilder; -template class BinaryELFBuilder; -template class BinaryELFBuilder; - template class ELFBuilder; template class ELFBuilder; template class ELFBuilder; diff --git a/tools/llvm-objcopy/ELF/Object.h b/tools/llvm-objcopy/ELF/Object.h index 4b606c4ae54..b0e83d2f56c 100644 --- a/tools/llvm-objcopy/ELF/Object.h +++ b/tools/llvm-objcopy/ELF/Object.h @@ -71,7 +71,7 @@ enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE }; class SectionVisitor { public: - virtual ~SectionVisitor(); + virtual ~SectionVisitor() = default; virtual void visit(const Section &Sec) = 0; virtual void visit(const OwnedDataSection &Sec) = 0; @@ -86,6 +86,23 @@ public: virtual void visit(const DecompressedSection &Sec) = 0; }; +class MutableSectionVisitor { +public: + virtual ~MutableSectionVisitor() = default; + + virtual void visit(Section &Sec) = 0; + virtual void visit(OwnedDataSection &Sec) = 0; + virtual void visit(StringTableSection &Sec) = 0; + virtual void visit(SymbolTableSection &Sec) = 0; + virtual void visit(RelocationSection &Sec) = 0; + virtual void visit(DynamicRelocationSection &Sec) = 0; + virtual void visit(GnuDebugLinkSection &Sec) = 0; + virtual void visit(GroupSection &Sec) = 0; + virtual void visit(SectionIndexSection &Sec) = 0; + virtual void visit(CompressedSection &Sec) = 0; + virtual void visit(DecompressedSection &Sec) = 0; +}; + class SectionWriter : public SectionVisitor { protected: Buffer &Out; @@ -128,9 +145,30 @@ public: explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {} }; +template class ELFSectionSizer : public MutableSectionVisitor { +private: + using Elf_Rel = typename ELFT::Rel; + using Elf_Rela = typename ELFT::Rela; + using Elf_Sym = typename ELFT::Sym; + +public: + void visit(Section &Sec) override; + void visit(OwnedDataSection &Sec) override; + void visit(StringTableSection &Sec) override; + void visit(DynamicRelocationSection &Sec) override; + void visit(SymbolTableSection &Sec) override; + void visit(RelocationSection &Sec) override; + void visit(GnuDebugLinkSection &Sec) override; + void visit(GroupSection &Sec) override; + void visit(SectionIndexSection &Sec) override; + void visit(CompressedSection &Sec) override; + void visit(DecompressedSection &Sec) override; +}; + #define MAKE_SEC_WRITER_FRIEND \ friend class SectionWriter; \ - template friend class ELFSectionWriter; + template friend class ELFSectionWriter; \ + template friend class ELFSectionSizer; class BinarySectionWriter : public SectionWriter { public: @@ -237,6 +275,7 @@ public: virtual void removeSectionReferences(const SectionBase *Sec); virtual void removeSymbols(function_ref ToRemove); virtual void accept(SectionVisitor &Visitor) const = 0; + virtual void accept(MutableSectionVisitor &Visitor) = 0; virtual void markSymbols(); }; @@ -293,6 +332,7 @@ public: explicit Section(ArrayRef Data) : Contents(Data) {} void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; void removeSectionReferences(const SectionBase *Sec) override; void initialize(SectionTableRef SecTable) override; void finalize() override; @@ -313,6 +353,7 @@ public: } void accept(SectionVisitor &Sec) const override; + void accept(MutableSectionVisitor &Visitor) override; }; class CompressedSection : public SectionBase { @@ -333,6 +374,7 @@ public: uint64_t getDecompressedAlign() const { return DecompressedAlign; } void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; static bool classof(const SectionBase *S) { return (S->Flags & ELF::SHF_COMPRESSED) || @@ -354,6 +396,7 @@ public: } void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; }; // There are two types of string tables that can exist, dynamic and not dynamic. @@ -378,6 +421,7 @@ public: uint32_t findIndex(StringRef Name) const; void finalize() override; void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; static bool classof(const SectionBase *S) { if (S->Flags & ELF::SHF_ALLOC) @@ -435,6 +479,7 @@ public: void initialize(SectionTableRef SecTable) override; void finalize() override; void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; SectionIndexSection() { Name = ".symtab_shndx"; @@ -479,6 +524,7 @@ public: void initialize(SectionTableRef SecTable) override; void finalize() override; void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; void removeSymbols(function_ref ToRemove) override; static bool classof(const SectionBase *S) { @@ -540,6 +586,7 @@ class RelocationSection public: void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; void removeSymbols(function_ref ToRemove) override; void markSymbols() override; @@ -573,6 +620,7 @@ public: void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); } void accept(SectionVisitor &) const override; + void accept(MutableSectionVisitor &Visitor) override; void finalize() override; void removeSymbols(function_ref ToRemove) override; void markSymbols() override; @@ -611,6 +659,7 @@ public: explicit DynamicRelocationSection(ArrayRef Data) : Contents(Data) {} void accept(SectionVisitor &) const override; + void accept(MutableSectionVisitor &Visitor) override; static bool classof(const SectionBase *S) { if (!(S->Flags & ELF::SHF_ALLOC)) @@ -632,6 +681,7 @@ public: // If we add this section from an external source we can use this ctor. explicit GnuDebugLinkSection(StringRef File); void accept(SectionVisitor &Visitor) const override; + void accept(MutableSectionVisitor &Visitor) override; }; class Reader { @@ -645,9 +695,7 @@ using object::ELFFile; using object::ELFObjectFile; using object::OwningBinary; -template class BinaryELFBuilder { - using Elf_Sym = typename ELFT::Sym; - +class BinaryELFBuilder { uint16_t EMachine; MemoryBuffer *MemBuf; std::unique_ptr Obj;