[llvm] r260488 - [readobj] Handle ELF files with no section table or with no program headers.

Michael J. Spencer via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 10 20:59:46 PST 2016


Author: mspencer
Date: Wed Feb 10 22:59:45 2016
New Revision: 260488

URL: http://llvm.org/viewvc/llvm-project?rev=260488&view=rev
Log:
[readobj] Handle ELF files with no section table or with no program headers.

This adds support for finding the dynamic table and dynamic symbol table via
the section table or the program header table. If there's no section table an
attempt is made to figure out the length of the dynamic symbol table.

Added:
    llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86
    llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86
    llvm/trunk/test/tools/llvm-readobj/dynamic-symbols.test
Removed:
    llvm/trunk/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64
Modified:
    llvm/trunk/include/llvm/Object/ELF.h
    llvm/trunk/test/Object/corrupt.test
    llvm/trunk/test/Object/invalid.test
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
    llvm/trunk/tools/llvm-readobj/llvm-readobj.h

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=260488&r1=260487&r2=260488&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Wed Feb 10 22:59:45 2016
@@ -62,6 +62,8 @@ public:
     return reinterpret_cast<const uint8_t *>(Buf.data());
   }
 
+  size_t getBufSize() const { return Buf.size(); }
+
 private:
 
   StringRef Buf;
@@ -200,6 +202,9 @@ public:
   uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
                                        const Elf_Shdr *SymTab,
                                        ArrayRef<Elf_Word> ShndxTable) const;
+  uint32_t getExtendedSymbolTableIndex(const Elf_Sym *Sym,
+                                       const Elf_Sym *FirstSym,
+                                       ArrayRef<Elf_Word> ShndxTable) const;
   const Elf_Ehdr *getHeader() const { return Header; }
   ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
                                        const Elf_Shdr *SymTab,
@@ -225,8 +230,15 @@ template <class ELFT>
 uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
     const Elf_Sym *Sym, const Elf_Shdr *SymTab,
     ArrayRef<Elf_Word> ShndxTable) const {
+  return getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable);
+}
+
+template <class ELFT>
+uint32_t ELFFile<ELFT>::getExtendedSymbolTableIndex(
+    const Elf_Sym *Sym, const Elf_Sym *FirstSym,
+    ArrayRef<Elf_Word> ShndxTable) const {
   assert(Sym->st_shndx == ELF::SHN_XINDEX);
-  unsigned Index = Sym - symbol_begin(SymTab);
+  unsigned Index = Sym - FirstSym;
 
   // The size of the table was checked in getSHNDXTable.
   return ShndxTable[Index];
@@ -238,7 +250,8 @@ ELFFile<ELFT>::getSection(const Elf_Sym
                           ArrayRef<Elf_Word> ShndxTable) const {
   uint32_t Index = Sym->st_shndx;
   if (Index == ELF::SHN_XINDEX)
-    return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable));
+    return getSection(
+        getExtendedSymbolTableIndex(Sym, symbol_begin(SymTab), ShndxTable));
 
   if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
     return nullptr;

Removed: llvm/trunk/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64?rev=260487&view=auto
==============================================================================
Binary files llvm/trunk/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 (original) and llvm/trunk/test/Object/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 (removed) differ

Modified: llvm/trunk/test/Object/corrupt.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/corrupt.test?rev=260488&r1=260487&r2=260488&view=diff
==============================================================================
--- llvm/trunk/test/Object/corrupt.test (original)
+++ llvm/trunk/test/Object/corrupt.test Wed Feb 10 22:59:45 2016
@@ -38,24 +38,17 @@ RUN:   FileCheck --check-prefix=PHENTSIZ
 
 PHENTSIZE: Invalid program header size
 
