diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -206,6 +206,12 @@ // This can be used to override the sh_flags field. Optional ShFlags; + + // This can be used to override the sh_type field. It is useful when we + // want to use specific YAML keys for a section of a particular type to + // describe the content, but still want to have a different final type + // for the section. + Optional ShType; }; // Fill is a block of data which is placed outside of sections. It is diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -551,6 +551,8 @@ To.sh_offset = *From->ShOffset; if (From->ShSize) To.sh_size = *From->ShSize; + if (From->ShType) + To.sh_type = *From->ShType; } template diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1094,11 +1094,13 @@ // automatically when they are not explicitly defined. assert(!IO.outputting() || (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue() && - !Section.ShName.hasValue() && !Section.ShFlags.hasValue())); + !Section.ShName.hasValue() && !Section.ShFlags.hasValue() && + !Section.ShType.hasValue())); IO.mapOptional("ShName", Section.ShName); IO.mapOptional("ShOffset", Section.ShOffset); IO.mapOptional("ShSize", Section.ShSize); IO.mapOptional("ShFlags", Section.ShFlags); + IO.mapOptional("ShType", Section.ShType); } static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { diff --git a/llvm/test/tools/yaml2obj/ELF/override-shtype.yaml b/llvm/test/tools/yaml2obj/ELF/override-shtype.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/ELF/override-shtype.yaml @@ -0,0 +1,44 @@ +## Check we are able to override the sh_type field for different sections. +## When doing this we are still able to use YAML keys that can be normally used +## to describe a section with the original type specified with the Type key. + +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s --check-prefixes=COMMON,ORIGINAL + +## Check we can use a hex value for the ShType. SHT_PROGBITS == 0x1. +# RUN: yaml2obj -DTYPE=0x1 %s -o %t2 +# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s --check-prefixes=COMMON,OVERRIDE + +# COMMON: Name: .gnu.version_r +# ORIGINAL-NEXT: Type: SHT_GNU_verneed +# OVERRIDE-NEXT: Type: SHT_PROGBITS +# COMMON: SectionData ( +# COMMON-NEXT: 0000: 01000100 04000000 10000000 00000000 | +# COMMON-NEXT: 0010: 91070000 00000300 01000000 00000000 | +# COMMON-NEXT: ) + +## Check we can use a string type name for the ShType. +# RUN: yaml2obj -DTYPE=SHT_PROGBITS %s -o %t3 +# RUN: cmp %t2 %t3 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + ShType: [[TYPE=SHT_GNU_verneed]] + Info: 0 + Dependencies: + - Version: 1 + File: dso.so.0 + Entries: + - Name: v1 + Hash: 1937 + Flags: 0 + Other: 3 +DynamicSymbols: []