[llvm-readelf] - Do not error out when dumping symbols.
authorGeorgii Rymar <grimar@accesssoftek.com>
Wed, 1 Jul 2020 12:25:33 +0000 (15:25 +0300)
committerGeorgii Rymar <grimar@accesssoftek.com>
Fri, 3 Jul 2020 08:55:35 +0000 (11:55 +0300)
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
llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
llvm/test/tools/llvm-readobj/ELF/symbols.test
llvm/tools/llvm-readobj/ELFDumper.cpp

index a7363ab..3a7ddab 100644 (file)
@@ -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:
index 817d52f..c4ac2f8 100644 (file)
@@ -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:
index ef45b71..da42569 100644 (file)
@@ -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
index 0fbaf7d..342677a 100644 (file)
@@ -682,11 +682,32 @@ void ELFDumper<ELFT>::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<StringRef> 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<Elf_Sym_Range> SymsOrErr = Obj->symbols(DotSymtabSec))
+      Syms = *SymsOrErr;
+    else
+      reportUniqueWarning(
+          createError("unable to read symbols from the SHT_SYMTAB section: " +
+                      toString(SymsOrErr.takeError())));
+
+    if (Expected<StringRef> 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 <typename ELFT>
 std::string ELFDumper<ELFT>::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<StringRef> 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(