-RUN: not llvm-readobj -dynamic-table \
-RUN:   %p/Inputs/corrupt-invalid-virtual-addr.elf.x86-64 2>&1 | \
-RUN:   FileCheck --check-prefix=VIRTADDR %s
-
-VIRTADDR: Virtual address is not in any segment
-
-
 RUN: not llvm-readobj -dyn-relocations \
 RUN:   %p/Inputs/corrupt-invalid-relocation-size.elf.x86-64 2>&1 | \
 RUN:   FileCheck --check-prefix=RELOC %s
 
-RELOC:  Invalid relocation entry size
+RELOC:  Invalid entity size
 
 RUN: not llvm-readobj -dyn-relocations \
 RUN:   %p/Inputs/corrupt-invalid-dynamic-table-size.elf.x86-64 2>&1 | \
 RUN:   FileCheck --check-prefix=DYN-TABLE-SIZE %s
 
-DYN-TABLE-SIZE:  Invalid dynamic table size
+DYN-TABLE-SIZE:  Invalid entity size
 
 
 RUN: not llvm-readobj -dyn-relocations \

Modified: llvm/trunk/test/Object/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/invalid.test?rev=260488&r1=260487&r2=260488&view=diff
==============================================================================
--- llvm/trunk/test/Object/invalid.test (original)
+++ llvm/trunk/test/Object/invalid.test Wed Feb 10 22:59:45 2016
@@ -35,9 +35,11 @@ SECTION-NEXT:    AddressAlignment:
 SECTION-NEXT:    EntrySize: 32
 
 RUN: not llvm-readobj -t %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-SYM-SIZE %s
-RUN: not llvm-readobj --dyn-symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-SYM-SIZE %s
 INVALID-SYM-SIZE: Invalid symbol size
 
+RUN: not llvm-readobj --dyn-symbols %p/Inputs/invalid-sh_entsize.elf 2>&1 | FileCheck --check-prefix=INVALID-DYNSYM-SIZE %s
+INVALID-DYNSYM-SIZE: Invalid entity size
+
 RUN: not llvm-readobj -t %p/Inputs/invalid-section-index.elf 2>&1 | FileCheck --check-prefix=INVALID-SECTION-INDEX %s
 
 INVALID-SECTION-INDEX: Invalid section index

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86?rev=260488&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 (added) and llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-phdrs.x86 Wed Feb 10 22:59:45 2016 differ

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86?rev=260488&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 (added) and llvm/trunk/test/tools/llvm-readobj/Inputs/dynamic-table-exe-no-shdrs.x86 Wed Feb 10 22:59:45 2016 differ

