[llvm] 7fc599c - [llvm-readobj] - Introduce warnings for cases when unable to read strings from string tables.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 7 04:41:08 PDT 2020


Author: Georgii Rymar
Date: 2020-04-07T14:40:32+03:00
New Revision: 7fc599ceb015c6456e48b79453df9ac1b2965123

URL: https://github.com/llvm/llvm-project/commit/7fc599ceb015c6456e48b79453df9ac1b2965123
DIFF: https://github.com/llvm/llvm-project/commit/7fc599ceb015c6456e48b79453df9ac1b2965123.diff

LOG: [llvm-readobj] - Introduce warnings for cases when unable to read strings from string tables.

Currently we have no dedicated warnings, but we return error message instead of a result.
It is generally not consistent with another warnings we have.

This change was suggested and discussed here:
https://reviews.llvm.org/D77216#1954873

This change refines error messages we report and also I had to update the API
to implement it.

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

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
    llvm/test/tools/llvm-readobj/ELF/loadname.test
    llvm/test/tools/llvm-readobj/ELF/needed-libs.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
index 7e1a43c36ad9..7b941bfd685d 100644
--- a/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
+++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
@@ -90,26 +90,54 @@ ProgramHeaders:
 
 ## Test handling of string references pointing past the end of the dynamic string table.
 # RUN: yaml2obj %s --docnum=3 -o %t.bad-string
-# RUN: llvm-readobj --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-LLVM
-# RUN: llvm-readelf --dynamic-table %t.bad-string | FileCheck %s --check-prefix BAD-STRING-GNU
-
-# BAD-STRING-LLVM: 0x000000000000000A STRSZ         1 (bytes)
-# BAD-STRING-LLVM: 0x0000000000000001 NEEDED        Shared library: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000007FFFFFFF FILTER        Filter library: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000007FFFFFFD AUXILIARY     Auxiliary library: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000007FFFFFFE USED          Not needed object: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000000000000E SONAME        Library soname: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000000000000F RPATH         Library rpath: [<Invalid offset 0x1>]
-# BAD-STRING-LLVM: 0x000000000000001D RUNPATH       Library runpath: [<Invalid offset 0x1>]
-
-# BAD-STRING-GNU:  0x000000000000000a (STRSZ)       1 (bytes)
-# BAD-STRING-GNU:  0x0000000000000001 (NEEDED)      Shared library: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000007fffffff (FILTER)      Filter library: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000007ffffffd (AUXILIARY)   Auxiliary library: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000007ffffffe (USED)        Not needed object: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000000000000e (SONAME)      Library soname: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000000000000f (RPATH)       Library rpath: [<Invalid offset 0x1>]
-# BAD-STRING-GNU:  0x000000000000001d (RUNPATH)     Library runpath: [<Invalid offset 0x1>]
+# RUN: llvm-readobj --dynamic-table %t.bad-string 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix BAD-STRING-LLVM -DFILE=%t.bad-string
+# RUN: llvm-readelf --dynamic-table %t.bad-string 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix BAD-STRING-GNU -DFILE=%t.bad-string
+
+# BAD-STRING-LLVM:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM:      LoadName: <?>
+# BAD-STRING-LLVM:      DynamicSection [ (10 entries)
+# BAD-STRING-LLVM-NEXT:   Tag                Type      Name/Value
+# BAD-STRING-LLVM-NEXT:   0x0000000000000005 STRTAB    0x1000
+# BAD-STRING-LLVM-NEXT:   0x000000000000000A STRSZ     1 (bytes)
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x0000000000000001 NEEDED    Shared library: [<?>]
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFF FILTER    Filter library: [<?>]
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFD AUXILIARY Auxiliary library: [<?>]
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x000000007FFFFFFE USED      Not needed object: [<?>]
+## Note: there is no "string table at offset 0xb0..." warning here, because it was printed earlier.
+# BAD-STRING-LLVM-NEXT:   0x000000000000000E SONAME    Library soname: [<?>]
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x000000000000000F RPATH     Library rpath: [<?>]
+# BAD-STRING-LLVM-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
+# BAD-STRING-LLVM-NEXT:   0x000000000000001D RUNPATH   Library runpath: [<?>]
+# BAD-STRING-LLVM-NEXT:   0x0000000000000000 NULL      0x0
+# BAD-STRING-LLVM-NEXT: ]
+
+# BAD-STRING-GNU:      warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb6, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT: Dynamic section at offset 0xb1 contains 10 entries:
+# BAD-STRING-GNU-NEXT:   Tag                Type        Name/Value
+# BAD-STRING-GNU-NEXT:   0x0000000000000005 (STRTAB)    0x1000
+# BAD-STRING-GNU-NEXT:   0x000000000000000a (STRSZ)     1 (bytes)
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb2, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x0000000000000001 (NEEDED)    Shared library: [<?>]
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb3, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x000000007fffffff (FILTER)    Filter library: [<?>]
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb4, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x000000007ffffffd (AUXILIARY) Auxiliary library: [<?>]
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb5, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x000000007ffffffe (USED)      Not needed object: [<?>]
+## Note: there is no "string table at offset 0xb6..." warning here, because it was printed earlier.
+# BAD-STRING-GNU-NEXT:   0x000000000000000e (SONAME)    Library soname: [<?>]
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb7, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x000000000000000f (RPATH)     Library rpath: [<?>]
+# BAD-STRING-GNU-NEXT: warning: '[[FILE]]': string table at offset 0xb0: unable to read the string at 0xb8, it goes past the end of the table (0xb1)
+# BAD-STRING-GNU-NEXT:   0x000000000000001d (RUNPATH)   Library runpath: [<?>]
+# BAD-STRING-GNU-NEXT:   0x0000000000000000 (NULL)      0x0
 
 --- !ELF
 FileHeader:
