From f0e500c351f9c3f48824d4aada8fb87d018f740c Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 11 Jul 2019 12:59:29 +0000 Subject: [PATCH] [yaml2obj] - Allow overriding the sh_size field. There is no way to set broken sh_size field currently for sections. It can be usefull for writing the test cases. Differential revision: https://reviews.llvm.org/D64401 llvm-svn: 365766 --- include/llvm/ObjectYAML/ELFYAML.h | 4 + lib/ObjectYAML/ELFYAML.cpp | 10 +- test/tools/yaml2obj/elf-override-shsize.yaml | 159 +++++++++++++++++++ tools/yaml2obj/yaml2elf.cpp | 20 ++- 4 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 test/tools/yaml2obj/elf-override-shsize.yaml diff --git a/include/llvm/ObjectYAML/ELFYAML.h b/include/llvm/ObjectYAML/ELFYAML.h index 68a0fc36b50..f4212516f48 100644 --- a/include/llvm/ObjectYAML/ELFYAML.h +++ b/include/llvm/ObjectYAML/ELFYAML.h @@ -144,6 +144,10 @@ struct Section { // section data at the offset specified. Useful for creating invalid objects. Optional ShOffset; + // This can be used to override the sh_size field. It does not affect the + // content written. + Optional ShSize; + Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); }; diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp index d968351bca9..7497154c757 100644 --- a/lib/ObjectYAML/ELFYAML.cpp +++ b/lib/ObjectYAML/ELFYAML.cpp @@ -913,11 +913,13 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { 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 are - // producing YAML, because yaml2obj sets an appropriate value for sh_offset - // automatically when it is not explicitly defined. - assert(!IO.outputting() || !Section.ShOffset.hasValue()); + // obj2yaml does not dump these fields. They are expected to be empty when we + // are producing YAML, because yaml2obj sets appropriate values for sh_offset + // and sh_size automatically when they are not explicitly defined. + assert(!IO.outputting() || + (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue())); IO.mapOptional("ShOffset", Section.ShOffset); + IO.mapOptional("ShSize", Section.ShSize); } static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { diff --git a/test/tools/yaml2obj/elf-override-shsize.yaml b/test/tools/yaml2obj/elf-override-shsize.yaml new file mode 100644 index 00000000000..fd5b0f8289e --- /dev/null +++ b/test/tools/yaml2obj/elf-override-shsize.yaml @@ -0,0 +1,159 @@ +## Check we are able to set custom sh_size 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 Size +# CASE1-NEXT: [ 0] NULL 0000000000000000 000000 000000 +# CASE1-NEXT: [ 1] .dynsym DYNSYM 0000000000000000 000380 000001 +# CASE1-NEXT: [ 2] .symtab SYMTAB 0000000000000000 000398 000002 +# CASE1-NEXT: [ 3] .dynamic DYNAMIC 0000000000000000 0003b0 000003 +# CASE1-NEXT: [ 4] .rela RELA 0000000000000000 0003b0 000004 +# CASE1-NEXT: [ 5] .nobits NOBITS 0000000000000000 0003b0 000005 +# CASE1-NEXT: [ 6] .group GROUP 0000000000000000 0003b0 000006 +# CASE1-NEXT: [ 7] .gnu.version VERSYM 0000000000000000 0003b0 000007 +# CASE1-NEXT: [ 8] .gnu.version_r VERNEED 0000000000000000 0003b0 000008 +# CASE1-NEXT: [ 9] .gnu.version_d VERDEF 0000000000000000 0003b0 000009 +# CASE1-NEXT: [10] .regular PROGBITS 0000000000000000 0003b0 00000a +# CASE1-NEXT: [11] .strtab STRTAB 0000000000000000 0003b0 00000b + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + ShSize: 0x000000001 + - Name: .symtab + Type: SHT_SYMTAB + ShSize: 0x000000002 + - Name: .dynamic + Type: SHT_DYNAMIC + ShSize: 0x000000003 + - Name: .rela + Type: SHT_RELA + ShSize: 0x000000004 + - Name: .nobits + Type: SHT_NOBITS + ShSize: 0x000000005 + - Name: .group + Type: SHT_GROUP + Info: 0 + ShSize: 0x000000006 + Members: + - Name: .gnu.version + Type: SHT_GNU_versym + Entries: [ ] + ShSize: 0x000000007 + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Info: 0x0000000000000001 + ShSize: 0x000000008 + Dependencies: + - Name: .gnu.version_d + Type: SHT_GNU_verdef + Info: 0x0000000000000001 + ShSize: 0x000000009 + Entries: + - Name: .regular + Type: SHT_PROGBITS + ShSize: 0x00000000A + - Name: .strtab + Type: SHT_STRTAB + ShSize: 0x00000000B + +## Here we check that defining ShSize does not actually change +## the content 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:.*]] fefefefefefefefe +# CASE2: [[FILESIZE:.*]]{{$}} +# CASE2: [[OFFSET]] fefefefefefefefe +# CASE2: [[FILESIZE]]{{$}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Content: "fefefefefefefefe" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + ShSize: 1 + Content: "fefefefefefefefe" + +## Check we can define sh_size larger than section content size +## and thus create overlaping sections. + +# RUN: yaml2obj --docnum=4 %s -o %t4 +# RUN: llvm-readobj --sections --section-data %t4 | FileCheck %s --check-prefix=CASE4 + +# CASE4: Name: .foo +# CASE4: SectionData ( +# CASE4-NEXT: 0000: AAAABBBB |....| +# CASE4: Name: .bar +# CASE4: SectionData ( +# CASE4-NEXT: 0000: BBBB |..| + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Content: "aaaa" + ShSize: 4 + - Name: .bar + Type: SHT_PROGBITS + Content: "bbbb" + +## Check we can set both Size and ShSize and the number of the actual +## bytes written is equal to Size in this case. + +# RUN: yaml2obj --docnum=5 %s -o %t5 +# RUN: od -t x4 -v %t5 | FileCheck %s --check-prefix=CASE5 + +# CASE5: aaaa 0000bbbb + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .foo + Type: SHT_PROGBITS + Content: "aaaa" + - Name: .bar + Type: SHT_PROGBITS + Size: 2 + ShSize: 4 + - Name: .zed + Type: SHT_PROGBITS + Content: "bbbb" diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 735057f6e7d..e821c642c85 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -270,9 +270,13 @@ bool ELFState::initImplicitHeader(ELFState &State, else return false; - // Override the sh_offset field if requested. - if (YAMLSec && YAMLSec->ShOffset) - Header.sh_offset = *YAMLSec->ShOffset; + // Override the sh_offset/sh_size fields if requested. + if (YAMLSec) { + if (YAMLSec->ShOffset) + Header.sh_offset = *YAMLSec->ShOffset; + if (YAMLSec->ShSize) + Header.sh_size = *YAMLSec->ShSize; + } return true; } @@ -364,9 +368,13 @@ bool ELFState::initSectionHeaders(ELFState &State, } else llvm_unreachable("Unknown section type"); - // Override the sh_offset field if requested. - if (Sec && Sec->ShOffset) - SHeader.sh_offset = *Sec->ShOffset; + // Override the sh_offset/sh_size fields if requested. + if (Sec) { + if (Sec->ShOffset) + SHeader.sh_offset = *Sec->ShOffset; + if (Sec->ShSize) + SHeader.sh_size = *Sec->ShSize; + } } return true;