Added: llvm/trunk/test/tools/llvm-readobj/dynamic-symbols.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/dynamic-symbols.test?rev=260488&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/dynamic-symbols.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/dynamic-symbols.test Wed Feb 10 22:59:45 2016
@@ -0,0 +1,198 @@
+RUN: llvm-readobj -dyn-symbols -dynamic-table \
+RUN:   %S/Inputs/dynamic-table-exe-no-shdrs.x86 | FileCheck %s
+RUN: llvm-readobj -dyn-symbols -dynamic-table \
+RUN:   %S/Inputs/dynamic-table-exe-no-phdrs.x86 | FileCheck %s
+
+CHECK:      File:
+CHECK-NEXT: Format: ELF32-i386
+CHECK-NEXT: Arch: i386
+CHECK-NEXT: AddressSize: 32bit
+CHECK-NEXT: LoadName:
+CHECK-NEXT: DynamicSymbols [
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: @
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Local
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: __gmon_start__@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Weak
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _Jv_RegisterClasses@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Weak
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: __libc_start_main@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _ITM_deregisterTMCloneTable@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Weak
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _ITM_registerTMCloneTable@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Weak
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: puts@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: __gxx_personality_v0@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _Unwind_Resume@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: __cxa_finalize@
+CHECK-NEXT:     Value: 0x0
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Weak
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Undefined
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _end@
+CHECK-NEXT:     Value: 0x1B68
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Absolute
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _edata@
+CHECK-NEXT:     Value: 0x1B64
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Absolute
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: _IO_stdin_used@
+CHECK-NEXT:     Value: 0x93C
+CHECK-NEXT:     Size: 4
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Object
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section:
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: __bss_start@
+CHECK-NEXT:     Value: 0x1B64
+CHECK-NEXT:     Size: 0
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: None
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section: Absolute
+CHECK-NEXT:   }
+CHECK-NEXT:   Symbol {
+CHECK-NEXT:     Name: main@
+CHECK-NEXT:     Value: 0x850
+CHECK-NEXT:     Size: 81
+CHECK-NEXT:     Binding: Global
+CHECK-NEXT:     Type: Function
+CHECK-NEXT:     Other: 0
+CHECK-NEXT:     Section:
+CHECK-NEXT:   }
+CHECK-NEXT: ]
+CHECK-NEXT: DynamicSection [
+CHECK-NEXT:   Tag        Type                 Name/Value
+CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary (libstdc++.so.6)
+CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary (libgcc_s.so.1)
+CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary (libc.so.6)
+CHECK-NEXT:   0x0000000C INIT                 0x62C
+CHECK-NEXT:   0x0000000D FINI                 0x920
+CHECK-NEXT:   0x00000019 INIT_ARRAY           0x19FC
+CHECK-NEXT:   0x0000001B INIT_ARRAYSZ         4
+CHECK-NEXT:   0x0000001A FINI_ARRAY           0x1A00
+CHECK-NEXT:   0x0000001C FINI_ARRAYSZ         4
+CHECK-NEXT:   0x00000004 HASH                 0x18C
+CHECK-NEXT:   0x6FFFFEF5 GNU_HASH             0x1E4
+CHECK-NEXT:   0x00000005 STRTAB               0x328
+CHECK-NEXT:   0x00000006 SYMTAB               0x218
+CHECK-NEXT:   0x0000000A STRSZ                408
+CHECK-NEXT:   0x0000000B SYMENT               16
+CHECK-NEXT:   0x00000015 DEBUG                0x0
+CHECK-NEXT:   0x00000003 PLTGOT               0x1B30
+CHECK-NEXT:   0x00000002 PLTRELSZ             64
+CHECK-NEXT:   0x00000014 PLTREL               REL
+CHECK-NEXT:   0x00000017 JMPREL               0x5EC
+CHECK-NEXT:   0x00000011 REL                  0x564
+CHECK-NEXT:   0x00000012 RELSZ                136
+CHECK-NEXT:   0x00000013 RELENT               8
+CHECK-NEXT:   0x00000016 TEXTREL              0x0
+CHECK-NEXT:   0x0000001E FLAGS                TEXTREL
+CHECK-NEXT:   0x6FFFFFFE VERNEED              0x4E4
+CHECK-NEXT:   0x6FFFFFFF VERNEEDNUM           3
+CHECK-NEXT:   0x6FFFFFF0 VERSYM               0x4C0
+CHECK-NEXT:   0x6FFFFFFA RELCOUNT             6
+CHECK-NEXT:   0x00000000 NULL                 0x0
+CHECK-NEXT: ]

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=260488&r1=260487&r2=260488&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Wed Feb 10 22:59:45 2016
@@ -48,6 +48,28 @@ namespace {
 
 template <class ELFT> class DumpStyle;
 
+/// \brief Represents a region described by entries in the .dynamic table.
+struct DynRegionInfo {
+  DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
+  DynRegionInfo(const void *A, uint64_t S, uint64_t ES)
+      : Addr(A), Size(S), EntSize(ES) {}
+  /// \brief Address in current address space.
+  const void *Addr;
+  /// \brief Size in bytes of the region.
+  uint64_t Size;
+  /// \brief Size of each entity in the region.
+  uint64_t EntSize;
+
+  template <typename Type> iterator_range<const Type *> getAsRange() const {
+    const Type *Start = reinterpret_cast<const Type *>(Addr);
+    if (Size == 0)
+      return {Start, Start};
+    if (EntSize != sizeof(Type) || Size % EntSize)
+      reportError("Invalid entity size");
+    return {Start, Start + (Size / EntSize)};
+  }
+};
+
 template<typename ELFT>
 class ELFDumper : public ObjDumper {
 public:
@@ -82,6 +104,7 @@ private:
   typedef ELFFile<ELFT> ELFO;
   typedef typename ELFO::Elf_Shdr Elf_Shdr;
   typedef typename ELFO::Elf_Sym Elf_Sym;
+  typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range;
   typedef typename ELFO::Elf_Dyn Elf_Dyn;
   typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range;
   typedef typename ELFO::Elf_Rel Elf_Rel;
@@ -101,21 +124,25 @@ private:
   typedef typename ELFO::Elf_Verdef Elf_Verdef;
   typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
 
-  /// \brief Represents a region described by entries in the .dynamic table.
-  struct DynRegionInfo {
-    DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {}
-    /// \brief Address in current address space.
-    const void *Addr;
-    /// \brief Size in bytes of the region.
-    uintX_t Size;
-    /// \brief Size of each entity in the region.
-    uintX_t EntSize;
-  };
+  DynRegionInfo checkDRI(DynRegionInfo DRI) {
+    if (DRI.Addr < Obj->base() ||
+        (const uint8_t *)DRI.Addr + DRI.Size > Obj->base() + Obj->getBufSize())
+      error(llvm::object::object_error::parse_failed);
+    return DRI;
+  }
+
+  DynRegionInfo createDRIFrom(const Elf_Phdr *P, uintX_t EntSize) {
+    return checkDRI({Obj->base() + P->p_offset, P->p_filesz, EntSize});
+  }
+  
+  DynRegionInfo createDRIFrom(const Elf_Shdr *S) {
+    return checkDRI({Obj->base() + S->sh_offset, S->sh_size, S->sh_entsize});
+  }
 
   void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments);
 
   void printSymbolsHelper(bool IsDynamic);
-  void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
+  void printSymbol(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
                    StringRef StrTable, bool IsDynamic);
 
   void printDynamicRelocation(Elf_Rela Rel);
@@ -123,23 +150,9 @@ private:
   void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
   void printValue(uint64_t Type, uint64_t Value);
 
-  template <typename REL>
-  static const REL *dyn_rel_begin(const DynRegionInfo &region);
-  template <typename REL>
-  static const REL *dyn_rel_end(const DynRegionInfo &region);
   Elf_Rel_Range dyn_rels() const;
   Elf_Rela_Range dyn_relas() const;
   StringRef getDynamicString(uint64_t Offset) const;
-  const Elf_Dyn *dynamic_table_begin() const {
-    ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_begin(DynamicProgHeader);
-    error(Ret.getError());
-    return *Ret;
-  }
-  const Elf_Dyn *dynamic_table_end() const {
-    ErrorOr<const Elf_Dyn *> Ret = Obj->dynamic_table_end(DynamicProgHeader);
-    error(Ret.getError());
-    return *Ret;
-  }
   StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb,
                              bool &IsDefault);
   void LoadVersionMap();