@@ -130,19 +158,19 @@ Sections:
       - Tag:   DT_STRSZ
         Value: 1
       - Tag:   DT_NEEDED
-        Value: 1
+        Value: 2
       - Tag:   DT_FILTER
-        Value: 1
+        Value: 3
       - Tag:   DT_AUXILIARY
-        Value: 1
+        Value: 4
       - Tag:   DT_USED
-        Value: 1
+        Value: 5
       - Tag:   DT_SONAME
-        Value: 1
+        Value: 6
       - Tag:   DT_RPATH
-        Value: 1
+        Value: 7
       - Tag:   DT_RUNPATH
-        Value: 1
+        Value: 8
       - Tag:   DT_NULL
         Value: 0
 Symbols: []
@@ -160,17 +188,23 @@ ProgramHeaders:
 ## Test handling of DT_STRTAB pointing outside the file's address space.
 # RUN: yaml2obj %s --docnum=4 -o %t.bad-strtab
 
-# RUN: llvm-readobj --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
-# RUN: llvm-readelf --dynamic-table %t.bad-strtab 2>&1 >/dev/null | FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
+# RUN: llvm-readobj --dynamic-table %t.bad-strtab 2>&1 >/dev/null | \
+# RUN:   FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
+# RUN: llvm-readelf --dynamic-table %t.bad-strtab 2>&1 >/dev/null | \
+# RUN:   FileCheck -DFILE=%t.bad-strtab %s --check-prefix BAD-STRTAB-ERR
 # BAD-STRTAB-ERR: warning: '[[FILE]]': Unable to parse DT_STRTAB: virtual address is not in any segment: 0x2000000
+# BAD-STRTAB-ERR: warning: '[[FILE]]': string table was not found
+
+# RUN: llvm-readobj --dynamic-table --needed-libs %t.bad-strtab 2>&1 | \
+# RUN:   FileCheck -DFILE=%t.bad-strtab %s --check-prefixes=BAD-STRTAB-ERR,BAD-STRTAB,BAD-STRTAB-LLVM
+# RUN: llvm-readelf --dynamic-table --needed-libs %t.bad-strtab 2>&1 | \
+# RUN:   FileCheck -DFILE=%t.bad-strtab %s --check-prefixes=BAD-STRTAB-ERR,BAD-STRTAB,BAD-STRTAB-GNU
 
