Index: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -144,6 +144,10 @@ // 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 anyhow. + Optional ShSize; + Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); }; Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -912,11 +912,13 @@ 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 an 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) { Index: test/Object/invalid.test =================================================================== --- test/Object/invalid.test +++ test/Object/invalid.test @@ -126,12 +126,12 @@ Symbols: - Name: foo -## Check that llvm-readobj reports an error if .dynsym has an invalid sh_entsize. +## Check that llvm-readobj reports a warning if .dynsym has an invalid sh_entsize. # RUN: yaml2obj %s --docnum=7 -o %t7 -# RUN: not llvm-readobj --dyn-symbols %t7 2>&1 | FileCheck --check-prefix=INVALID-DYNSYM-SIZE %s +# RUN: llvm-readobj --dyn-symbols %t7 2>&1 | FileCheck --check-prefix=INVALID-DYNSYM-SIZE %s -# INVALID-DYNSYM-SIZE: error: Invalid entity size +# INVALID-DYNSYM-SIZE: warning: Invalid entity size --- !ELF FileHeader: @@ -458,22 +458,22 @@ Sections: - Section: .dynamic -## Check that llvm-readobj reports an error when a dynamic relocation section +## Check that llvm-readobj reports a warning when a dynamic relocation section ## has sh_entsize field with size != sizeof(Elf_Rela). -# RUN: not llvm-readobj --dyn-relocations \ +# RUN: llvm-readobj --dyn-relocations \ # RUN: %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 \ # RUN: | FileCheck --check-prefix=RELOC-BROKEN-ENTSIZE %s -# RELOC-BROKEN-ENTSIZE: error: Invalid entity size +# RELOC-BROKEN-ENTSIZE: warning: Invalid entity size -## Check that llvm-readobj reports an error when .dynamic section has an invalid +## Check that llvm-readobj reports a warning when .dynamic section has an invalid ## size, which isn't a multiple of the dynamic entry size. # RUN: yaml2obj %s --docnum=22 -o %t22 -# RUN: not llvm-readobj --dyn-relocations %t22 2>&1 | FileCheck --check-prefix=DYN-TABLE-SIZE %s +# RUN: llvm-readobj --dyn-relocations %t22 2>&1 | FileCheck --check-prefix=DYN-TABLE-SIZE %s -# DYN-TABLE-SIZE: error: Invalid entity size +# DYN-TABLE-SIZE: warning: Invalid entity size --- !ELF FileHeader: Index: test/tools/llvm-readobj/elf-dynamic-malformed.test =================================================================== --- test/tools/llvm-readobj/elf-dynamic-malformed.test +++ test/tools/llvm-readobj/elf-dynamic-malformed.test @@ -1,9 +1,9 @@ # Test handling of a dynamic section size which is not a multiple of its entry size. # RUN: yaml2obj %s --docnum=1 -o %t.bad-size -# RUN: not llvm-readobj --dynamic-table %t.bad-size 2>&1 | FileCheck %s --check-prefix ERR-SIZE -# RUN: not llvm-readelf --dynamic-table %t.bad-size 2>&1 | FileCheck %s --check-prefix ERR-SIZE +# RUN: llvm-readobj --dynamic-table %t.bad-size 2>&1 | FileCheck %s --implicit-check-not=Dynamic --check-prefix WARN +# RUN: llvm-readelf --dynamic-table %t.bad-size 2>&1 | FileCheck %s --implicit-check-not=Dynamic --check-prefix WARN -# ERR-SIZE: error: Invalid entity size +# WARN: warning: Invalid entity size --- !ELF FileHeader: Index: test/tools/yaml2obj/elf-override-shsize.yaml =================================================================== --- /dev/null +++ test/tools/yaml2obj/elf-override-shsize.yaml @@ -0,0 +1,105 @@ +## 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" Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -134,8 +134,11 @@ const Type *Start = reinterpret_cast(Addr); if (!Start) return {Start, Start}; - if (EntSize != sizeof(Type) || Size % EntSize) - reportError("Invalid entity size"); + if (EntSize != sizeof(Type) || Size % EntSize) { + // TODO: This warning needs to be more precise. + reportWarning("Invalid entity size"); + return {Start, Start}; + } return {Start, Start + (Size / EntSize)}; } }; Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -270,9 +270,13 @@ 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 @@ } 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;