@@ -147,15 +160,17 @@ private:
   void LoadVersionDefs(const Elf_Shdr *sec) const;
 
   const ELFO *Obj;
+  DynRegionInfo DynamicTable;
+
+  // Dynamic relocation info.
   DynRegionInfo DynRelRegion;
   DynRegionInfo DynRelaRegion;
-  const Elf_Phdr *DynamicProgHeader = nullptr;
+
+  DynRegionInfo DynSymRegion;
   StringRef DynamicStringTable;
-  const Elf_Sym *DynSymStart = nullptr;
   StringRef SOName;
   const Elf_Hash *HashTable = nullptr;
   const Elf_GnuHash *GnuHashTable = nullptr;
-  const Elf_Shdr *DotDynSymSec = nullptr;
   const Elf_Shdr *DotSymtabSec = nullptr;
   ArrayRef<Elf_Word> ShndxTable;
 
@@ -188,16 +203,18 @@ private:
 
 public:
   Elf_Dyn_Range dynamic_table() const {
-    ErrorOr<Elf_Dyn_Range> Ret = Obj->dynamic_table(DynamicProgHeader);
-    error(Ret.getError());
-    return *Ret;
+    return DynamicTable.getAsRange<Elf_Dyn>();
+  }
+
+  Elf_Sym_Range dynamic_symbols() const {
+    return DynSymRegion.getAsRange<Elf_Sym>();
   }
 
   std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
                                 bool IsDynamic);