-# RUN: llvm-readobj --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-LLVM
-# RUN: llvm-readelf --dynamic-table --needed-libs %t.bad-strtab | FileCheck %s --check-prefixes=BAD-STRTAB,BAD-STRTAB-GNU
-# BAD-STRTAB-LLVM: LoadName: <String table is empty or was not found>
-# BAD-STRTAB-LLVM: 0x0000000000000001  NEEDED   Shared library: [<String table is empty or was not found>]
-# BAD-STRTAB-GNU:  0x0000000000000001 (NEEDED)  Shared library: [<String table is empty or was not found>]
+# BAD-STRTAB-LLVM: LoadName: <?>
+# BAD-STRTAB-LLVM: 0x0000000000000001  NEEDED   Shared library: [<?>]
+# BAD-STRTAB-GNU:  0x0000000000000001 (NEEDED)  Shared library: [<?>]
 # BAD-STRTAB:      NeededLibraries [
-# BAD-STRTAB:        <String table is empty or was not found>
+# BAD-STRTAB:        <?>
 # BAD-STRTAB:      ]
 
 --- !ELF

diff  --git a/llvm/test/tools/llvm-readobj/ELF/loadname.test b/llvm/test/tools/llvm-readobj/ELF/loadname.test
index a8eaab4b8ad7..aba3a5ba2af1 100644
--- a/llvm/test/tools/llvm-readobj/ELF/loadname.test
+++ b/llvm/test/tools/llvm-readobj/ELF/loadname.test
@@ -61,5 +61,6 @@ ProgramHeaders:
 # RUN: llvm-readelf --dynamic-table %t.err.1.o 2>&1 | FileCheck %s -DFILE=%t.err.1.o --check-prefixes=BROKEN-OFFSET,BROKEN-OFFSET-GNU
 
 # BROKEN-OFFSET:      warning: '[[FILE]]': Unable to parse DT_STRTAB: can't map virtual address 0xfffe to the segment with index 1: the segment ends at 0x10077, which is greater than the file size (0x228)
-# BROKEN-OFFSET-LLVM: LoadName: <String table is empty or was not found>
-# BROKEN-OFFSET-GNU:  0x000000000000000e (SONAME) Library soname: [<String table is empty or was not found>]
+# BROKEN-OFFSET:      warning: '[[FILE]]': string table was not found
+# BROKEN-OFFSET-LLVM: LoadName: <?>
+# BROKEN-OFFSET-GNU:  0x000000000000000e (SONAME) Library soname: [<?>]

diff  --git a/llvm/test/tools/llvm-readobj/ELF/needed-libs.test b/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
index 3be99cade5dc..536a54b51117 100644
--- a/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
+++ b/llvm/test/tools/llvm-readobj/ELF/needed-libs.test
@@ -1,21 +1,23 @@
 ## In this test we check the --needed-libs option.
 
 # RUN: yaml2obj %s --docnum=1 -o %t1
-# RUN: llvm-readobj --needed-libs %t1 \
-# RUN:   | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=NEEDED-LIBS
-# RUN: llvm-readelf --needed-libs %t1 \
-# RUN:   | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=NEEDED-LIBS
+# RUN: llvm-readobj --needed-libs %t1 2>&1 \
+# RUN:   | FileCheck %s -DFILE=%t1 --implicit-check-not=warning: --strict-whitespace --check-prefix=NEEDED-LIBS
+# RUN: llvm-readelf --needed-libs %t1 2>&1 \
+# RUN:   | FileCheck %s -DFILE=%t1 --implicit-check-not=warning: --strict-whitespace --check-prefix=NEEDED-LIBS
 
 ## Check that library names are sorted when printed.
 ## Document that we also sort error entries.
 
-#      NEEDED-LIBS:NeededLibraries [
-# NEEDED-LIBS-NEXT:  <Invalid offset 0x1111111>
-# NEEDED-LIBS-NEXT:  <Invalid offset 0x9999999>
-# NEEDED-LIBS-NEXT:  aaa
-# NEEDED-LIBS-NEXT:  bbb
-# NEEDED-LIBS-NEXT:  ccc
-# NEEDED-LIBS-NEXT:]
+#      NEEDED-LIBS:{{^}}NeededLibraries [{{$}}
+# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x9999a11, it goes past the end of the table (0x85){{$}}
+# NEEDED-LIBS-NEXT:  warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x1111189, it goes past the end of the table (0x85){{$}}
+# NEEDED-LIBS-NEXT:{{^}}  <?>{{$}}
+# NEEDED-LIBS-NEXT:{{^}}  <?>{{$}}
+# NEEDED-LIBS-NEXT:{{^}}  aaa{{$}}
+# NEEDED-LIBS-NEXT:{{^}}  bbb{{$}}
+# NEEDED-LIBS-NEXT:{{^}}  ccc{{$}}
+# NEEDED-LIBS-NEXT:{{^}}]{{$}}
 
 --- !ELF
 FileHeader:
