From c3bc697974d2d7f3c151cb9853b40cc6bf73ba4b Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 5 Sep 2019 14:25:57 +0000 Subject: [yaml2obj] Write the section header table after section contents Linkers (ld.bfd/gold/lld) place the section header table at the very end. This allows tools to strip it, which is optional in executable/shared objects. In addition, if we add or section, the size of the section header table will change. Placing the section header table in the end keeps section offsets unchanged. yaml2obj currently places the section header table immediately after the program header. Follow what linkers do to make offset updating easier. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D67221 llvm-svn: 371074 --- llvm/lib/ObjectYAML/ELFEmitter.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'llvm/lib/ObjectYAML') diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index cd3a0faa03d..362a9432568 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -116,7 +116,6 @@ template class ELFState { bool buildSectionIndex(); bool buildSymbolIndexes(); - void initELFHeader(Elf_Ehdr &Header); void initProgramHeaders(std::vector &PHeaders); bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, StringRef SecName, ELFYAML::Section *YAMLSec); @@ -132,6 +131,7 @@ template class ELFState { void setProgramHeaderLayout(std::vector &PHeaders, std::vector &SHeaders); void finalizeStrings(); + void writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream &OS); bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section, ContiguousBlobAccumulator &CBA); @@ -205,8 +205,11 @@ template ELFState::ELFState(ELFYAML::Object &D) : Doc(D) { } } -template void ELFState::initELFHeader(Elf_Ehdr &Header) { +template +void ELFState::writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream &OS) { using namespace llvm::ELF; + + Elf_Ehdr Header; zero(Header); Header.e_ident[EI_MAG0] = 0x7f; Header.e_ident[EI_MAG1] = 'E'; @@ -230,14 +233,18 @@ template void ELFState::initELFHeader(Elf_Ehdr &Header) { Header.e_shentsize = Doc.Header.SHEntSize ? (uint16_t)*Doc.Header.SHEntSize : sizeof(Elf_Shdr); // Immediately following the ELF header and program headers. - Header.e_shoff = - Doc.Header.SHOffset - ? (typename ELFT::uint)(*Doc.Header.SHOffset) - : sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size(); + // Align the start of the section header and write the ELF header. + uint64_t ShOffset; + CBA.getOSAndAlignedOffset(ShOffset, sizeof(typename ELFT::uint)); + Header.e_shoff = Doc.Header.SHOffset + ? typename ELFT::uint(*Doc.Header.SHOffset) + : ShOffset; Header.e_shnum = Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.Sections.size(); Header.e_shstrndx = Doc.Header.SHStrNdx ? (uint16_t)*Doc.Header.SHStrNdx : SN2I.get(".shstrtab"); + + OS.write((const char *)&Header, sizeof(Header)); } template @@ -1040,19 +1047,13 @@ int ELFState::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) { if (!State.buildSectionIndex() || !State.buildSymbolIndexes()) return 1; - Elf_Ehdr Header; - State.initELFHeader(Header); - - // TODO: Flesh out section header support. - std::vector PHeaders; State.initProgramHeaders(PHeaders); // XXX: This offset is tightly coupled with the order that we write // things to `OS`. - const size_t SectionContentBeginOffset = Header.e_ehsize + - Header.e_phentsize * Header.e_phnum + - Header.e_shentsize * Header.e_shnum; + const size_t SectionContentBeginOffset = + sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size(); ContiguousBlobAccumulator CBA(SectionContentBeginOffset); std::vector SHeaders; @@ -1062,10 +1063,10 @@ int ELFState::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) { // Now we can decide segment offsets State.setProgramHeaderLayout(PHeaders, SHeaders); - OS.write((const char *)&Header, sizeof(Header)); + State.writeELFHeader(CBA, OS); writeArrayData(OS, makeArrayRef(PHeaders)); - writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); + writeArrayData(OS, makeArrayRef(SHeaders)); return 0; } -- cgit v1.2.3