-  const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; }
   const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
   ArrayRef<Elf_Word> getShndxTable() { return ShndxTable; }
+  StringRef getDynamicStringTable() const { return DynamicStringTable; }
 };
 
 template <typename ELFT> class DumpStyle {
@@ -340,7 +357,7 @@ void ELFDumper<ELFT>::LoadVersionDefs(co
 
 template <class ELFT> void ELFDumper<ELFT>::LoadVersionMap() {
   // If there is no dynamic symtab or version table, there is nothing to do.
-  if (!DynSymStart || !dot_gnu_version_sec)
+  if (!DynSymRegion.Addr || !dot_gnu_version_sec)
     return;
 
   // Has the VersionMap already been loaded?
@@ -374,18 +391,15 @@ static void printVersionSymbolSection(EL
   W.printHex("Offset", Sec->sh_offset);
   W.printNumber("Link", Sec->sh_link);
 
-  const typename ELFO::Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
   const uint8_t *P = (const uint8_t *)Obj->base() + Sec->sh_offset;
-  ErrorOr<StringRef> StrTableOrErr =
-      Obj->getStringTableForSymtab(*DynSymSec);
-  error(StrTableOrErr.getError());
+  StringRef StrTable = Dumper->getDynamicStringTable();
 
   // Same number of entries in the dynamic symbol table (DT_SYMTAB).
   ListScope Syms(W, "Symbols");
-  for (const typename ELFO::Elf_Sym &Sym : Obj->symbols(DynSymSec)) {
+  for (const typename ELFO::Elf_Sym &Sym : Dumper->dynamic_symbols()) {
     DictScope S(W, "Symbol");
     std::string FullSymbolName =
-        Dumper->getFullSymbolName(&Sym, *StrTableOrErr, true /* IsDynamic */);
+        Dumper->getFullSymbolName(&Sym, StrTable, true /* IsDynamic */);
     W.printNumber("Version", *P);
     W.printString("Name", FullSymbolName);
     P += sizeof(typename ELFO::Elf_Half);
@@ -461,7 +475,7 @@ StringRef ELFDumper<ELFT>::getSymbolVers
 
   // Determine the position in the symbol table of this entry.
   size_t entry_index = (reinterpret_cast<uintptr_t>(symb) -
-                        reinterpret_cast<uintptr_t>(DynSymStart)) /
+                        reinterpret_cast<uintptr_t>(DynSymRegion.Addr)) /
                        sizeof(Elf_Sym);
 
   // Get the corresponding version index entry
@@ -517,7 +531,7 @@ std::string ELFDumper<ELFT>::getFullSymb
 template <typename ELFO>
 static void
 getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol,
-                    const typename ELFO::Elf_Shdr *SymTab,
+                    const typename ELFO::Elf_Sym *FirstSym,
                     ArrayRef<typename ELFO::Elf_Word> ShndxTable,
                     StringRef &SectionName, unsigned &SectionIndex) {
   SectionIndex = Symbol->st_shndx;
@@ -536,7 +550,7 @@ getSectionNameIndex(const ELFO &Obj, con
   else {
     if (SectionIndex == SHN_XINDEX)
       SectionIndex =
-          Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable);
+          Obj.getExtendedSymbolTableIndex(Symbol, FirstSym, ShndxTable);
     ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex);
     error(Sec.getError());
     SectionName = errorOrDefault(Obj.getSectionName(*Sec));
@@ -990,7 +1004,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
   SmallVector<const Elf_Phdr *, 4> LoadSegments;
   for (const Elf_Phdr &Phdr : Obj->program_headers()) {
     if (Phdr.p_type == ELF::PT_DYNAMIC) {
-      DynamicProgHeader = &Phdr;
+      DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn));
       continue;
     }
     if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0)
@@ -1005,10 +1019,17 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
         reportError("Multilpe SHT_SYMTAB");
       DotSymtabSec = &Sec;
       break;
+    case ELF::SHT_DYNAMIC: {
+      if (DynamicTable.Addr == nullptr)
+        DynamicTable = createDRIFrom(&Sec);
+      const Elf_Shdr *DynStrSec = unwrapOrError(Obj->getSection(Sec.sh_link));
+      DynamicStringTable = unwrapOrError(Obj->getStringTable(DynStrSec));
+      break;
+    }
     case ELF::SHT_DYNSYM:
-      if (DotDynSymSec != nullptr)
-        reportError("Multilpe SHT_DYNSYM");
-      DotDynSymSec = &Sec;
+      // The dynamic table does not contain the size of the dynamic symbol
+      // table, so get that from the section table if present.
+      DynSymRegion = createDRIFrom(&Sec);
       break;
     case ELF::SHT_SYMTAB_SHNDX: {
       ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
@@ -1049,12 +1070,12 @@ void ELFDumper<ELFT>::parseDynamicTable(
     const Elf_Phdr *const *I = std::upper_bound(
         LoadSegments.begin(), LoadSegments.end(), VAddr, compareAddr<ELFT>);
     if (I == LoadSegments.begin())
-      report_fatal_error("Virtual address is not in any segment");
+      return nullptr;
     --I;
     const Elf_Phdr &Phdr = **I;
     uint64_t Delta = VAddr - Phdr.p_vaddr;
     if (Delta >= Phdr.p_filesz)
-      report_fatal_error("Virtual address is not in any segment");
+      return nullptr;
     return Obj->base() + Phdr.p_offset + Delta;
   };
 
@@ -1078,8 +1099,11 @@ void ELFDumper<ELFT>::parseDynamicTable(
       StringTableSize = Dyn.getVal();
       break;
     case ELF::DT_SYMTAB:
-      DynSymStart =
-          reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr()));
+      if (DynSymRegion.Addr)
+        break;
+      DynSymRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynSymRegion.EntSize = sizeof(Elf_Sym);
+      // Figure out the size once we have scanned the entire dynamic table.
       break;
     case ELF::DT_RELA:
       DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
@@ -1108,35 +1132,59 @@ void ELFDumper<ELFT>::parseDynamicTable(
     DynamicStringTable = StringRef(StringTableBegin, StringTableSize);
   if (SONameOffset)
     SOName = getDynamicString(SONameOffset);
-}
-
-template <typename ELFT>
-template <typename REL>
-const REL *ELFDumper<ELFT>::dyn_rel_begin(const DynRegionInfo &Region) {
-  if (Region.Size && Region.EntSize != sizeof(REL))
-    report_fatal_error("Invalid relocation entry size");
-  return reinterpret_cast<const REL *>(Region.Addr);
-}
-
-template <typename ELFT>
-template <typename REL>
-const REL *ELFDumper<ELFT>::dyn_rel_end(const DynRegionInfo &Region) {
-  uint64_t Size = Region.Size;
-  if (Size % sizeof(REL))
-    report_fatal_error("Invalid relocation table size");
-  return dyn_rel_begin<REL>(Region) + Size / sizeof(REL);
+  if (DynSymRegion.Addr && !DynSymRegion.Size) {
+    // There was no section table entry for the dynamic section, and there is
+    // no DT entry describing its size, so attempt to guess at its size.
+    // Initally guess that it ends at the end of the file.
+    const void *Start = DynSymRegion.Addr;
+    const void *End = Obj->base() + Obj->getBufSize();
+
+    // Check all the sections we know about.
+    for (const Elf_Shdr &Sec : Obj->sections()) {
+      const void *Addr = Obj->base() + Sec.sh_offset;
+      if (Addr >= Start && Addr < End)
+        End = Addr;
+    }
+    
+    // Check all the dynamic regions we know about.
+    auto CheckDRI = [&](DynRegionInfo DRI) {
+      if (DRI.Addr >= Start && DRI.Addr < End)
+        End = DRI.Addr;
+    };
+
+    CheckDRI(DynamicTable);
+    CheckDRI(DynRelRegion);
+    CheckDRI(DynRelaRegion);
+    
+    if (DynamicStringTable.data() >= Start && DynamicStringTable.data() < End)
+      End = DynamicStringTable.data();
+
+    // Scan to the first invalid symbol.
+    auto SymI = reinterpret_cast<const Elf_Sym *>(Start);
+    for (; ((const char *)SymI + sizeof(Elf_Sym)) <= End; ++SymI) {
+      uint32_t NameOffset = SymI->st_name;
+      if (SymI > Start && !NameOffset)
+        break;
+      if (NameOffset >= DynamicStringTable.size())
+        break;
+      uint16_t SectionIndex = SymI->st_shndx;
+      if ((Obj->getNumSections() && SectionIndex >= Obj->getNumSections()) &&
+          SectionIndex < SHN_LORESERVE)
+        break;
+    }
+    End = SymI;
+    DynSymRegion.Size = (const char *)End - (const char *)Start;
+  }
 }
 
 template <typename ELFT>
 typename ELFDumper<ELFT>::Elf_Rel_Range ELFDumper<ELFT>::dyn_rels() const {
-  return make_range(dyn_rel_begin<Elf_Rel>(DynRelRegion),
-                    dyn_rel_end<Elf_Rel>(DynRelRegion));
+  return DynRelRegion.getAsRange<Elf_Rel>();
 }
 
 template <typename ELFT>
 typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
-  return make_range(dyn_rel_begin<Elf_Rela>(DynRelaRegion),
-                    dyn_rel_end<Elf_Rela>(DynRelaRegion));
+  return DynRelaRegion.getAsRange<Elf_Rela>();
 }
 
 template<class ELFT>
@@ -1211,7 +1259,7 @@ void ELFDumper<ELFT>::printSections() {
         if (!SymSec)
           continue;
         if (*SymSec == &Sec)
-          printSymbol(&Sym, Symtab, StrTable, false);
+          printSymbol(&Sym, Obj->symbol_begin(Symtab), StrTable, false);
       }
     }
 
@@ -1328,7 +1376,8 @@ void ELFDumper<ELFT>::printDynamicReloca
   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
   StringRef SymbolName;
   uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL());
