[llvm] r261099 - Change how readobj stores info about dynamic symbols.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 17 07:38:21 PST 2016


Author: rafael
Date: Wed Feb 17 09:38:21 2016
New Revision: 261099

URL: http://llvm.org/viewvc/llvm-project?rev=261099&view=rev
Log:
Change how readobj stores info about dynamic symbols.

We used to keep both a section and a pointer to the first symbol.

The oddity of keeping a section for dynamic symbols is because there is
a DT_SYMTAB but no DT_SYMTABZ, so to print the table we have to find the
size via a section table.

The reason for still keeping a pointer to the first symbol is because we
want to be able to print relocation tables even if the section table is
missing (it is mandatory only for files used in linking).

With this patch we keep just a DynRegionInfo. This then requires
changing a few places that were asking for a Elf_Shdr but actually just
needed the first symbol.

The test change is to delete the program header pointer.
Now that we use the information of both DT_SYMTAB and .dynsym, we don't
depend on the sh_entsize of .dynsym if we see DT_SYMTAB.

Note: It is questionable if it is worth it putting the effort to report
broken sh_entsize given that in files with no section table we have to
assume it is sizeof(Elf_Sym), but that is for another change.

Extracted from r260488.

Modified:
    llvm/trunk/include/llvm/Object/ELF.h
    llvm/trunk/test/Object/Inputs/invalid-sh_entsize.elf
    llvm/trunk/test/Object/invalid.test
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=261099&r1=261098&r2=261099&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Wed Feb 17 09:38:21 2016
@@ -200,6 +200,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 +228,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];

Modified: llvm/trunk/test/Object/Inputs/invalid-sh_entsize.elf
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/invalid-sh_entsize.elf?rev=261099&r1=261098&r2=261099&view=diff
==============================================================================
Binary files llvm/trunk/test/Object/Inputs/invalid-sh_entsize.elf (original) and llvm/trunk/test/Object/Inputs/invalid-sh_entsize.elf Wed Feb 17 09:38:21 2016 differ

Modified: llvm/trunk/test/Object/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/invalid.test?rev=261099&r1=261098&r2=261099&view=diff
==============================================================================
--- llvm/trunk/test/Object/invalid.test (original)
+++ llvm/trunk/test/Object/invalid.test Wed Feb 17 09:38:21 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

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=261099&r1=261098&r2=261099&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Wed Feb 17 09:38:21 2016
@@ -48,9 +48,14 @@ namespace {
 
 template <class ELFT> class DumpStyle;
 
-/// \brief Represents a region described by entries in the .dynamic table.
+/// Represents a contiguous uniform range in the file. We cannot just create a
+/// range directly because when creating one of these from the .dynamic table
+/// the size, entity size and virtual address are different entries in arbitrary
+/// order (DT_REL, DT_RELSZ, DT_RELENT for example).
 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.
@@ -102,6 +107,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;
@@ -121,10 +127,14 @@ private:
   typedef typename ELFO::Elf_Verdef Elf_Verdef;
   typedef typename ELFO::Elf_Verdaux Elf_Verdaux;
 
+  DynRegionInfo createDRIFrom(const Elf_Shdr *S) {
+    return {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);
@@ -155,13 +165,12 @@ private:
   DynRegionInfo DynRelRegion;
   DynRegionInfo DynRelaRegion;
   DynRegionInfo DynPLTRelRegion;
+  DynRegionInfo DynSymRegion;
   const Elf_Phdr *DynamicProgHeader = nullptr;
   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;
 
@@ -199,11 +208,15 @@ public:
     return *Ret;
   }
 
+  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 {
@@ -346,7 +359,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?
@@ -380,18 +393,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);
@@ -467,7 +477,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
@@ -523,7 +533,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;
@@ -542,7 +552,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));
@@ -1012,9 +1022,9 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
       DotSymtabSec = &Sec;
       break;
     case ELF::SHT_DYNSYM:
-      if (DotDynSymSec != nullptr)
+      if (DynSymRegion.Size)
         reportError("Multilpe SHT_DYNSYM");
-      DotDynSymSec = &Sec;
+      DynSymRegion = createDRIFrom(&Sec);
       break;
     case ELF::SHT_SYMTAB_SHNDX: {
       ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
@@ -1084,8 +1094,8 @@ void ELFDumper<ELFT>::parseDynamicTable(
       StringTableSize = Dyn.getVal();
       break;
     case ELF::DT_SYMTAB:
-      DynSymStart =
-          reinterpret_cast<const Elf_Sym *>(toMappedAddr(Dyn.getPtr()));
+      DynSymRegion.Addr = toMappedAddr(Dyn.getPtr());
+      DynSymRegion.EntSize = sizeof(Elf_Sym);
       break;
     case ELF::DT_RELA:
       DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
@@ -1213,7 +1223,7 @@ void ELFDumper<ELFT>::printSections() {
         if (!SymSec)
           continue;
         if (*SymSec == &Sec)
-          printSymbol(&Sym, Symtab, StrTable, false);
+          printSymbol(&Sym, Obj->symbol_begin(Symtab), StrTable, false);
       }
     }
 
@@ -1341,7 +1351,7 @@ 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 = dynamic_symbols().begin() + SymIndex;
   SymbolName = errorOrDefault(Sym->getName(DynamicStringTable));
   if (opts::ExpandRelocs) {
     DictScope Group(W, "Relocation");
@@ -1359,14 +1369,23 @@ 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;
+  Elf_Sym_Range Syms(nullptr, nullptr);
+
+  if (IsDynamic) {
+    StrTable = DynamicStringTable;
+    Syms = dynamic_symbols();
+  } 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>
@@ -1382,11 +1401,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();
@@ -1760,10 +1780,11 @@ void ELFDumper<ELFT>::printGnuHashTable(
   W.printNumber("Shift Count", GnuHashTable->shift2);
   W.printHexList("Bloom Filter", GnuHashTable->filter());
   W.printList("Buckets", GnuHashTable->buckets());
-  if (!DotDynSymSec)
+  Elf_Sym_Range Syms = dynamic_symbols();
+  unsigned NumSyms = std::distance(Syms.begin(), Syms.end());
+  if (!NumSyms)
     reportError("No dynamic symbol section");
-  W.printHexList("Values",
-                 GnuHashTable->values(DotDynSymSec->getEntityCount()));
+  W.printHexList("Values", GnuHashTable->values(NumSyms));
 }
 
 template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
@@ -1891,11 +1912,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)
@@ -1955,8 +1974,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);
     }
   }
 
@@ -2059,7 +2078,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);
 
@@ -2093,7 +2112,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);
 




More information about the llvm-commits mailing list