@@ -56,11 +58,18 @@ ProgramHeaders:
 
 ## Check what we print when the dynamic string table is empty.
 # RUN: yaml2obj %s --docnum=2 -o %t2
-# RUN: llvm-readobj --needed-libs %t2 | FileCheck %s --check-prefix=EMPTY-DYNSTR
-# RUN: llvm-readelf --needed-libs %t2 | FileCheck %s --check-prefix=EMPTY-DYNSTR
+# RUN: llvm-readobj --needed-libs %t2 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t2 --implicit-check-not=warning: --check-prefixes=EMPTY-DYNSTR,EMPTY-DYNSTR-LLVM
+# RUN: llvm-readelf --needed-libs %t2 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t2 --implicit-check-not=warning: --check-prefix=EMPTY-DYNSTR
 
+# EMPTY-DYNSTR:      warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x78, it goes past the end of the table (0x78)
+# EMPTY-DYNSTR-LLVM: LoadName: <?>
 # EMPTY-DYNSTR:      NeededLibraries [
-# EMPTY-DYNSTR-NEXT:   <String table is empty or was not found>
+# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x79, it goes past the end of the table (0x78)
+# EMPTY-DYNSTR-NEXT: warning: '[[FILE]]': string table at offset 0x78: unable to read the string at 0x7a, it goes past the end of the table (0x78)
+# EMPTY-DYNSTR-NEXT:   <?>
+# EMPTY-DYNSTR-NEXT:   <?>
 # EMPTY-DYNSTR-NEXT: ]
 
 --- !ELF
@@ -82,6 +91,8 @@ Sections:
         Value: 0x0000000000000000
       - Tag:   DT_NEEDED
         Value: 1
+      - Tag:   DT_NEEDED
+        Value: 2
       - Tag:   DT_STRSZ
         Value: 0x0
       - Tag:   DT_NULL

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index ca05f99aa715..fcbfbbb351db 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -288,7 +288,7 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
   Optional<DynRegionInfo> DynSymRegion;
   DynRegionInfo DynamicTable;
   StringRef DynamicStringTable;
-  std::string SOName = "<Not found>";
+  StringRef SOName = "<Not found>";
   const Elf_Hash *HashTable = nullptr;
   const Elf_GnuHash *GnuHashTable = nullptr;
   const Elf_Shdr *DotSymtabSec = nullptr;
@@ -341,12 +341,12 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
   Expected<StringRef> getSymbolSectionName(const Elf_Sym *Symbol,
                                            unsigned SectionIndex) const;
   Expected<std::string> getStaticSymbolName(uint32_t Index) const;
-  std::string getDynamicString(uint64_t Value) const;
+  StringRef getDynamicString(uint64_t Value) const;
   Expected<StringRef> getSymbolVersionByIndex(uint32_t VersionSymbolIndex,
                                               bool &IsDefault) const;
 
   void printSymbolsHelper(bool IsDynamic) const;
-  void printDynamicEntry(raw_ostream &OS, uint64_t Type, uint64_t Value) const;
+  std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
 
   const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
   const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; }
@@ -2387,10 +2387,24 @@ void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) {
 }
 
 template <class ELFT>