-  const Elf_Sym *Sym = DynSymStart + SymIndex;
+  const Elf_Sym *Sym =
+      DynSymRegion.getAsRange<Elf_Sym>().begin() + SymIndex;
   SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
   if (opts::ExpandRelocs) {
     DictScope Group(W, "Relocation");
@@ -1346,14 +1395,21 @@ void ELFDumper<ELFT>::printDynamicReloca
 
 template<class ELFT>
 void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
-  const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;
-  if (!Symtab)
-    return;
-  ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
-  error(StrTableOrErr.getError());
-  StringRef StrTable = *StrTableOrErr;
-  for (const Elf_Sym &Sym : Obj->symbols(Symtab))
-    printSymbol(&Sym, Symtab, StrTable, IsDynamic);
+  StringRef StrTable = DynamicStringTable;
+  Elf_Sym_Range Syms(nullptr, nullptr);
+  if (IsDynamic)
+    Syms = DynSymRegion.getAsRange<Elf_Sym>();
+  else {
+    if (!DotSymtabSec)
+      return;
+    ErrorOr<StringRef> StrTableOrErr =
+        Obj->getStringTableForSymtab(*DotSymtabSec);
+    error(StrTableOrErr.getError());
+    StrTable = *StrTableOrErr;
+    Syms = Obj->symbols(DotSymtabSec);
+  }
+  for (const Elf_Sym &Sym : Syms)
+    printSymbol(&Sym, Syms.begin(), StrTable, IsDynamic);
 }
 
 template<class ELFT>
