Index: llvm/trunk/test/tools/llvm-objcopy/ELF/binary-input.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/binary-input.test +++ llvm/trunk/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 { Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.h +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.h @@ -71,7 +71,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } void accept(SectionVisitor &Sec) const override; + void accept(MutableSectionVisitor &Visitor) override; }; class CompressedSection : public SectionBase { @@ -333,6 +374,7 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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::ELFObjectFile; using object::OwningBinary; -template class BinaryELFBuilder { - using Elf_Sym = typename ELFT::Sym; - +class BinaryELFBuilder { uint16_t EMachine; MemoryBuffer *MemBuf; std::unique_ptr Obj; Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp @@ -71,7 +71,47 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ Visitor.visit(*this); } +void SymbolTableSection::accept(MutableSectionVisitor &Visitor) { + Visitor.visit(*this); +} + template void RelocSectionWithSymtabBase::removeSectionReferences( const SectionBase *Sec) { @@ -540,6 +606,10 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /*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 @@ 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 @@ } 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 @@ 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;