Index: lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- lib/ObjectYAML/ELFEmitter.cpp +++ lib/ObjectYAML/ELFEmitter.cpp @@ -116,7 +116,7 @@ bool buildSectionIndex(); bool buildSymbolIndexes(); - void initELFHeader(Elf_Ehdr &Header); + void initELFHeader(Elf_Ehdr &Header, uint64_t SHOff); void initProgramHeaders(std::vector &PHeaders); bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, StringRef SecName, ELFYAML::Section *YAMLSec); @@ -205,7 +205,8 @@ } } -template void ELFState::initELFHeader(Elf_Ehdr &Header) { +template +void ELFState::initELFHeader(Elf_Ehdr &Header, uint64_t SHOff) { using namespace llvm::ELF; zero(Header); Header.e_ident[EI_MAG0] = 0x7f; @@ -231,9 +232,7 @@ 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(); + Doc.Header.SHOffset ? typename ELFT::uint(*Doc.Header.SHOffset) : SHOff; 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 @@ -1040,19 +1039,13 @@ 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 +1055,16 @@ // Now we can decide segment offsets State.setProgramHeaderLayout(PHeaders, SHeaders); + // Align the start of the section header and write the ELF header. + Elf_Ehdr Header; + uint64_t SHOff; + CBA.getOSAndAlignedOffset(SHOff, sizeof(typename ELFT::uint)); + State.initELFHeader(Header, SHOff); OS.write((const char *)&Header, sizeof(Header)); + writeArrayData(OS, makeArrayRef(PHeaders)); - writeArrayData(OS, makeArrayRef(SHeaders)); CBA.writeBlobToStream(OS); + writeArrayData(OS, makeArrayRef(SHeaders)); return 0; } Index: test/Object/invalid.test =================================================================== --- test/Object/invalid.test +++ test/Object/invalid.test @@ -315,7 +315,7 @@ # RUN: yaml2obj %s --docnum=16 -o %t16 # RUN: not llvm-readobj -r %t16 2>&1 | FileCheck -DFILE=%t16 --check-prefix=INVALID-REL-SYM %s -# INVALID-REL-SYM: error: '[[FILE]]': unable to access section [index 2] data at 0x18000180: offset goes past the end of file +# INVALID-REL-SYM: error: '[[FILE]]': unable to access section [index 2] data at 0x18000040: offset goes past the end of file --- !ELF FileHeader: @@ -565,7 +565,7 @@ # RUN: yaml2obj --docnum=26 %s -o %t26 # RUN: not llvm-readobj -h %t26 2>&1 | FileCheck -DFILE=%t26 --check-prefix=INVALID-SEC-NUM1 %s -# INVALID-SEC-NUM1: error: '[[FILE]]': invalid section header table offset (e_shoff = 0x40) or invalid number of sections specified in the first section header's sh_size field (0x3ffffffffffffff) +# INVALID-SEC-NUM1: error: '[[FILE]]': invalid section header table offset (e_shoff = 0x78) or invalid number of sections specified in the first section header's sh_size field (0x3ffffffffffffff) --- !ELF FileHeader: Index: test/tools/llvm-objcopy/ELF/group-reorder.test =================================================================== --- test/tools/llvm-objcopy/ELF/group-reorder.test +++ test/tools/llvm-objcopy/ELF/group-reorder.test @@ -8,12 +8,12 @@ # aren't purely sorting based on offsets (it gets moved to the beginning # despite having a larger offset). -# IN: There are 7 section headers, starting at offset 0x40: +# IN: There are 7 section headers, starting at offset 0x160: # IN: [Nr] Name Type Address Off Size # IN-NEXT: [ 0] NULL 0000000000000000 000000 000000 -# IN-NEXT: [ 1] .foo PROGBITS 0000000000000000 000200 000040 -# IN-NEXT: [ 2] .group GROUP 0000000000000000 000240 000008 -# IN-NEXT: [ 3] .bar PROGBITS 0000000000000000 000248 000040 +# IN-NEXT: [ 1] .foo PROGBITS 0000000000000000 000040 000040 +# IN-NEXT: [ 2] .group GROUP 0000000000000000 000080 000008 +# IN-NEXT: [ 3] .bar PROGBITS 0000000000000000 000088 000040 # IN: COMDAT group section [ 2] `.group' [bar] contains 1 sections: # IN-NEXT: [Index] Name Index: test/tools/llvm-objcopy/ELF/invalid-e_shoff.test =================================================================== --- test/tools/llvm-objcopy/ELF/invalid-e_shoff.test +++ test/tools/llvm-objcopy/ELF/invalid-e_shoff.test @@ -7,13 +7,13 @@ ## Sanity check that the section header table is at offset 64: # RUN: llvm-readobj --file-headers %t.o | FileCheck %s --check-prefix=VALIDATE -# VALIDATE: SectionHeaderOffset: 0x40{{$}} +# VALIDATE: SectionHeaderOffset: 0x80{{$}} ## Truncate the file to end before the section header table ends. -# RUN: %python -c "with open('%/t.o', 'r+b') as input: input.truncate(65)" +# RUN: %python -c "with open('%/t.o', 'r+b') as input: input.truncate(0x7f)" # RUN: not llvm-objcopy %t.o 2>&1 | FileCheck %s -DINPUT=%t.o --check-prefix=CASE1 -# CASE1: error: '[[INPUT]]': section header table goes past the end of the file: e_shoff = 0x40 +# CASE1: error: '[[INPUT]]': section header table goes past the end of the file: e_shoff = 0x80 ## Set the e_shoff field to a value much larger than the object file size. # RUN: %python -c "with open('%/t2.o', 'r+b') as input: import struct; bytes = struct.pack('