-void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
-                                        uint64_t Value) const {
-  const char *ConvChar =
-      (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
+std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
+                                             uint64_t Value) const {
+  auto FormatHexValue = [](uint64_t V) {
+    std::string Str;
+    raw_string_ostream OS(Str);
+    const char *ConvChar =
+        (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64;
+    OS << format(ConvChar, V);
+    return OS.str();
+  };
+
+  auto FormatFlags = [](uint64_t V,
+                        llvm::ArrayRef<llvm::EnumEntry<unsigned int>> Array) {
+    std::string Str;
+    raw_string_ostream OS(Str);
+    printFlags(V, Array, OS);
+    return OS.str();
+  };
 
   // Handle custom printing of architecture specific tags
   switch (ObjF->getELFFile()->getHeader()->e_machine) {
@@ -2398,8 +2412,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
     switch (Type) {
     case DT_AARCH64_BTI_PLT:
     case DT_AARCH64_PAC_PLT:
-      OS << Value;
-      return;
+      return std::to_string(Value);
     default:
       break;
     }
@@ -2407,12 +2420,10 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case EM_HEXAGON:
     switch (Type) {
     case DT_HEXAGON_VER:
-      OS << Value;
-      return;
+      return std::to_string(Value);
     case DT_HEXAGON_SYMSZ:
     case DT_HEXAGON_PLT:
-      OS << format(ConvChar, Value);
-      return;
+      return FormatHexValue(Value);
     default:
       break;
     }
@@ -2423,8 +2434,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
     case DT_MIPS_LOCAL_GOTNO:
     case DT_MIPS_SYMTABNO:
     case DT_MIPS_UNREFEXTNO:
-      OS << Value;
-      return;
+      return std::to_string(Value);
     case DT_MIPS_TIME_STAMP:
     case DT_MIPS_ICHECKSUM:
     case DT_MIPS_IVERSION:
@@ -2465,11 +2475,9 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
     case DT_MIPS_PLTGOT:
     case DT_MIPS_RWPLT:
     case DT_MIPS_RLD_MAP_REL:
-      OS << format(ConvChar, Value);
-      return;
+      return FormatHexValue(Value);
     case DT_MIPS_FLAGS:
-      printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS);
-      return;
+      return FormatFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags));
     default:
       break;
     }
@@ -2480,13 +2488,10 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
 
   switch (Type) {
   case DT_PLTREL:
-    if (Value == DT_REL) {
-      OS << "REL";
-      break;
-    } else if (Value == DT_RELA) {
-      OS << "RELA";
-      break;
-    }
+    if (Value == DT_REL)
+      return "REL";
+    if (Value == DT_RELA)
+      return "RELA";
     LLVM_FALLTHROUGH;
   case DT_PLTGOT:
   case DT_HASH:
@@ -2506,14 +2511,12 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case DT_VERSYM:
   case DT_GNU_HASH:
   case DT_NULL:
-    OS << format(ConvChar, Value);
-    break;
+    return FormatHexValue(Value);
   case DT_RELACOUNT:
   case DT_RELCOUNT:
   case DT_VERDEFNUM:
   case DT_VERNEEDNUM:
-    OS << Value;
-    break;
+    return std::to_string(Value);
   case DT_PLTRELSZ:
   case DT_RELASZ:
   case DT_RELAENT:
@@ -2526,8 +2529,7 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case DT_PREINIT_ARRAYSZ:
   case DT_ANDROID_RELSZ:
   case DT_ANDROID_RELASZ:
-    OS << Value << " (bytes)";
-    break;
+    return std::to_string(Value) + " (bytes)";
   case DT_NEEDED:
   case DT_SONAME:
   case DT_AUXILIARY:
@@ -2535,37 +2537,45 @@ void ELFDumper<ELFT>::printDynamicEntry(raw_ostream &OS, uint64_t Type,
   case DT_FILTER:
   case DT_RPATH:
   case DT_RUNPATH: {
-    const std::map<uint64_t, const char*> TagNames = {
-      {DT_NEEDED,    "Shared library"},
-      {DT_SONAME,    "Library soname"},
-      {DT_AUXILIARY, "Auxiliary library"},
-      {DT_USED,      "Not needed object"},
-      {DT_FILTER,    "Filter library"},
-      {DT_RPATH,     "Library rpath"},
-      {DT_RUNPATH,   "Library runpath"},
+    const std::map<uint64_t, const char *> TagNames = {
+        {DT_NEEDED, "Shared library"},       {DT_SONAME, "Library soname"},
+        {DT_AUXILIARY, "Auxiliary library"}, {DT_USED, "Not needed object"},
+        {DT_FILTER, "Filter library"},       {DT_RPATH, "Library rpath"},
+        {DT_RUNPATH, "Library runpath"},
     };
-    OS << TagNames.at(Type) << ": [" << getDynamicString(Value) << "]";
-    break;
+
+    return (Twine(TagNames.at(Type)) + ": [" + getDynamicString(Value) + "]")
+        .str();
   }
   case DT_FLAGS:
-    printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
-    break;
+    return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags));
   case DT_FLAGS_1:
-    printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
-    break;
+    return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags1));
   default:
