Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -140,6 +140,10 @@ llvm::yaml::Hex64 AddressAlign; Optional EntSize; + // This can be used to override the sh_offset field. + // Useful for creating invalid objects. + Optional ShOffset; + Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); }; Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -911,6 +911,9 @@ IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); IO.mapOptional("EntSize", Section.EntSize); + + assert(!IO.outputting()); + IO.mapOptional("ShOffset", Section.ShOffset); } static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { Index: test/tools/yaml2obj/elf-override-shoffset.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/elf-override-shoffset.yaml @@ -0,0 +1,68 @@ +## Check we are able to set custom sh_offset field +## for different sections. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf --sections %t | FileCheck %s + +# CHECK: Section Headers: +# CHECK-NEXT: [Nr] Name Type Address Off +# CHECK-NEXT: [ 0] NULL {{.*}} 000000 +# CHECK-NEXT: [ 1] .dynsym DYNSYM {{.*}} 000001 +# CHECK-NEXT: [ 2] .symtab SYMTAB {{.*}} 000002 +# CHECK-NEXT: [ 3] .dynamic DYNAMIC {{.*}} 000003 +# CHECK-NEXT: [ 4] .rela RELA {{.*}} 000004 +# CHECK-NEXT: [ 5] .nobits NOBITS {{.*}} 000005 +# CHECK-NEXT: [ 6] .group GROUP {{.*}} 000006 +# CHECK-NEXT: [ 7] .gnu.version VERSYM {{.*}} 000007 +# CHECK-NEXT: [ 8] .gnu.version_r VERNEED {{.*}} 000008 +# CHECK-NEXT: [ 9] .gnu.version_d VERDEF {{.*}} 000009 +# CHECK-NEXT: [10] .regular PROGBITS {{.*}} 00000a +# CHECK-NEXT: [11] .strtab STRTAB {{.*}} 00000b + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + ShOffset: 0x000000001 + - Name: .symtab + Type: SHT_SYMTAB + ShOffset: 0x000000002 + - Name: .dynamic + Type: SHT_DYNAMIC + ShOffset: 0x000000003 + - Name: .rela + Type: SHT_RELA + ShOffset: 0x000000004 + - Name: .nobits + Type: SHT_NOBITS + ShOffset: 0x000000005 + - Name: .group + Type: SHT_GROUP + Info: 0 + ShOffset: 0x000000006 + Members: + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ ] + ShOffset: 0x000000007 + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Info: 0x0000000000000001 + ShOffset: 0x000000008 + Dependencies: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Info: 0x0000000000000001 + ShOffset: 0x000000009 + Entries: + - Name: .regular + Type: SHT_PROGBITS + ShOffset: 0x00000000A + - Name: .strtab + Type: SHT_STRTAB + ShOffset: 0x00000000B Index: tools/obj2yaml/elf2yaml.cpp =================================================================== --- tools/obj2yaml/elf2yaml.cpp +++ tools/obj2yaml/elf2yaml.cpp @@ -360,6 +360,8 @@ template std::error_code ELFDumper::dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S) { + // Dump fields. We do not dump the ShOffset field. When not explicitly + // set, the value is set by yaml2obj automatically. S.Type = Shdr->sh_type; if (Shdr->sh_flags) S.Flags = static_cast(Shdr->sh_flags); Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -269,6 +269,11 @@ YAMLSec); else return false; + + // Override the sh_offset field if requested. + if (YAMLSec && YAMLSec->ShOffset) + Header.sh_offset = *YAMLSec->ShOffset; + return true; } @@ -358,6 +363,10 @@ return false; } else llvm_unreachable("Unknown section type"); + + // Override the sh_offset field if requested. + if (Sec && Sec->ShOffset) + SHeader.sh_offset = *Sec->ShOffset; } return true;