[llvm] r368272 - [yaml2obj/obj2yaml] - Add a basic support for extended section indexes.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 8 02:49:06 PDT 2019


Author: grimar
Date: Thu Aug  8 02:49:05 2019
New Revision: 368272

URL: http://llvm.org/viewvc/llvm-project?rev=368272&view=rev
Log:
[yaml2obj/obj2yaml] - Add a basic support for extended section indexes.

In some cases a symbol might have section index == SHN_XINDEX.
This is an escape value indicating that the actual section header index
is too large to fit in the containing field.
Then the SHT_SYMTAB_SHNDX section is used. It contains the 32bit values
that stores section indexes.

ELF gABI says that there can be multiple SHT_SYMTAB_SHNDX sections,
i.e. for example one for .symtab and one for .dynsym
(1) https://groups.google.com/forum/#!topic/generic-abi/-XJAV5d8PRg
(2) DT_SYMTAB_SHNDX: http://www.sco.com/developers/gabi/latest/ch5.dynamic.html

In this patch I am only supporting a single SHT_SYMTAB_SHNDX associated
with a .symtab. This is a more or less common case which is used a few tests I saw in LLVM.

I decided not to create the SHT_SYMTAB_SHNDX section as "implicit",
but implement is like a kind of regular section for now.
i.e. tools do not recreate this section or its content, like they do for
symbol table sections, for example. That should allow to write all kind of
possible broken test cases for our needs and keep the output closer to requested.

Differential revision: https://reviews.llvm.org/D65446

Added:
    llvm/trunk/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml
    llvm/trunk/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml
Removed:
    llvm/trunk/test/tools/obj2yaml/Inputs/shn_xindex.o
Modified:
    llvm/trunk/include/llvm/Object/ELF.h
    llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
    llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp
    llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
    llvm/trunk/test/Object/invalid.test
    llvm/trunk/test/tools/llvm-readobj/elf-section-types.test
    llvm/trunk/test/tools/obj2yaml/special-symbol-indices.yaml
    llvm/trunk/tools/obj2yaml/elf2yaml.cpp

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Thu Aug  8 02:49:05 2019
@@ -635,8 +635,11 @@ ELFFile<ELFT>::getSHNDXTable(const Elf_S
   const Elf_Shdr &SymTable = **SymTableOrErr;
   if (SymTable.sh_type != ELF::SHT_SYMTAB &&
       SymTable.sh_type != ELF::SHT_DYNSYM)
-    // TODO: this error is untested.
-    return createError("invalid sh_type");
+    return createError("SHT_SYMTAB_SHNDX section is linked with " +
+                       object::getELFSectionTypeName(getHeader()->e_machine,
+                                                     SymTable.sh_type) +
+                       " section (expected SHT_SYMTAB/SHT_DYNSYM)");
+
   if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))
     return createError("SHT_SYMTAB_SHNDX section has sh_size (" +
                        Twine(SymTable.sh_size) +

Modified: llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/ELFYAML.h Thu Aug  8 02:49:05 2019
@@ -128,6 +128,7 @@ struct Section {
     NoBits,
     Verdef,
     Verneed,
+    SymtabShndxSection,
     Symver,
     MipsABIFlags
   };
@@ -274,6 +275,16 @@ struct RelocationSection : Section {
   }
 };
 
+struct SymtabShndxSection : Section {
+  std::vector<uint32_t> Entries;
+
+  SymtabShndxSection() : Section(SectionKind::SymtabShndxSection) {}
+
+  static bool classof(const Section *S) {
+    return S->Kind == SectionKind::SymtabShndxSection;
+  }
+};
+
 // Represents .MIPS.abiflags section
 struct MipsABIFlags : Section {
   llvm::yaml::Hex16 Version;

Modified: llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFEmitter.cpp Thu Aug  8 02:49:05 2019
@@ -141,6 +141,9 @@ template <class ELFT> class ELFState {
   bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group,
                            ContiguousBlobAccumulator &CBA);
   bool writeSectionContent(Elf_Shdr &SHeader,
+                           const ELFYAML::SymtabShndxSection &Shndx,
+                           ContiguousBlobAccumulator &CBA);
+  bool writeSectionContent(Elf_Shdr &SHeader,
                            const ELFYAML::SymverSection &Section,
                            ContiguousBlobAccumulator &CBA);
   bool writeSectionContent(Elf_Shdr &SHeader,
@@ -358,6 +361,9 @@ bool ELFState<ELFT>::initSectionHeaders(
     } else if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
       if (!writeSectionContent(SHeader, *S, CBA))
         return false;
+    } else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) {
+      if (!writeSectionContent(SHeader, *S, CBA))
+        return false;
     } else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) {
       if (!writeSectionContent(SHeader, *S, CBA))
         return false;
@@ -740,6 +746,21 @@ bool ELFState<ELFT>::writeSectionContent
   return true;
 }
 
