diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -235,13 +235,14 @@ # INVALID-PH-ENTSIZE: error: '[[FILE]]': invalid e_phentsize: 12336 -## Check that llvm-readobj reports an error when we have no SHT_SYMTAB_SHNDX section, +## Check that llvm-readobj reports a warning when we have no SHT_SYMTAB_SHNDX section, ## but have a symbol referencing it. -# RUN: not llvm-readobj --symbols %p/Inputs/invalid-ext-symtab-index.elf-x86-64 2>&1 | \ +# RUN: llvm-readobj --symbols %p/Inputs/invalid-ext-symtab-index.elf-x86-64 2>&1 | \ # RUN: FileCheck -DFILE=%p/Inputs/invalid-ext-symtab-index.elf-x86-64 --check-prefix=INVALID-EXT-SYMTAB-INDEX %s -# INVALID-EXT-SYMTAB-INDEX: error: '[[FILE]]': extended symbol index (0) is past the end of the SHT_SYMTAB_SHNDX section of size 0 +# INVALID-EXT-SYMTAB-INDEX: warning: '[[FILE]]': extended symbol index (0) is past the end of the SHT_SYMTAB_SHNDX section of size 0 +# INVALID-EXT-SYMTAB-INDEX: Section: Reserved (0xFFFF) ## Check that llvm-readobj reports an error if a relocation section ## has a broken sh_offset (past the end of the file). diff --git a/llvm/test/tools/llvm-readobj/elf-section-symbols.test b/llvm/test/tools/llvm-readobj/elf-section-symbols.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/elf-section-symbols.test @@ -0,0 +1,85 @@ +## ELF section symbols use the section names when printing. This test verifies +## this and also that appropriate things are printed if the section is somehow +## invalid. + +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-readobj %t1 --symbols 2> %t.llvm.err1 | FileCheck %s --check-prefix=LLVM1 +# RUN: FileCheck %s --input-file %t.llvm.err1 --check-prefix=WARN1 --implicit-check-not=warning +# RUN: llvm-readelf %t1 --symbols 2> %t.gnu.err1 | FileCheck %s --check-prefix=GNU1 +# RUN: FileCheck %s --input-file %t.gnu.err1 --check-prefix=WARN1 --implicit-check-not=warning + +# LLVM1: Name: (0) +# LLVM1: Name: .foo (0) +# LLVM1: Name:
(0) +# LLVM1: Name: .bar (0) +# LLVM1: Name:
(0) + +# GNU1: Symbol table '.symtab' contains 5 entries: +# GNU1-NEXT: Num: {{.*}} Type {{.*}} Ndx Name +# GNU1-NEXT: 0: {{.*}} NOTYPE {{.*}} UND {{$}} +# GNU1-NEXT: 1: {{.*}} SECTION {{.*}} 1 .foo +# GNU1-NEXT: 2: {{.*}} SECTION {{.*}} 67
+# GNU1-NEXT: 3: {{.*}} SECTION {{.*}} 2 .bar +# GNU1-NEXT: 4: {{.*}} SECTION {{.*}} 66
+ +# WARN1: warning: '{{.*}}.tmp1': invalid section index: 67 +# WARN1: warning: '{{.*}}.tmp1': invalid section index: 66 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .foo + Type: SHT_PROGBITS + - Name: .bar + Type: SHT_PROGBITS + - Name: .symtab_shndx + Type: SHT_SYMTAB_SHNDX + Link: .symtab + Entries: [ 0, 0, 0, 2, 0x42 ] +Symbols: + - Name: "" + Section: .foo + Type: STT_SECTION + - Name: "" + Index: 0x43 + Type: STT_SECTION + # Section symbol via SHT_SYMTAB_SHNDX. + - Name: "" + Index: SHN_XINDEX + Type: STT_SECTION + # Section symbol via SHT_SYMTAB_SHNDX with invalid index. + - Name: "" + Index: SHN_XINDEX + Type: STT_SECTION + +# RUN: yaml2obj %s --docnum=2 -o %t2 +# RUN: llvm-readobj %t2 --symbols 2> %t.llvm.err2 | FileCheck %s --check-prefix=LLVM2 +# RUN: FileCheck %s --input-file %t.llvm.err2 --check-prefix=WARN2 --implicit-check-not=warning +# RUN: llvm-readelf %t2 --symbols 2> %t.gnu.err2 | FileCheck %s --check-prefix=GNU2 +# RUN: FileCheck %s --input-file %t.gnu.err2 --check-prefix=WARN2 --implicit-check-not=warning + +# LLVM2: Name: (0) +# LLVM2: Name: (0) + +# GNU2: Symbol table '.symtab' contains 2 entries: +# GNU2-NEXT: Num: {{.*}} Type {{.*}} Ndx Name +# GNU2-NEXT: 0: {{.*}} NOTYPE {{.*}} UND {{$}} +# GNU2-NEXT: 1: {{.*}} SECTION {{.*}} RSV[0xffff] + +# WARN2: warning: '{{.*}}.tmp2': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Symbols: + # Section symbol via SHT_SYMTAB_SHNDX when SHT_SYMTAB_SHNDX is missing. + - Name: "" + Index: SHN_XINDEX + Type: STT_SECTION diff --git a/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test b/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test --- a/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test +++ b/llvm/test/tools/llvm-readobj/elf-symbol-shndx.test @@ -1,17 +1,12 @@ -# Show that llvm-readobj prints symbol shndxes correctly, for valid indexes, -# invalid indexes (i.e. section indexes that don't correspond to a real -# section), reserved values and processor/os-specific index values, for both GNU -# and LLVM styles. +## Show that llvm-readobj prints symbol shndxes correctly, for valid indexes, +## invalid indexes (i.e. section indexes that don't correspond to a real +## section), reserved values and processor/os-specific index values, for both GNU +## and LLVM styles. # RUN: yaml2obj --docnum=1 %s > %t1 # RUN: llvm-readobj --symbols %t1 | FileCheck %s --check-prefix=LLVM1 # RUN: llvm-readelf --symbols %t1 | FileCheck %s --check-prefix=GNU1 -# llvm-readobj doesn't accept shndx values that are not valid section indexes -# for LLVM style, so only test GNU output in this case. -# RUN: yaml2obj --docnum=2 %s > %t2 -# RUN: llvm-readelf --symbols %t2 | FileCheck %s --check-prefix=GNU2 - # LLVM1: Name: undef # LLVM1: Section: # LLVM1-SAME: Undefined (0x0) @@ -49,11 +44,6 @@ # GNU1-NEXT: 7: {{.*}} RSV[0xfffe] reserved # GNU1-NEXT: 8: {{.*}} 1 xindex -# GNU2: Symbol table '.symtab' contains 2 entries: -# GNU2-NEXT: Num: {{.*}} Ndx Name -# GNU2-NEXT: 0: {{.*}} UND -# GNU2-NEXT: 1: {{.*}} 66 bad - --- !ELF FileHeader: Class: ELFCLASS32 @@ -92,13 +82,106 @@ Index: SHN_XINDEX Binding: STB_GLOBAL +## In this case, the index does not correspond to a real section. Check that GNU +## style just prints the section index as normal and LLVM style prints a warning +## (but only once for each warning). +# RUN: yaml2obj --docnum=2 %s > %t2 +# RUN: llvm-readobj --symbols %t2 2> %t2.llvm.err | FileCheck %s --check-prefix=LLVM2 +# RUN: FileCheck %s --input-file=%t2.llvm.err --check-prefix=BAD-SHNDX --implicit-check-not=warning +# RUN: llvm-readelf --symbols %t2 2> %t2.gnu.err | FileCheck %s --check-prefix=GNU2 +# RUN: FileCheck %s --input-file=%t2.gnu.err --allow-empty --implicit-check-not={{.}} + +# LLVM2: Name: bad +# LLVM2: Section: +# LLVM2-SAME: (0x42) +# LLVM2: Name: bad2 +# LLVM2: Section: +# LLVM2-SAME: (0x42) +# LLVM2: Name: bad3 +# LLVM2: Section: +# LLVM2-SAME: (0x43) +# LLVM2: Name: invalid_shndx +# LLVM2: Section: +# LLVM2-SAME: (0x9) +# LLVM2: Name: invalid_shndx2 +# LLVM2: Section: +# LLVM2-SAME: (0x9) +# LLVM2: Name: invalid_shndx3 +# LLVM2: Section: +# LLVM2-SAME: (0xA) + +# GNU2: Symbol table '.symtab' contains 7 entries: +# GNU2-NEXT: Num: {{.*}} Ndx Name +# GNU2-NEXT: 0: {{.*}} UND +# GNU2-NEXT: 1: {{.*}} 66 bad +# GNU2-NEXT: 2: {{.*}} 66 bad2 +# GNU2-NEXT: 3: {{.*}} 67 bad3 +# GNU2-NEXT: 4: {{.*}} 9 invalid_shndx +# GNU2-NEXT: 5: {{.*}} 9 invalid_shndx2 +# GNU2-NEXT: 6: {{.*}} 10 invalid_shndx3 + +# BAD-SHNDX: warning: '{{.*}}tmp2': invalid section index: 66 +# BAD-SHNDX: warning: '{{.*}}tmp2': invalid section index: 67 +# BAD-SHNDX: warning: '{{.*}}tmp2': invalid section index: 9 +# BAD-SHNDX: warning: '{{.*}}tmp2': invalid section index: 10 + --- !ELF FileHeader: Class: ELFCLASS32 Data: ELFDATA2LSB Type: ET_REL Machine: EM_386 +Sections: + - Name: .symtab_shndx + Type: SHT_SYMTAB_SHNDX + Link: .symtab + Entries: [ 0, 0, 0, 0, 9, 9, 10 ] Symbols: - Name: bad Index: 0x42 - Binding: STB_GLOBAL + - Name: bad2 + Index: 0x42 + - Name: bad3 + Index: 0x43 + - Name: invalid_shndx + Index: SHN_XINDEX + - Name: invalid_shndx2 + Index: SHN_XINDEX + - Name: invalid_shndx3 + Index: SHN_XINDEX + +## In this case, the symtab shndx section is missing, so symbols with section +## indexes of SHN_XINDEX print as Reserved symbols. +# RUN: yaml2obj --docnum=3 %s > %t3 +# RUN: llvm-readobj --symbols %t3 2> %t3.llvm.err | FileCheck %s --check-prefix=LLVM3 +# RUN: FileCheck %s --input-file=%t3.llvm.err --check-prefix=NO-SYMTAB-SHNDX --implicit-check-not=warning +# RUN: llvm-readelf --symbols %t3 2> %t3.gnu.err | FileCheck %s --check-prefix=GNU3 +# RUN: FileCheck %s --input-file=%t3.gnu.err --check-prefix=NO-SYMTAB-SHNDX --implicit-check-not=warning + +# LLVM3: Name: no_shndx +# LLVM3: Section: +# LLVM3-SAME: Reserved (0xFFFF) +# LLVM3: Name: no_shndx2 +# LLVM3: Section: +# LLVM3-SAME: Reserved (0xFFFF) + +# GNU3: Symbol table '.symtab' contains 3 entries: +# GNU3-NEXT: Num: {{.*}} Ndx Name +# GNU3-NEXT: 0: {{.*}} UND +# GNU3-NEXT: 1: {{.*}} RSV[0xffff] no_shndx +# GNU3-NEXT: 2: {{.*}} RSV[0xffff] no_shndx2 + +# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0 +# NO-SYMTAB-SHNDX: warning: '{{.*}}tmp3': extended symbol index (2) is past the end of the SHT_SYMTAB_SHNDX section of size 0 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Symbols: + - Name: no_shndx + Index: SHN_XINDEX + - Name: no_shndx2 + Index: SHN_XINDEX diff --git a/llvm/test/tools/yaml2obj/dynamic-symbols.yaml b/llvm/test/tools/yaml2obj/dynamic-symbols.yaml --- a/llvm/test/tools/yaml2obj/dynamic-symbols.yaml +++ b/llvm/test/tools/yaml2obj/dynamic-symbols.yaml @@ -44,7 +44,7 @@ ## Check we can use numeric values to refer to sections. # RUN: yaml2obj --docnum=2 %s -o %t2 -# RUN: not llvm-readobj --dyn-symbols %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=NUM +# RUN: llvm-readobj --dyn-symbols %t2 2>&1 | FileCheck -DFILE=%t2 %s --check-prefix=NUM # NUM: Name: foo # NUM: Section: @@ -54,7 +54,10 @@ # NUM: Section: # NUM-SAME: .strtab (0x2) -# NUM: error: '[[FILE]]': invalid section index: 255 +# NUM: Name: zed +# NUM: warning: '[[FILE]]': invalid section index: 255 +# NUM: Section: +# NUM-SAME: (0xFF) --- !ELF FileHeader: diff --git a/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml b/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml --- a/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml +++ b/llvm/test/tools/yaml2obj/elf-sht-symtab-shndx.yaml @@ -3,9 +3,9 @@ ## but no SHT_SYMTAB_SHNDX section is defined. # RUN: yaml2obj --docnum=1 %s -o %t1 -# RUN: not llvm-readobj --symbols 2>&1 %t1 | FileCheck -DFILE=%t1 %s --check-prefix=CASE1 +# RUN: llvm-readobj --symbols 2>&1 %t1 | FileCheck -DFILE=%t1 %s --check-prefix=CASE1 -# CASE1: error: '[[FILE]]': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0 +# CASE1: warning: '[[FILE]]': extended symbol index (1) is past the end of the SHT_SYMTAB_SHNDX section of size 0 --- !ELF FileHeader: @@ -71,9 +71,9 @@ ## 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 -DFILE=%t3 --check-prefix=CASE3 +# RUN: llvm-readobj --symbols 2>&1 %t3 | FileCheck %s -DFILE=%t3 --check-prefix=CASE3 -# CASE3: error: '[[FILE]]': invalid section index: 255 +# CASE3: warning: '[[FILE]]': invalid section index: 255 --- !ELF FileHeader: diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -433,6 +433,8 @@ virtual void printMipsABIFlags(const ELFObjectFile *Obj) = 0; const ELFDumper *dumper() const { return Dumper; } + void reportUniqueWarning(Error Err) const; + protected: std::function WarningHandler; StringRef FileName; @@ -556,6 +558,14 @@ void printSectionMapping(const ELFO *Obj); }; +template +void DumpStyle::reportUniqueWarning(Error Err) const { + handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { + cantFail(WarningHandler(EI.message()), + "WarningHandler should always return ErrorSuccess"); + }); +} + template class LLVMStyle : public DumpStyle { public: TYPEDEF_ELF_TYPES(ELFT) @@ -824,10 +834,18 @@ if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) { Elf_Sym_Range Syms = unwrapOrError( ObjF->getFileName(), ObjF->getELFFile()->symbols(DotSymtabSec)); - unsigned SectionIndex = unwrapOrError( - ObjF->getFileName(), getSymbolSectionIndex(Symbol, Syms.begin())); - return unwrapOrError(ObjF->getFileName(), - getSymbolSectionName(Symbol, SectionIndex)); + Expected SectionIndex = + getSymbolSectionIndex(Symbol, Syms.begin()); + if (!SectionIndex) { + ELFDumperStyle->reportUniqueWarning(SectionIndex.takeError()); + return ""; + } + Expected NameOrErr = getSymbolSectionName(Symbol, *SectionIndex); + if (!NameOrErr) { + ELFDumperStyle->reportUniqueWarning(NameOrErr.takeError()); + return ("
").str(); + } + return *NameOrErr; } if (!IsDynamic) @@ -3298,12 +3316,18 @@ return "ABS"; case ELF::SHN_COMMON: return "COM"; - case ELF::SHN_XINDEX: - return to_string(format_decimal( - unwrapOrError(this->FileName, - object::getExtendedSymbolTableIndex( - Symbol, FirstSym, this->dumper()->getShndxTable())), - 3)); + case ELF::SHN_XINDEX: { + Expected IndexOrErr = object::getExtendedSymbolTableIndex( + Symbol, FirstSym, this->dumper()->getShndxTable()); + if (!IndexOrErr) { + assert(Symbol->st_shndx == SHN_XINDEX && + "getSymbolSectionIndex should only fail due to an invalid " + "SHT_SYMTAB_SHNDX table/reference"); + this->reportUniqueWarning(IndexOrErr.takeError()); + return "RSV[0xffff]"; + } + return to_string(format_decimal(*IndexOrErr, 3)); + } default: // Find if: // Processor specific @@ -5454,11 +5478,25 @@ template void LLVMStyle::printSymbolSection(const Elf_Sym *Symbol, const Elf_Sym *First) { - unsigned SectionIndex = unwrapOrError( - this->FileName, this->dumper()->getSymbolSectionIndex(Symbol, First)); - StringRef SectionName = unwrapOrError( - this->FileName, this->dumper()->getSymbolSectionName(Symbol, SectionIndex)); - W.printHex("Section", SectionName, SectionIndex); + Expected SectionIndex = + this->dumper()->getSymbolSectionIndex(Symbol, First); + if (!SectionIndex) { + assert(Symbol->st_shndx == SHN_XINDEX && + "getSymbolSectionIndex should only fail due to an invalid " + "SHT_SYMTAB_SHNDX table/reference"); + this->reportUniqueWarning(SectionIndex.takeError()); + W.printHex("Section", "Reserved", SHN_XINDEX); + return; + } + + Expected SectionName = + this->dumper()->getSymbolSectionName(Symbol, *SectionIndex); + if (!SectionName) { + this->reportUniqueWarning(SectionName.takeError()); + W.printHex("Section", "", *SectionIndex); + } else { + W.printHex("Section", *SectionName, *SectionIndex); + } } template