From d37a9dfc0b1c99a3394416399f626b4739a7f211 Mon Sep 17 00:00:00 2001
From: "Michael J. Spencer" <bigcheesegs@gmail.com>
Date: Fri, 10 Jul 2015 20:11:57 +0000
Subject: [PATCH] [Object][ELF] Handle the dynamic string table in files
 without a section table.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241937 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/llvm/Object/ELF.h         | 20 +++++++++++++++-----
 test/Object/no-section-table.test | 30 +++++++++++++++++++++++++++++-
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 0fad59205cf..2f4b38b09e3 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -176,7 +176,6 @@ private:
   StringRef DotShstrtab;                    // Section header string table.
   StringRef DotStrtab;                      // Symbol header string table.
   const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section.
-  StringRef DynSymStrTab;                   // Dynnamic symbol string table.
   const Elf_Shdr *DotDynSymSec = nullptr;   // Dynamic symbol table section.
   const Elf_Hash *HashTable = nullptr;
 
@@ -200,6 +199,7 @@ private:
 
   DynRegionInfo DynamicRegion;
   DynRegionInfo DynHashRegion;
+  DynRegionInfo DynStrRegion;
   DynRegionInfo DynRelaRegion;
 
   // Pointer to SONAME entry in dynamic string table
@@ -655,7 +655,9 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC)
       ErrorOr<StringRef> SymtabOrErr = getStringTable(*SectionOrErr);
       if ((EC = SymtabOrErr.getError()))
         return;
-      DynSymStrTab = *SymtabOrErr;
+      DynStrRegion.Addr = SymtabOrErr->data();
+      DynStrRegion.Size = SymtabOrErr->size();
+      DynStrRegion.EntSize = 1;
       break;
     }
     case ELF::SHT_DYNAMIC:
@@ -764,6 +766,14 @@ void ELFFile<ELFT>::scanDynamicTable() {
       HashTable =
           reinterpret_cast<const Elf_Hash *>(toMappedAddr(DynI->getPtr()));
       break;
+    case ELF::DT_STRTAB:
+      if (!DynStrRegion.Addr)
+        DynStrRegion.Addr = toMappedAddr(DynI->getPtr());
+      break;
+    case ELF::DT_STRSZ:
+      if (!DynStrRegion.Size)
+        DynStrRegion.Size = DynI->getVal();
+      break;
     case ELF::DT_RELA:
       if (!DynRelaRegion.Addr)
         DynRelaRegion.Addr = toMappedAddr(DynI->getPtr());
@@ -897,9 +907,9 @@ ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
 
 template <class ELFT>
 const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const {
-  if (!DotDynSymSec || Offset >= DynSymStrTab.size())
+  if (Offset >= DynStrRegion.Size)
     return nullptr;
-  return (const char *)DynSymStrTab.begin() + Offset;
+  return (const char *)DynStrRegion.Addr + Offset;
 }
 
 template <class ELFT>
@@ -1012,7 +1022,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section,
     IsDefault = false;
   }
 
-  if (name_offset >= DynSymStrTab.size())
+  if (name_offset >= DynStrRegion.Size)
     return object_error::parse_failed;
   return StringRef(getDynamicString(name_offset));
 }
diff --git a/test/Object/no-section-table.test b/test/Object/no-section-table.test
index 1049390ce85..77fb98a4d40 100644
--- a/test/Object/no-section-table.test
+++ b/test/Object/no-section-table.test
@@ -1,5 +1,33 @@
-RUN: llvm-readobj %p/Inputs/no-section-table.so -hash-table | FileCheck %s
+RUN: llvm-readobj %p/Inputs/no-section-table.so -hash-table -dynamic-table \
+RUN:   | FileCheck %s
 
+CHECK: DynamicSection [ (24 entries)
+CHECK:   Tag                Type                 Name/Value
+CHECK:   0x0000000000000001 NEEDED               SharedLibrary (libc.so.6)
+CHECK:   0x000000000000000C INIT                 0x4B8
+CHECK:   0x000000000000000D FINI                 0x618
+CHECK:   0x0000000000000019 INIT_ARRAY           0x2006C0
+CHECK:   0x000000000000001B INIT_ARRAYSZ         8 (bytes)
+CHECK:   0x000000000000001A FINI_ARRAY           0x2006C8
+CHECK:   0x000000000000001C FINI_ARRAYSZ         8 (bytes)
+CHECK:   0x0000000000000004 HASH                 0x158
+CHECK:   0x0000000000000005 STRTAB               0x2D8
+CHECK:   0x0000000000000006 SYMTAB               0x1A0
+CHECK:   0x000000000000000A STRSZ                179 (bytes)
+CHECK:   0x000000000000000B SYMENT               24 (bytes)
+CHECK:   0x0000000000000003 PLTGOT               0x2008C0
+CHECK:   0x0000000000000002 PLTRELSZ             48 (bytes)
+CHECK:   0x0000000000000014 PLTREL               RELA
+CHECK:   0x0000000000000017 JMPREL               0x488
+CHECK:   0x0000000000000007 RELA                 0x3C8
+CHECK:   0x0000000000000008 RELASZ               192 (bytes)
+CHECK:   0x0000000000000009 RELAENT              24 (bytes)
+CHECK:   0x000000006FFFFFFE VERNEED              0x3A8
+CHECK:   0x000000006FFFFFFF VERNEEDNUM           1
+CHECK:   0x000000006FFFFFF0 VERSYM               0x38C
+CHECK:   0x000000006FFFFFF9 unknown              0x3
+CHECK:   0x0000000000000000 NULL                 0x0
+CHECK: ]
 CHECK: HashTable {
 CHECK:   Num Buckets: 3
 CHECK:   Num Chains: 13