+template <class ELFT>
+bool ELFState<ELFT>::writeSectionContent(
+    Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx,
+    ContiguousBlobAccumulator &CBA) {
+  raw_ostream &OS =
+      CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
+
+  for (uint32_t E : Shndx.Entries)
+    support::endian::write<uint32_t>(OS, E, ELFT::TargetEndianness);
+
+  SHeader.sh_entsize = Shndx.EntSize ? (uint64_t)*Shndx.EntSize : 4;
+  SHeader.sh_size = Shndx.Entries.size() * SHeader.sh_entsize;
+  return true;
+}
+
 template <class ELFT>
 bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                          const ELFYAML::Group &Section,

Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Thu Aug  8 02:49:05 2019
@@ -563,7 +563,7 @@ void ScalarEnumerationTraits<ELFYAML::EL
   ECase(SHN_HEXAGON_SCOMMON_4);
   ECase(SHN_HEXAGON_SCOMMON_8);
 #undef ECase
-  IO.enumFallback<Hex32>(Value);
+  IO.enumFallback<Hex16>(Value);
 }
 
 void ScalarEnumerationTraits<ELFYAML::ELF_STB>::enumeration(
@@ -897,8 +897,6 @@ StringRef MappingTraits<ELFYAML::Symbol>
                                                    ELFYAML::Symbol &Symbol) {
   if (Symbol.Index && Symbol.Section.data())
     return "Index and Section cannot both be specified for Symbol";
-  if (Symbol.Index && *Symbol.Index == ELFYAML::ELF_SHN(ELF::SHN_XINDEX))
-    return "Large indexes are not supported";
   if (Symbol.NameIndex && !Symbol.Name.empty())
     return "Name and NameIndex cannot both be specified for Symbol";
   return StringRef();
@@ -969,6 +967,11 @@ static void groupSectionMapping(IO &IO,
   IO.mapRequired("Members", Group.Members);
 }
 
+static void sectionMapping(IO &IO, ELFYAML::SymtabShndxSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Entries", Section.Entries);
+}
+
 void MappingTraits<ELFYAML::SectionOrType>::mapping(
     IO &IO, ELFYAML::SectionOrType &sectionOrType) {
   IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType);
@@ -1049,6 +1052,11 @@ void MappingTraits<std::unique_ptr<ELFYA
       Section.reset(new ELFYAML::VerneedSection());
     sectionMapping(IO, *cast<ELFYAML::VerneedSection>(Section.get()));
     break;
+  case ELF::SHT_SYMTAB_SHNDX:
+    if (!IO.outputting())
+      Section.reset(new ELFYAML::SymtabShndxSection());
+    sectionMapping(IO, *cast<ELFYAML::SymtabShndxSection>(Section.get()));
+    break;
   default:
     if (!IO.outputting())
       Section.reset(new ELFYAML::RawContentSection());

Modified: llvm/trunk/test/Object/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/invalid.test?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/test/Object/invalid.test (original)
+++ llvm/trunk/test/Object/invalid.test Thu Aug  8 02:49:05 2019
@@ -207,7 +207,7 @@ Sections:
 # RUN: yaml2obj %s --docnum=11 -o %t11
 # RUN: not llvm-readobj --symbols %t11 2>&1 | FileCheck --check-prefix=INVALID-XINDEX-SIZE %s
 
-# INVALID-XINDEX-SIZE: error: {{.*}}: SHT_SYMTAB_SHNDX section has sh_size (24) which is not equal to the number of symbols (6)
+# INVALID-XINDEX-SIZE: error: {{.*}}: SHT_SYMTAB_SHNDX section has sh_size (24) which is not equal to the number of symbols (2)
 
 --- !ELF
 FileHeader:
@@ -218,8 +218,7 @@ FileHeader:
 Sections:
   - Name: .symtab_shndx
     Type: SHT_SYMTAB_SHNDX
-    Size: 0x18
-    EntSize: 4
+    Entries: [ 0, 1 ]
     Link: .symtab
 
 ## Check that llvm-readobj reports an error if the e_phentsize field is broken.

Modified: llvm/trunk/test/tools/llvm-readobj/elf-section-types.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/elf-section-types.test?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/elf-section-types.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/elf-section-types.test Thu Aug  8 02:49:05 2019
@@ -166,8 +166,7 @@ Sections:
   - Name: symtab_shndx
     Type: SHT_SYMTAB_SHNDX
     Link: .symtab
-    EntSize: 0x4
-    Content: "0000000000000000"
+    Entries: [ 0, 1 ]
   - Name: relr
     Type: SHT_RELR
   - Name: android_rel

Removed: llvm/trunk/test/tools/obj2yaml/Inputs/shn_xindex.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/Inputs/shn_xindex.o?rev=368271&view=auto
==============================================================================
Binary file - no diff available.

Added: llvm/trunk/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml?rev=368272&view=auto
==============================================================================
--- llvm/trunk/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml (added)
+++ llvm/trunk/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml Thu Aug  8 02:49:05 2019
@@ -0,0 +1,189 @@
+## Check that obj2yaml is able to dump a normal object which
+## contains the SHT_SYMTAB_SHNDX section and symbols with
+## section index == SHN_XINDEX.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=CASE1
+
+# CASE1:      --- !ELF
+# CASE1-NEXT: FileHeader:
+# CASE1-NEXT:   Class:   ELFCLASS64
+# CASE1-NEXT:   Data:    ELFDATA2LSB
+# CASE1-NEXT:   Type:    ET_REL
+# CASE1-NEXT:   Machine: EM_X86_64
+# CASE1-NEXT: Sections:
+# CASE1-NEXT:   - Name:    bar
+# CASE1-NEXT:     Type:    SHT_PROGBITS
+# CASE1-NEXT:   - Name:    .symtab_shndx
+# CASE1-NEXT:     Type:    SHT_SYMTAB_SHNDX
+# CASE1-NEXT:     Link:    .symtab
+# CASE1-NEXT:     EntSize: 0x0000000000000004
+# CASE1-NEXT:     Entries: [ 0, 1, 2 ]
+# CASE1-NEXT: Symbols:
+# CASE1-NEXT:   - Name:  bar
+# CASE1-NEXT:     Type:  STT_SECTION
+# CASE1-NEXT:     Index: SHN_XINDEX
+# CASE1-NEXT:   - Name:  .symtab_shndx
+# CASE1-NEXT:     Type:  STT_SECTION
+# CASE1-NEXT:     Index: SHN_XINDEX
+# CASE1-NEXT: ...
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 1, 2 ]
+    Link:    .symtab
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has
+## symbols with section index == SHN_XINDEX, but no SHT_SYMTAB_SHNDX section.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: not obj2yaml %t2 2>&1 | FileCheck %s -DFILE=%t2 --check-prefix=CASE2
+
+# CASE2: Error reading file: [[FILE]]: extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has symbols with
+## section index == SHN_XINDEX, but SHT_SYMTAB_SHNDX table contains invalid indices
+## that are larger than total number of the sections.
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: not obj2yaml %t3 2>&1 | FileCheck %s -DFILE=%t3 --check-prefix=CASE3
+
+# CASE3: Error reading file: [[FILE]]: invalid section index: 254
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 254 ]
+    Link:    .symtab
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj is unable to dump an object, which has symbols with
+## section index == SHN_XINDEX, but SHT_SYMTAB_SHNDX table contains more
+## entries than the number of symbols in .symtab.
+
+# RUN: yaml2obj --docnum=4 %s -o %t4
+# RUN: not obj2yaml %t4 2>&1 | FileCheck %s -DFILE=%t4 --check-prefix=CASE4
+
+## FIXME: The error message below needs rewording. Size should not be equal to the number of symbols.
+## CASE4: Error reading file: [[FILE]]: SHT_SYMTAB_SHNDX section has sh_size (48) which is not equal to the number of symbols (3)
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 1, 2 ]
+    Link:    .symtab
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## ELF gABI allows having multiple SHT_SYMTAB_SHNDX sections.
+## We only support having one associated with .symtab now.
+
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: not obj2yaml %t5 2>&1 | FileCheck %s -DFILE=%t5 --check-prefix=CASE5
+
+# CASE5: Error reading file: [[FILE]]: multiple SHT_SYMTAB_SHNDX sections are not supported
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .symtab_shndx1
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0 ]
+    EntSize: 4
+    Link:    .symtab
+  - Name:    .symtab_shndx2
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0 ]
+    Link:    .symtab
+
+## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is
+## not associated with a SHT_SYMTAB section (this case is illegal).
+
+# RUN: yaml2obj --docnum=6 %s -o %t6
+# RUN: not obj2yaml %t6 2>&1 | FileCheck %s -DFILE=%t6 --check-prefix=CASE6
+
+# CASE6: Error reading file: [[FILE]]: SHT_SYMTAB_SHNDX section is linked with SHT_PROGBITS section (expected SHT_SYMTAB/SHT_DYNSYM)
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0 ]
+    Link:    .foo
+  - Name:    .foo
+    Type:    SHT_PROGBITS
+
+## Check that yaml2obj can't dump the object if SHT_SYMTAB_SHNDX is
+## associated with a SHT_DYNSYM section (not implemented yet).
+
+# RUN: yaml2obj --docnum=7 %s -o %t7
+# RUN: not obj2yaml %t7 2>&1 | FileCheck %s -DFILE=%t7 --check-prefix=CASE7
+
+# CASE7: Error reading file: [[FILE]]: only SHT_SYMTAB_SHNDX associated with SHT_SYMTAB are supported
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 1 ]
+    Link:    .dynsym
+DynamicSymbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX

Modified: llvm/trunk/test/tools/obj2yaml/special-symbol-indices.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/special-symbol-indices.yaml?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/test/tools/obj2yaml/special-symbol-indices.yaml (original)
+++ llvm/trunk/test/tools/obj2yaml/special-symbol-indices.yaml Thu Aug  8 02:49:05 2019
@@ -18,7 +18,7 @@
 # CHECK-NEXT:     Index:   SHN_HEXAGON_SCOMMON_1
 # CHECK-NEXT:     Binding: STB_GLOBAL
 # CHECK-NEXT:   - Name:    unknown_index
-# CHECK-NEXT:     Index:   0x0000FFFE
+# CHECK-NEXT:     Index:   0xFFFE
 # CHECK-NEXT:     Binding: STB_GLOBAL
 
 !ELF
@@ -47,8 +47,3 @@ Symbols:
   - Name:     unknown_index
     Index:    0xfffe
     Binding:  STB_GLOBAL
-
-## shn_xindex.o contains a symbol with st_shndx == SHN_XINDEX.
-## We do not support it at this moment.
-# RUN: not obj2yaml %S/Inputs/shn_xindex.o 2>&1 | FileCheck %s --check-prefix=ERR
-# ERR: Error reading file: {{.*}}shn_xindex.o: SHN_XINDEX symbols are not supported