@@ -1369,11 +1425,12 @@ void ELFDumper<ELFT>::printDynamicSymbol
 }
 
 template <class ELFT>
-void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
-                                  StringRef StrTable, bool IsDynamic) {
+void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol,
+                                  const Elf_Sym *FirstSym, StringRef StrTable,
+                                  bool IsDynamic) {
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName,
+  getSectionNameIndex(*Obj, Symbol, FirstSym, ShndxTable, SectionName,
                       SectionIndex);
   std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
   unsigned char SymbolType = Symbol->getType();
@@ -1650,8 +1707,8 @@ template <> void ELFDumper<ELFType<suppo
 
 template<class ELFT>
 void ELFDumper<ELFT>::printDynamicTable() {
-  auto I = dynamic_table_begin();
-  auto E = dynamic_table_end();
+  auto I = dynamic_table().begin();
+  auto E = dynamic_table().end();
 
   if (I == E)
     return;
@@ -1747,10 +1804,10 @@ void ELFDumper<ELFT>::printGnuHashTable(
   W.printNumber("Shift Count", GnuHashTable->shift2);
   W.printHexList("Bloom Filter", GnuHashTable->filter());
   W.printList("Buckets", GnuHashTable->buckets());
-  if (!DotDynSymSec)
+  if (!DynSymRegion.Size || !DynSymRegion.EntSize)
     reportError("No dynamic symbol section");
-  W.printHexList("Values",
-                 GnuHashTable->values(DotDynSymSec->getEntityCount()));
+  W.printHexList(
+      "Values", GnuHashTable->values(DynSymRegion.Size / DynSymRegion.EntSize));
 }
 
 template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
@@ -1878,11 +1935,9 @@ template <class ELFT> void MipsGOTParser
     return;
   }
 
-  const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
-  ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec);
-  error(StrTable.getError());
-  const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec);
-  const Elf_Sym *DynSymEnd = Obj->symbol_end(DynSymSec);
+  StringRef StrTable = Dumper->getDynamicStringTable();
+  const Elf_Sym *DynSymBegin = Dumper->dynamic_symbols().begin();
+  const Elf_Sym *DynSymEnd = Dumper->dynamic_symbols().end();
   std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
 
   if (*DtGotSym > DynSymTotal)
