summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Rimar <grimar@accesssoftek.com>2019-08-08 09:49:05 +0000
committerGeorge Rimar <grimar@accesssoftek.com>2019-08-08 09:49:05 +0000
commitd3963051c49037b1ce6edace90f59056d3bddffa (patch)
treed9ac3df45a3acaffb0611b8ce714efe2d7d7eaba
parent6db975b7b89df9d4b27fa40411963f8f8891c349 (diff)
downloadbcm5719-llvm-d3963051c49037b1ce6edace90f59056d3bddffa.tar.gz
bcm5719-llvm-d3963051c49037b1ce6edace90f59056d3bddffa.zip
[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 llvm-svn: 368272
-rw-r--r--llvm/include/llvm/Object/ELF.h7
-rw-r--r--llvm/include/llvm/ObjectYAML/ELFYAML.h11
-rw-r--r--llvm/lib/ObjectYAML/ELFEmitter.cpp21
-rw-r--r--llvm/lib/ObjectYAML/ELFYAML.cpp14
-rw-r--r--llvm/test/Object/invalid.test5
-rw-r--r--llvm/test/tools/llvm-readobj/elf-section-types.test3
-rw-r--r--llvm/test/tools/obj2yaml/Inputs/shn_xindex.obin403 -> 0 bytes
-rw-r--r--llvm/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml189
-rw-r--r--llvm/test/tools/obj2yaml/special-symbol-indices.yaml7
-rw-r--r--llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml129
-rw-r--r--llvm/tools/obj2yaml/elf2yaml.cpp71
11 files changed, 428 insertions, 29 deletions
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index a9a78e9fd4d..5b7ad184fc8 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -635,8 +635,11 @@ ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section,
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) +
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 89c0c5827f9..a282f329945 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -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;
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 370d62088a4..d2ceb40e2c1 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -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(ELFState<ELFT> &State,
} 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;
@@ -741,6 +747,21 @@ bool ELFState<ELFT>::writeSectionContent(
}
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,
ContiguousBlobAccumulator &CBA) {
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 7497154c757..be191118c59 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -563,7 +563,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHN>::enumeration(
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>::validate(IO &IO,
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, ELFYAML::Group &Group) {
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<ELFYAML::Section>>::mapping(
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());
diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test
index 05f38e9d007..7566ab23d17 100644
--- a/llvm/test/Object/invalid.test
+++ b/llvm/test/Object/invalid.test
@@ -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.
diff --git a/llvm/test/tools/llvm-readobj/elf-section-types.test b/llvm/test/tools/llvm-readobj/elf-section-types.test
index f65655afbcc..9b3e350173f 100644
--- a/llvm/test/tools/llvm-readobj/elf-section-types.test
+++ b/llvm/test/tools/llvm-readobj/elf-section-types.test
@@ -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
diff --git a/llvm/test/tools/obj2yaml/Inputs/shn_xindex.o b/llvm/test/tools/obj2yaml/Inputs/shn_xindex.o
deleted file mode 100644
index 73e2b60ba1e..00000000000
--- a/llvm/test/tools/obj2yaml/Inputs/shn_xindex.o
+++ /dev/null
Binary files differ
diff --git a/llvm/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml b/llvm/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml
new file mode 100644
index 00000000000..e926019655d
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/elf-sht-symtab-shndx.yaml
@@ -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
diff --git a/llvm/test/tools/obj2yaml/special-symbol-indices.yaml b/llvm/test/tools/obj2yaml/special-symbol-indices.yaml
index fcc2a705f9c..9ba424101ed 100644
--- a/llvm/test/tools/obj2yaml/special-symbol-indices.yaml
+++ b/llvm/test/tools/obj2yaml/special-symbol-indices.yaml
@@ -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
diff --git a/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml b/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml
new file mode 100644
index 00000000000..c8d86b1ed2f
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml
@@ -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
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 717b9f13672..a228d3917ee 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -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::Object *> ELFDumper<ELFT>::dump() {
// 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::Object *> ELFDumper<ELFT>::dump() {
// 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 Elf_Sym *Sym, const Elf_Shdr *SymTab,
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();
}
@@ -500,6 +530,21 @@ ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) {
}
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) {
auto S = make_unique<ELFYAML::NoBitsSection>();
OpenPOWER on IntegriCloud