Added: llvm/trunk/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml?rev=368272&view=auto
==============================================================================
--- llvm/trunk/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml (added)
+++ llvm/trunk/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml Thu Aug  8 02:49:05 2019
@@ -0,0 +1,129 @@
+## Check that yaml2obj is able to produce output
+## when a symbol with section index SHN_XINDEX is used,
+## but no SHT_SYMTAB_SHNDX section is defined.
+
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: not llvm-readobj --symbols 2>&1 %t1 | FileCheck %s --check-prefix=CASE1
+
+# CASE1: error: extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj keeps the SHT_SYMTAB_SHNDX section in the output
+## even when symbol's section index value is low enough to not require the extended symtab. 
+## Also, check that symbols in .symtab still have the SHN_XINDEX index.
+
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-readobj --sections --symbols --section-data 2>&1 %t2 | FileCheck %s --check-prefix=CASE2
+
+# CASE2:      Section {
+# CASE2:       Name: .symtab_shndx (1)
+# CASE2-NEXT:  Type: SHT_SYMTAB_SHNDX (0x12)
+
+# CASE2:      Name: .symtab
+# CASE2:      SectionData (
+# CASE2-NEXT:   0000: 00000000 00000000 00000000 00000000
+# CASE2-NEXT:   0010: 00000000 00000000 00000000 0300FFFF
+##                                                   ^-- 0xFFFF here is a SHN_XINDEX.
+# CASE2-NEXT:   0020: 00000000 00000000 00000000 00000000
+# CASE2-NEXT: )
+
+# CASE2:      Symbol {
+# CASE2:        Name: bar (0)
+# CASE2-NEXT:   Value: 0x0
+# CASE2-NEXT:   Size: 0
+# CASE2-NEXT:   Binding: Local (0x0)
+# CASE2-NEXT:   Type: Section (0x3)
+# CASE2-NEXT:   Other: 0
+# CASE2-NEXT:   Section: bar (0x1)
+# CASE2-NEXT: }
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 1 ]
+    Link:    .symtab
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj allows producing broken SHT_SYMTAB_SHNDX section
+## content (in the case below it contains 0xff as an index of a section,
+## which is larger than the total number of sections in the file).
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: not llvm-readobj --symbols 2>&1 %t3 | FileCheck %s --check-prefix=CASE3
+
+# CASE3: error: invalid section index: 255
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: bar
+    Type: SHT_PROGBITS
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0, 255 ]
+    Link:    .symtab
+Symbols:
+  - Type:  STT_SECTION
+    Index: SHN_XINDEX
+
+## Check that yaml2obj reports an error if a symbol index does not fit into 2 bytes.
+
+# RUN: not yaml2obj --docnum=4 %s -o %t4 2>&1 | FileCheck %s --check-prefix=CASE4
+
+# CASE4: error: out of range hex16 number
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Symbols:
+  - Type:  STT_SECTION
+    Index: 65536
+
+## Check we can set a custom sh_entsize for SHT_SYMTAB_SHNDX section.
+
+# RUN: yaml2obj --docnum=5 %s -o %t5
+# RUN: not llvm-readelf -S 2>&1 %t5 | FileCheck %s -DFILE=%t5 --check-prefix=CASE5
+
+# CASE5: error: '[[FILE]]': section [index 1] has an invalid sh_entsize: 2
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .symtab_shndx
+    Type:    SHT_SYMTAB_SHNDX
+    Entries: [ 0 ]
+    EntSize: 2
+    Link:    .symtab

Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=368272&r1=368271&r2=368272&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Thu Aug  8 02:49:05 2019
@@ -59,6 +59,8 @@ class ELFDumper {
   Expected<ELFYAML::RelocationSection *> dumpRelocSection(const Elf_Shdr *Shdr);
   Expected<ELFYAML::RawContentSection *>
   dumpContentSection(const Elf_Shdr *Shdr);
+  Expected<ELFYAML::SymtabShndxSection *>
+  dumpSymtabShndxSection(const Elf_Shdr *Shdr);
   Expected<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
   Expected<ELFYAML::VerdefSection *> dumpVerdefSection(const Elf_Shdr *Shdr);
   Expected<ELFYAML::SymverSection *> dumpSymverSection(const Elf_Shdr *Shdr);
@@ -158,15 +160,45 @@ template <class ELFT> Expected<ELFYAML::
 
   // Dump symbols. We need to do this early because other sections might want
   // to access the deduplicated symbol names that we also create here.
+  const Elf_Shdr *SymTab = nullptr;
+  const Elf_Shdr *SymTabShndx = nullptr;
+  const Elf_Shdr *DynSymTab = nullptr;
+
   for (const Elf_Shdr &Sec : Sections) {
-    if (Sec.sh_type == ELF::SHT_SYMTAB)
-      if (Error E = dumpSymbols(&Sec, Y->Symbols))
-        return std::move(E);
-    if (Sec.sh_type == ELF::SHT_DYNSYM)
-      if (Error E = dumpSymbols(&Sec, Y->DynamicSymbols))
-        return std::move(E);
+    if (Sec.sh_type == ELF::SHT_SYMTAB) {
+      SymTab = &Sec;
+    } else if (Sec.sh_type == ELF::SHT_DYNSYM) {
+      DynSymTab = &Sec;
+    } else if (Sec.sh_type == ELF::SHT_SYMTAB_SHNDX) {
+      // ABI allows us to have one SHT_SYMTAB_SHNDX for each symbol table.
+      // We only support having the SHT_SYMTAB_SHNDX for SHT_SYMTAB now.
+      if (SymTabShndx)
+        return createStringError(obj2yaml_error::not_implemented,
+                                 "multiple SHT_SYMTAB_SHNDX sections are not supported");
+      SymTabShndx = &Sec;
+    }
   }
 
+  // We need to locate the SHT_SYMTAB_SHNDX section early, because it might be
+  // needed for dumping symbols.
+  if (SymTabShndx) {
+    if (!SymTab || SymTabShndx->sh_link != SymTab - Sections.begin())
+      return createStringError(
+          obj2yaml_error::not_implemented,
+          "only SHT_SYMTAB_SHNDX associated with SHT_SYMTAB are supported");
+
+    auto TableOrErr = Obj.getSHNDXTable(*SymTabShndx);
+    if (!TableOrErr)
+      return TableOrErr.takeError();
+    ShndxTable = *TableOrErr;
+  }
+  if (SymTab)
+    if (Error E = dumpSymbols(SymTab, Y->Symbols))
+      return std::move(E);
+  if (DynSymTab)
+    if (Error E = dumpSymbols(DynSymTab, Y->DynamicSymbols))
+      return std::move(E);
+
   for (const Elf_Shdr &Sec : Sections) {
     switch (Sec.sh_type) {
     case ELF::SHT_DYNAMIC: {
@@ -182,10 +214,11 @@ template <class ELFT> Expected<ELFYAML::
       // Do not dump these sections.
       break;
     case ELF::SHT_SYMTAB_SHNDX: {
-      auto TableOrErr = Obj.getSHNDXTable(Sec);
-      if (!TableOrErr)
-        return TableOrErr.takeError();
-      ShndxTable = *TableOrErr;
+      Expected<ELFYAML::SymtabShndxSection *> SecOrErr =
+          dumpSymtabShndxSection(&Sec);
+      if (!SecOrErr)
+        return SecOrErr.takeError();
+      Y->Sections.emplace_back(*SecOrErr);
       break;
     }
     case ELF::SHT_REL:
@@ -309,9 +342,6 @@ Error ELFDumper<ELFT>::dumpSymbol(const
   S.Name = SymbolNameOrErr.get();
 
   if (Sym->st_shndx >= ELF::SHN_LORESERVE) {
-    if (Sym->st_shndx == ELF::SHN_XINDEX)
-      return createStringError(obj2yaml_error::not_implemented,
-                               "SHN_XINDEX symbols are not supported");
     S.Index = (ELFYAML::ELF_SHN)Sym->st_shndx;
     return Error::success();
   }
@@ -499,6 +529,21 @@ ELFDumper<ELFT>::dumpContentSection(cons
   return S.release();
 }
 
+template <class ELFT>
+Expected<ELFYAML::SymtabShndxSection *>
+ELFDumper<ELFT>::dumpSymtabShndxSection(const Elf_Shdr *Shdr) {
+  auto S = make_unique<ELFYAML::SymtabShndxSection>();
+  if (Error E = dumpCommonSection(Shdr, *S))
+    return std::move(E);
+
+  auto EntriesOrErr = Obj.template getSectionContentsAsArray<Elf_Word>(Shdr);
+  if (!EntriesOrErr)
+    return EntriesOrErr.takeError();
+  for (const Elf_Word &E : *EntriesOrErr)
+    S->Entries.push_back(E);
+  return S.release();
+}
+
 template <class ELFT>
 Expected<ELFYAML::NoBitsSection *>
 ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {




More information about the llvm-commits mailing list