[yaml2obj] - Add a way to override sh_type section field.
authorGeorgii Rymar <grimar@accesssoftek.com>
Tue, 28 Jul 2020 09:53:06 +0000 (12:53 +0300)
committerGeorgii Rymar <grimar@accesssoftek.com>
Tue, 28 Jul 2020 13:16:42 +0000 (16:16 +0300)
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
llvm/lib/ObjectYAML/ELFEmitter.cpp
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/test/tools/yaml2obj/ELF/override-shtype.yaml [new file with mode: 0644]

index b1ffb20..9a5c06f 100644 (file)
@@ -206,6 +206,12 @@ struct Section : public Chunk {
 
   // This can be used to override the sh_flags field.
   Optional<llvm::yaml::Hex64> 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<ELF_SHT> ShType;
 };
 
 // Fill is a block of data which is placed outside of sections. It is
index 65b0305..bc27c03 100644 (file)
@@ -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 <class ELFT>
index f85d6a5..f460a38 100644 (file)
@@ -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 (file)
index 0000000..ac29b3b
--- /dev/null
@@ -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: []