From bd93f5ce07ef2fb9c1897bddc576fe4afb464788 Mon Sep 17 00:00:00 2001 From: Georgii Rymar Date: Tue, 28 Jul 2020 12:53:06 +0300 Subject: [PATCH] [yaml2obj] - Add a way to override sh_type section field. This adds the `ShType` key similar to others `Sh*` keys we have. My use case is the following. Imagine we have a `SHT_SYMTAB_SHNDX` section and want to hide it from a dumper. The natural way would be to do something like: ``` - Name: .symtab_shndx Type: [[TYPE=SHT_SYMTAB_SHNDX]] Entries: [ 0, 1 ] ``` and then change the TYPE from `SHT_SYMTAB_SHNDX` to something else, for example to `SHT_PROGBITS`. But we have a problem: regular sections does not have `Entries` key, so yaml2obj will be unable to produce a section. The solution is to introduce a `ShType` key to override the final type. This is not the first time I am facing the need to change the type. I was able to invent workarounds or solved issues differently in the past, but finally came to conclusion that we just should support the `ShType`. Differential revision: https://reviews.llvm.org/D84738 --- llvm/include/llvm/ObjectYAML/ELFYAML.h | 6 +++ llvm/lib/ObjectYAML/ELFEmitter.cpp | 2 + llvm/lib/ObjectYAML/ELFYAML.cpp | 4 +- .../tools/yaml2obj/ELF/override-shtype.yaml | 44 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/yaml2obj/ELF/override-shtype.yaml diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index b1ffb20681ea..9a5c06fdfcd5 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -206,6 +206,12 @@ struct Section : public Chunk { // 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 index 65b03050c7cd..bc27c03cb687 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -551,6 +551,8 @@ static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) { 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 index f85d6a5d30ef..f460a387540d 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1094,11 +1094,13 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { // 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 index 000000000000..ac29b3b0e8bc --- /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: [] -- 2.34.1