From 64156347baa4452489ec1c0fab8eec48d1ffd168 Mon Sep 17 00:00:00 2001 From: Georgii Rymar Date: Wed, 1 Jul 2020 15:25:33 +0300 Subject: [PATCH] [llvm-readelf] - Do not error out when dumping symbols. When the --symbols option/--dyn-symbols is given we might report an error and exit when something goes not right. E.g. when the SHT_SYMTAB section is broken. Though we could report a warning and try to continue dumping instead in many cases. This patch removes `unwrapOrErr` calls from the code involved in the flow described. Differential revision: https://reviews.llvm.org/D82955 --- llvm/test/Object/invalid.test | 28 +++--- llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test | 29 +++++- llvm/test/tools/llvm-readobj/ELF/symbols.test | 115 ++++++++++++++++++++++ llvm/tools/llvm-readobj/ELFDumper.cpp | 40 ++++++-- 4 files changed, 187 insertions(+), 25 deletions(-) diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index a7363ab..3a7ddab 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -115,9 +115,9 @@ Symbols: ## Check that llvm-readobj reports an error if .symtab has an invalid sh_entsize. # RUN: yaml2obj %s --docnum=6 -o %t6 -# RUN: not llvm-readobj --symbols %t6 2>&1 | FileCheck -DFILE=%t6 --check-prefix=INVALID-SYM-SIZE %s +# RUN: llvm-readobj --symbols %t6 2>&1 | FileCheck -DFILE=%t6 --check-prefix=INVALID-SYM-SIZE %s -# INVALID-SYM-SIZE: error: '[[FILE]]': section [index 1] has an invalid sh_entsize: 32 +# INVALID-SYM-SIZE: warning: '[[FILE]]': unable to read symbols from the SHT_SYMTAB section: section [index 1] has an invalid sh_entsize: 32 --- !ELF FileHeader: @@ -152,13 +152,13 @@ Sections: DynamicSymbols: - Name: foo -## Check that llvm-readobj reports an error if .symtab has an invalid sh_link value, +## Check that llvm-readobj reports a warning if .symtab has an invalid sh_link value, ## which is greater than number of sections. # RUN: yaml2obj %s --docnum=8 -o %t8 -# RUN: not llvm-readobj --symbols %t8 2>&1 | FileCheck -DFILE=%t8 --check-prefix=INVALID-SYMTAB-LINK %s +# RUN: llvm-readobj --symbols %t8 2>&1 | FileCheck -DFILE=%t8 --check-prefix=INVALID-SYMTAB-LINK %s -# INVALID-SYMTAB-LINK: error: '[[FILE]]': invalid section index: 255 +# INVALID-SYMTAB-LINK: warning: '[[FILE]]': unable to get the string table for the SHT_SYMTAB section: invalid section index: 255 --- !ELF FileHeader: @@ -187,13 +187,13 @@ FileHeader: Machine: EM_X86_64 SHEntSize: 1 -## Check that llvm-readobj reports an error if .symtab has sh_size +## Check that llvm-readobj reports a warning if .symtab has sh_size ## that is not a multiple of sh_entsize. # RUN: yaml2obj %s --docnum=10 -o %t10 -# RUN: not llvm-readobj --symbols %t10 2>&1 | FileCheck -DFILE=%t10 --check-prefix=INVALID-SYMTAB-SIZE %s +# RUN: llvm-readobj --symbols %t10 2>&1 | FileCheck -DFILE=%t10 --check-prefix=INVALID-SYMTAB-SIZE %s -# INVALID-SYMTAB-SIZE: error: '[[FILE]]': section [index 1] has an invalid sh_size (1) which is not a multiple of its sh_entsize (24) +# INVALID-SYMTAB-SIZE: warning: '[[FILE]]': unable to read symbols from the SHT_SYMTAB section: section [index 1] has an invalid sh_size (1) which is not a multiple of its sh_entsize (24) --- !ELF FileHeader: @@ -276,13 +276,13 @@ Sections: Type: SHT_RELA ShOffset: 0x10000 -## Check that llvm-objdump reports an error when we try to print symbols and +## Check that llvm-objdump reports a warning when we try to print symbols and ## .shstrtab has a broken sh_offset so large that sh_offset + sh_size overflows the platform address size type. # RUN: yaml2obj %s --docnum=14 -o %t14 -# RUN: not llvm-readobj --symbols %t14 2>&1 | FileCheck -DFILE=%t14 --check-prefix=INVALID-SECTION-SIZE2 %s +# RUN: llvm-readobj --symbols %t14 2>&1 | FileCheck -DFILE=%t14 --check-prefix=INVALID-SECTION-SIZE2 %s -# INVALID-SECTION-SIZE2: error: '[[FILE]]': section [index 1] has a sh_offset (0xffffffff) + sh_size (0x1b) that cannot be represented +# INVALID-SECTION-SIZE2: warning: '[[FILE]]': unable to get the name of the SHT_SYMTAB section: section [index 1] has a sh_offset (0xffffffff) + sh_size (0x1b) that cannot be represented --- !ELF FileHeader: @@ -364,13 +364,13 @@ Sections: Type: SHT_PROGBITS ShOffset: 0xFFFF0000 -## Check that llvm-readobj reports an error if symbol name +## Check that llvm-readobj reports a warning if symbol name ## offset goes past the end of the symbol string table. # RUN: yaml2obj %s --docnum=18 -o %t18 -# RUN: not llvm-readobj --symbols %t18 2>&1 | FileCheck -DFILE=%t18 --check-prefix=INVALID-SYM-NAME %s +# RUN: llvm-readobj --symbols %t18 2>&1 | FileCheck -DFILE=%t18 --check-prefix=INVALID-SYM-NAME %s -# INVALID-SYM-NAME: error: '[[FILE]]': st_name (0x1) is past the end of the string table of size 0x1 +# INVALID-SYM-NAME: warning: '[[FILE]]': st_name (0x1) is past the end of the string table of size 0x1 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test index 817d52f..c4ac2f8 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test +++ b/llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test @@ -434,9 +434,9 @@ Sections: ## table goes past the end of the file. Document we stop dumping symbols and report an error. # RUN: yaml2obj %s --docnum=13 -o %t14 -# RUN: not llvm-readobj --dyn-symbols %t14 2>&1 | \ +# RUN: llvm-readobj --dyn-symbols %t14 2>&1 | \ # RUN: FileCheck %s -DFILE=%t14 --check-prefix=DYNSTR-INVALID-LLVM -# RUN: not llvm-readelf --dyn-symbols %t14 2>&1 | \ +# RUN: llvm-readelf --dyn-symbols %t14 2>&1 | \ # RUN: FileCheck %s -DFILE=%t14 --check-prefix=DYNSTR-INVALID-GNU # DYNSTR-INVALID-LLVM: warning: '[[FILE]]': the dynamic string table at 0x78 goes past the end of the file (0x2a8) with DT_STRSZ = 0xffffffff @@ -450,13 +450,34 @@ Sections: # DYNSTR-INVALID-LLVM-NEXT: Other: 0 # DYNSTR-INVALID-LLVM-NEXT: Section: Undefined (0x0) # DYNSTR-INVALID-LLVM-NEXT: } -# DYNSTR-INVALID-LLVM-NEXT: error: '[[FILE]]': st_name (0xffffff00) is past the end of the string table of size 0x6 +# DYNSTR-INVALID-LLVM-NEXT: warning: '[[FILE]]': st_name (0xffffff00) is past the end of the string table of size 0x6 +# DYNSTR-INVALID-LLVM-NEXT: Symbol { +# DYNSTR-INVALID-LLVM-NEXT: Name: (4294967040) +# DYNSTR-INVALID-LLVM-NEXT: Value: 0x0 +# DYNSTR-INVALID-LLVM-NEXT: Size: 0 +# DYNSTR-INVALID-LLVM-NEXT: Binding: Local (0x0) +# DYNSTR-INVALID-LLVM-NEXT: Type: None (0x0) +# DYNSTR-INVALID-LLVM-NEXT: Other: 0 +# DYNSTR-INVALID-LLVM-NEXT: Section: Undefined (0x0) +# DYNSTR-INVALID-LLVM-NEXT: } +# DYNSTR-INVALID-LLVM-NEXT: Symbol { +# DYNSTR-INVALID-LLVM-NEXT: Name: test (1) +# DYNSTR-INVALID-LLVM-NEXT: Value: 0x0 +# DYNSTR-INVALID-LLVM-NEXT: Size: 0 +# DYNSTR-INVALID-LLVM-NEXT: Binding: Local (0x0) +# DYNSTR-INVALID-LLVM-NEXT: Type: None (0x0) +# DYNSTR-INVALID-LLVM-NEXT: Other: 0 +# DYNSTR-INVALID-LLVM-NEXT: Section: Undefined (0x0) +# DYNSTR-INVALID-LLVM-NEXT: } +# DYNSTR-INVALID-LLVM-NEXT: ] # DYNSTR-INVALID-GNU: warning: '[[FILE]]': the dynamic string table at 0x78 goes past the end of the file (0x2a8) with DT_STRSZ = 0xffffffff # DYNSTR-INVALID-GNU: Symbol table '.dynsym' contains 3 entries: # DYNSTR-INVALID-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name # DYNSTR-INVALID-GNU-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND -# DYNSTR-INVALID-GNU-NEXT: error: '[[FILE]]': st_name (0xffffff00) is past the end of the string table of size 0x6 +# DYNSTR-INVALID-GNU-NEXT: warning: '[[FILE]]': st_name (0xffffff00) is past the end of the string table of size 0x6 +# DYNSTR-INVALID-GNU-NEXT: 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# DYNSTR-INVALID-GNU-NEXT: 2: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND test --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/ELF/symbols.test b/llvm/test/tools/llvm-readobj/ELF/symbols.test index ef45b71..da42569 100644 --- a/llvm/test/tools/llvm-readobj/ELF/symbols.test +++ b/llvm/test/tools/llvm-readobj/ELF/symbols.test @@ -116,3 +116,118 @@ Symbols: Value: 0x2 DynamicSymbols: - Name: zed + +## Check the behavior when we are unable to print symbols due to an error. + +## Case 1: check we are able to dump symbols even when can't get the string table for the +## SHT_SYMTAB section because of invalid sh_link value. +# RUN: yaml2obj --docnum=2 -DLINK=0xff %s -o %t64.err1 +# RUN: llvm-readobj --symbols %t64.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err1 --check-prefix=STRTAB-LINK-ERR-LLVM +# RUN: llvm-readelf --symbols %t64.err1 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err1 --check-prefix=STRTAB-LINK-ERR-GNU + +# STRTAB-LINK-ERR-LLVM: Symbols [ +# STRTAB-LINK-ERR-LLVM-NEXT: warning: '[[FILE]]': unable to get the string table for the SHT_SYMTAB section: invalid section index: 255 +# STRTAB-LINK-ERR-LLVM-NEXT: warning: '[[FILE]]': st_name (0x0) is past the end of the string table of size 0x0 +# STRTAB-LINK-ERR-LLVM-NEXT: Symbol { +# STRTAB-LINK-ERR-LLVM-NEXT: Name: (0) +# STRTAB-LINK-ERR-LLVM-NEXT: Value: 0x0 +# STRTAB-LINK-ERR-LLVM-NEXT: Size: 0 +# STRTAB-LINK-ERR-LLVM-NEXT: Binding: Local (0x0) +# STRTAB-LINK-ERR-LLVM-NEXT: Type: None (0x0) +# STRTAB-LINK-ERR-LLVM-NEXT: Other: 0 +# STRTAB-LINK-ERR-LLVM-NEXT: Section: Undefined (0x0) +# STRTAB-LINK-ERR-LLVM-NEXT: } +# STRTAB-LINK-ERR-LLVM-NEXT: warning: '[[FILE]]': st_name (0x1) is past the end of the string table of size 0x0 +# STRTAB-LINK-ERR-LLVM-NEXT: Symbol { +# STRTAB-LINK-ERR-LLVM-NEXT: Name: (1) +# STRTAB-LINK-ERR-LLVM-NEXT: Value: 0x1 +# STRTAB-LINK-ERR-LLVM-NEXT: Size: 0 +# STRTAB-LINK-ERR-LLVM-NEXT: Binding: Global (0x1) +# STRTAB-LINK-ERR-LLVM-NEXT: Type: None (0x0) +# STRTAB-LINK-ERR-LLVM-NEXT: Other: 0 +# STRTAB-LINK-ERR-LLVM-NEXT: Section: .symtab (0x1) +# STRTAB-LINK-ERR-LLVM-NEXT: } +# STRTAB-LINK-ERR-LLVM-NEXT: ] + +# STRTAB-LINK-ERR-GNU: warning: '[[FILE]]': unable to get the string table for the SHT_SYMTAB section: invalid section index: 255 +# STRTAB-LINK-ERR-GNU: Symbol table '.symtab' contains 2 entries: +# STRTAB-LINK-ERR-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name +# STRTAB-LINK-ERR-GNU-NEXT: warning: '[[FILE]]': st_name (0x0) is past the end of the string table of size 0x0 +# STRTAB-LINK-ERR-GNU-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# STRTAB-LINK-ERR-GNU-NEXT: warning: '[[FILE]]': st_name (0x1) is past the end of the string table of size 0x0 +# STRTAB-LINK-ERR-GNU-NEXT: 1: 0000000000000001 0 NOTYPE GLOBAL DEFAULT 1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SHStrNdx: [[SHSTRTAB=2]] +Sections: + - Name: .symtab + Type: SHT_SYMTAB + Link: [[LINK=.strtab]] + EntSize: [[ENTSIZE=0x18]] +## Define the .shstrtab section to reveal its position. + - Name: .shstrtab + Type: SHT_STRTAB +Symbols: + - Name: foo + Value: 0x1 + Binding: STB_GLOBAL + Index: 1 + +## Case 2: check we report a warning when we are unable to read symbols +## from the the SHT_SYMTAB section. +# RUN: yaml2obj --docnum=2 -DENTSIZE=0xFF %s -o %t64.err2 +# RUN: llvm-readobj --symbols %t64.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err2 --check-prefix=SYMTAB-ENTSIZE-ERR-LLVM +# RUN: llvm-readelf --symbols %t64.err2 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err2 --check-prefix=SYMTAB-ENTSIZE-ERR-GNU + +# SYMTAB-ENTSIZE-ERR-LLVM: Symbols [ +# SYMTAB-ENTSIZE-ERR-LLVM-NEXT: warning: '[[FILE]]': unable to read symbols from the SHT_SYMTAB section: section [index 1] has an invalid sh_entsize: 255 +# SYMTAB-ENTSIZE-ERR-LLVM: ] + +# SYMTAB-ENTSIZE-ERR-GNU: warning: '[[FILE]]': unable to read symbols from the SHT_SYMTAB section: section [index 1] has an invalid sh_entsize: 255 +# SYMTAB-ENTSIZE-ERR-GNU-NOT: {{.}} + +## Case 3: check we report a warning, but continue dumping, when we are unable to read the name of the SHT_SYMTAB section. +## In this case we set the e_shstrndx field to an invalid index so that the .shstrtab section can't be located. +# RUN: yaml2obj --docnum=2 -DSHSTRTAB=0xff %s -o %t64.err3 +# RUN: llvm-readobj --symbols %t64.err3 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err3 --check-prefix=SYMTAB-SHSTRTAB-ERR-LLVM +# RUN: llvm-readelf --symbols %t64.err3 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t64.err3 --check-prefix=SYMTAB-SHSTRTAB-ERR-GNU + +# SYMTAB-SHSTRTAB-ERR-LLVM: Symbols [ +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: warning: '[[FILE]]': unable to get the name of the SHT_SYMTAB section: section header string table index 255 does not exist +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Symbol { +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Name: (0) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Value: 0x0 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Size: 0 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Binding: Local (0x0) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Type: None (0x0) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Other: 0 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Section: Undefined (0x0) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: } +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Symbol { +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Name: foo (1) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Value: 0x1 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Size: 0 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Binding: Global (0x1) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Type: None (0x0) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Other: 0 +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: warning: '[[FILE]]': section header string table index 255 does not exist +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: Section: (0x1) +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: } +# SYMTAB-SHSTRTAB-ERR-LLVM-NEXT: ] + +# SYMTAB-SHSTRTAB-ERR-GNU: warning: '[[FILE]]': unable to get the name of the SHT_SYMTAB section: section header string table index 255 does not exist +# SYMTAB-SHSTRTAB-ERR-GNU: Symbol table '' contains 2 entries: +# SYMTAB-SHSTRTAB-ERR-GNU-NEXT: Num: Value Size Type Bind Vis Ndx Name +# SYMTAB-SHSTRTAB-ERR-GNU-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# SYMTAB-SHSTRTAB-ERR-GNU-NEXT: 1: 0000000000000001 0 NOTYPE GLOBAL DEFAULT 1 foo diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 0fbaf7d..342677a 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -682,11 +682,32 @@ void ELFDumper::printSymbolsHelper(bool IsDynamic) const { } else { if (!DotSymtabSec) return; - StrTable = unwrapOrError(ObjF->getFileName(), - Obj->getStringTableForSymtab(*DotSymtabSec)); - Syms = unwrapOrError(ObjF->getFileName(), Obj->symbols(DotSymtabSec)); - SymtabName = - unwrapOrError(ObjF->getFileName(), Obj->getSectionName(DotSymtabSec)); + + if (Expected StrTableOrErr = + Obj->getStringTableForSymtab(*DotSymtabSec)) + StrTable = *StrTableOrErr; + else + reportUniqueWarning(createError( + "unable to get the string table for the SHT_SYMTAB section: " + + toString(StrTableOrErr.takeError()))); + + if (Expected SymsOrErr = Obj->symbols(DotSymtabSec)) + Syms = *SymsOrErr; + else + reportUniqueWarning( + createError("unable to read symbols from the SHT_SYMTAB section: " + + toString(SymsOrErr.takeError()))); + + if (Expected SymtabNameOrErr = + Obj->getSectionName(DotSymtabSec)) { + SymtabName = *SymtabNameOrErr; + } else { + reportUniqueWarning( + createError("unable to get the name of the SHT_SYMTAB section: " + + toString(SymtabNameOrErr.takeError()))); + SymtabName = ""; + } + Entries = DotSymtabSec->getEntityCount(); } if (Syms.begin() == Syms.end()) @@ -1156,8 +1177,13 @@ template std::string ELFDumper::getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic) const { - std::string SymbolName = maybeDemangle( - unwrapOrError(ObjF->getFileName(), Symbol->getName(StrTable))); + std::string SymbolName; + if (Expected NameOrErr = Symbol->getName(StrTable)) { + SymbolName = maybeDemangle(*NameOrErr); + } else { + reportUniqueWarning(NameOrErr.takeError()); + return ""; + } if (SymbolName.empty() && Symbol->getType() == ELF::STT_SECTION) { Elf_Sym_Range Syms = unwrapOrError( -- 2.7.4