@@ -1942,8 +1997,8 @@ template <class ELFT> void MipsGOTParser
     const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
     for (; It != GotGlobalEnd; ++It) {
       DictScope D(W, "Entry");
-      printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
-                          *StrTable, true);
+      printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, StrTable,
+                          true);
     }
   }
 
@@ -2046,7 +2101,7 @@ void MipsGOTParser<ELFT>::printGlobalGot
 
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+  getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
                       Dumper->getShndxTable(), SectionName, SectionIndex);
   W.printHex("Section", SectionName, SectionIndex);
 
@@ -2080,7 +2135,7 @@ void MipsGOTParser<ELFT>::printPLTEntry(
 
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+  getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
                       Dumper->getShndxTable(), SectionName, SectionIndex);
   W.printHex("Section", SectionName, SectionIndex);
 

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.h?rev=260488&r1=260487&r2=260488&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.h (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.h Wed Feb 10 22:59:45 2016
@@ -12,6 +12,7 @@
 
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
 #include <string>
 
 namespace llvm {
@@ -22,6 +23,11 @@ namespace llvm {
   // Various helper functions.
   LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
   void error(std::error_code ec);
+  template <class T> T unwrapOrError(ErrorOr<T> EO) {
+    if (EO)
+      return *EO;
+    reportError(EO.getError().message());
+  }
   bool relocAddressLess(object::RelocationRef A,
                         object::RelocationRef B);
 } // namespace llvm




More information about the llvm-commits mailing list