[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<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> 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
llvm-svn: 350336
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 39794a3..d77e03c 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -71,7 +71,47 @@
Shdr.sh_entsize = Sec.EntrySize;
}
-SectionVisitor::~SectionVisitor() {}
+template <class ELFT> void ELFSectionSizer<ELFT>::visit(Section &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::visit(OwnedDataSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::visit(StringTableSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::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 <class ELFT>
+void ELFSectionSizer<ELFT>::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 <class ELFT>
+void ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &Sec) {}
+
+template <class ELFT> void ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::visit(SectionIndexSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::visit(CompressedSection &Sec) {}
+
+template <class ELFT>
+void ELFSectionSizer<ELFT>::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 <class ELFT>
void ELFSectionWriter<ELFT>::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 <class SymTabType>
void RelocSectionWithSymtabBase<SymTabType>::removeSectionReferences(
const SectionBase *Sec) {
@@ -540,6 +606,10 @@
Visitor.visit(*this);
}
+void RelocationSection::accept(MutableSectionVisitor &Visitor) {
+ Visitor.visit(*this);
+}
+
void RelocationSection::removeSymbols(
function_ref<bool(const Symbol &)> 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 <class ELFT>
void ELFSectionWriter<ELFT>::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 <class ELFT> void BinaryELFBuilder<ELFT>::initFileHeader() {
+void BinaryELFBuilder::initFileHeader() {
Obj->Flags = 0x0;
Obj->Type = ET_REL;
Obj->OSABI = ELFOSABI_NONE;
@@ -710,11 +792,9 @@
Obj->Version = 1;
}
-template <class ELFT> void BinaryELFBuilder<ELFT>::initHeaderSegment() {
- Obj->ElfHdrSegment.Index = 0;
-}
+void BinaryELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
-template <class ELFT> StringTableSection *BinaryELFBuilder<ELFT>::addStrTab() {
+StringTableSection *BinaryELFBuilder::addStrTab() {
auto &StrTab = Obj->addSection<StringTableSection>();
StrTab.Name = ".strtab";
@@ -722,15 +802,11 @@
return &StrTab;
}
-template <class ELFT>
-SymbolTableSection *
-BinaryELFBuilder<ELFT>::addSymTab(StringTableSection *StrTab) {
+SymbolTableSection *BinaryELFBuilder::addSymTab(StringTableSection *StrTab) {
auto &SymTab = Obj->addSection<SymbolTableSection>();
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 <class ELFT>
-void BinaryELFBuilder<ELFT>::addData(SymbolTableSection *SymTab) {
+void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
auto Data = ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
MemBuf->getBufferSize());
@@ -763,13 +838,13 @@
/*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0);
}
-template <class ELFT> void BinaryELFBuilder<ELFT>::initSections() {
+void BinaryELFBuilder::initSections() {
for (auto &Section : Obj->sections()) {
Section.initialize(Obj->sections());
}
}
-template <class ELFT> std::unique_ptr<Object> BinaryELFBuilder<ELFT>::build() {
+std::unique_ptr<Object> BinaryELFBuilder::build() {
initFileHeader();
initHeaderSegment();
StringTableSection *StrTab = addStrTab();
@@ -1122,14 +1197,7 @@
Reader::~Reader() {}
std::unique_ptr<Object> BinaryReader::create() const {
- if (MInfo.Is64Bit)
- return MInfo.IsLittleEndian
- ? BinaryELFBuilder<ELF64LE>(MInfo.EMachine, MemBuf).build()
- : BinaryELFBuilder<ELF64BE>(MInfo.EMachine, MemBuf).build();
- else
- return MInfo.IsLittleEndian
- ? BinaryELFBuilder<ELF32LE>(MInfo.EMachine, MemBuf).build()
- : BinaryELFBuilder<ELF32BE>(MInfo.EMachine, MemBuf).build();
+ return BinaryELFBuilder(MInfo.EMachine, MemBuf).build();
}
std::unique_ptr<Object> 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<ELFSectionSizer<ELFT>>();
+ 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<BinarySectionWriter>(Buf);
}
-template class BinaryELFBuilder<ELF64LE>;
-template class BinaryELFBuilder<ELF64BE>;
-template class BinaryELFBuilder<ELF32LE>;
-template class BinaryELFBuilder<ELF32BE>;
-
template class ELFBuilder<ELF64LE>;
template class ELFBuilder<ELF64BE>;
template class ELFBuilder<ELF32LE>;