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. It does not place the + // section data at the offset specified. 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,12 @@ IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); IO.mapOptional("EntSize", Section.EntSize); + + // obj2yaml does not dump this field. It is expected to be empty when we + // producing YAML, because yam2obj sets an appropriate value for sh_offset + // automatically when it is not explicitly defined. + assert(!IO.outputting() || !Section.ShOffset.hasValue()); + 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,106 @@ +## Check we are able to set custom sh_offset field +## for different sections. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readelf --sections %t1 | FileCheck %s --check-prefix=CASE1 + +# CASE1: Section Headers: +# CASE1-NEXT: [Nr] Name Type Address Off +# CASE1-NEXT: [ 0] NULL {{.*}} 000000 +# CASE1-NEXT: [ 1] .dynsym DYNSYM {{.*}} 000001 +# CASE1-NEXT: [ 2] .symtab SYMTAB {{.*}} 000002 +# CASE1-NEXT: [ 3] .dynamic DYNAMIC {{.*}} 000003 +# CASE1-NEXT: [ 4] .rela RELA {{.*}} 000004 +# CASE1-NEXT: [ 5] .nobits NOBITS {{.*}} 000005 +# CASE1-NEXT: [ 6] .group GROUP {{.*}} 000006 +# CASE1-NEXT: [ 7] .gnu.version VERSYM {{.*}} 000007 +# CASE1-NEXT: [ 8] .gnu.version_r VERNEED {{.*}} 000008 +# CASE1-NEXT: [ 9] .gnu.version_d VERDEF {{.*}} 000009 +# CASE1-NEXT: [10] .regular PROGBITS {{.*}} 00000a +# CASE1-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 + +## Here we check that defining ShOffset does not actually change +## the offset at which section data is placed and also does +## not affect file size. + +# RUN: yaml2obj --docnum=2 %s -o %t2 +# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: od -t x8 -v %t2 > %t.txt +# RUN: od -t x8 -v %t3 >> %t.txt +# RUN: FileCheck %s --input-file=%t.txt --check-prefix=CASE2 + +# CASE2: [[OFFSET:.*]] 8877665544332211 +# CASE2: [[FILESIZE:.*]]{{$}} +# CASE2: [[OFFSET]] 8877665544332211 +# CASE2: [[FILESIZE]]{{$}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Content: "1122334455667788" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + ShOffset: 0xFFFF0000 + Content: "1122334455667788" 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;