-    OS << format(ConvChar, Value);
-    break;
+    return FormatHexValue(Value);
   }
 }
 
 template <class ELFT>
-std::string ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
-  if (DynamicStringTable.empty())
-    return "<String table is empty or was not found>";
+StringRef ELFDumper<ELFT>::getDynamicString(uint64_t Value) const {
+  auto WarnAndReturn = [this](const Twine &Msg) {
+    reportUniqueWarning(createError(Msg));
+    return "<?>";
+  };
+
+  if (DynamicStringTable.empty() && !DynamicStringTable.data())
+    return WarnAndReturn("string table was not found");
+
   if (Value < DynamicStringTable.size())
     return DynamicStringTable.data() + Value;
-  return Twine("<Invalid offset 0x" + utohexstr(Value) + ">").str();
+
+  const uint64_t Offset =
+      (const uint8_t *)DynamicStringTable.data() - ObjF->getELFFile()->base();
+  return WarnAndReturn(
+      "string table at offset 0x" + Twine::utohexstr(Offset) +
+      ": unable to read the string at 0x" + Twine::utohexstr(Offset + Value) +
+      ", it goes past the end of the table (0x" +
+      Twine::utohexstr(Offset + DynamicStringTable.size()) + ")");
 }
 
 template <class ELFT> void ELFDumper<ELFT>::printUnwindInfo() {
@@ -2596,14 +2606,14 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicTable() {
 template <class ELFT> void ELFDumper<ELFT>::printNeededLibraries() {
   ListScope D(W, "NeededLibraries");
 
-  std::vector<std::string> Libs;
+  std::vector<StringRef> Libs;
   for (const auto &Entry : dynamic_table())
     if (Entry.d_tag == ELF::DT_NEEDED)
       Libs.push_back(getDynamicString(Entry.d_un.d_val));
 
   llvm::sort(Libs);
 
-  for (const std::string &L : Libs)
+  for (StringRef L : Libs)
     W.startLine() << L << "\n";
 }
 
@@ -4235,12 +4245,11 @@ template <class ELFT> void GNUStyle<ELFT>::printDynamic(const ELFO *Obj) {
   std::string ValueFmt = " %-" + std::to_string(MaxTagSize) + "s ";
   for (auto Entry : Table) {
     uintX_t Tag = Entry.getTag();
-    std::string TypeString =
+    std::string Type =
         std::string("(") + Obj->getDynamicTagAsString(Tag).c_str() + ")";
+    std::string Value = this->dumper()->getDynamicEntry(Tag, Entry.getVal());
     OS << "  " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10)
-       << format(ValueFmt.c_str(), TypeString.c_str());
-    this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
-    OS << "\n";
+       << format(ValueFmt.c_str(), Type.c_str()) << Value << "\n";
   }
 }
 
@@ -6051,7 +6060,6 @@ template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Ob
   if (Table.empty())
     return;
 
-  raw_ostream &OS = W.getOStream();
   W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n";
 
   size_t MaxTagSize = getMaxDynamicTagSize(Obj, Table);
@@ -6064,12 +6072,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printDynamic(const ELFFile<ELFT> *Ob
   std::string ValueFmt = "%-" + std::to_string(MaxTagSize) + "s ";
   for (auto Entry : Table) {
     uintX_t Tag = Entry.getTag();
+    std::string Value = this->dumper()->getDynamicEntry(Tag, Entry.getVal());
     W.startLine() << "  " << format_hex(Tag, ELFT::Is64Bits ? 18 : 10, true)
                   << " "
                   << format(ValueFmt.c_str(),
-                            Obj->getDynamicTagAsString(Tag).c_str());
-    this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal());
-    OS << "\n";
+                            Obj->getDynamicTagAsString(Tag).c_str())
+                  << Value << "\n";
   }
   W.startLine() << "]\n";
 }


        


More information about the llvm-commits mailing list