[llvm] r244510 - Don't iterate over all sections in the ELFFile constructor.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 14:29:35 PDT 2015


Author: rafael
Date: Mon Aug 10 16:29:35 2015
New Revision: 244510

URL: http://llvm.org/viewvc/llvm-project?rev=244510&view=rev
Log:
Don't iterate over all sections in the ELFFile constructor.

With this we finally have an ELFFile that is O(1) to construct. This is helpful
for programs like lld which have to do their own section walk.

Modified:
    llvm/trunk/include/llvm/Object/ELF.h
    llvm/trunk/include/llvm/Object/ELFObjectFile.h
    llvm/trunk/tools/llvm-readobj/ARMEHABIPrinter.h
    llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
    llvm/trunk/tools/obj2yaml/elf2yaml.cpp

Modified: llvm/trunk/include/llvm/Object/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=244510&r1=244509&r2=244510&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELF.h (original)
+++ llvm/trunk/include/llvm/Object/ELF.h Mon Aug 10 16:29:35 2015
@@ -68,9 +68,6 @@ private:
   const Elf_Ehdr *Header;
   const Elf_Shdr *SectionHeaderTable = nullptr;
   StringRef DotShstrtab;                    // Section header string table.
-  const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section.
-
-  const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr;
 
 public:
   template<typename T>
@@ -81,6 +78,8 @@ public:
   ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const;
   ErrorOr<StringRef> getStringTableForSymtab(const Elf_Shdr &Section) const;
 
+  ErrorOr<ArrayRef<Elf_Word>> getSHNDXTable(const Elf_Shdr &Section) const;
+
   void VerifyStrTab(const Elf_Shdr *sh) const;
 
   StringRef getRelocationTypeName(uint32_t Type) const;
@@ -198,9 +197,13 @@ public:
 
   uint64_t getNumSections() const;
   uintX_t getStringTableIndex() const;
-  ELF::Elf64_Word getExtendedSymbolTableIndex(const Elf_Sym *symb) const;
+  ELF::Elf64_Word
+  getExtendedSymbolTableIndex(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+                              ArrayRef<Elf_Word> ShndxTable) const;
   const Elf_Ehdr *getHeader() const { return Header; }
-  ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *symb) const;
+  ErrorOr<const Elf_Shdr *> getSection(const Elf_Sym *Sym,
+                                       const Elf_Shdr *SymTab,
+                                       ArrayRef<Elf_Word> ShndxTable) const;
   ErrorOr<const Elf_Shdr *> getSection(uint32_t Index) const;
 
   const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const {
@@ -217,26 +220,27 @@ typedef ELFFile<ELFType<support::big, fa
 typedef ELFFile<ELFType<support::big, true>> ELF64BEFile;
 
 template <class ELFT>
-ELF::Elf64_Word
-ELFFile<ELFT>::getExtendedSymbolTableIndex(const Elf_Sym *Sym) const {
+ELF::Elf64_Word ELFFile<ELFT>::getExtendedSymbolTableIndex(
+    const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+    ArrayRef<Elf_Word> ShndxTable) const {
   assert(Sym->st_shndx == ELF::SHN_XINDEX);
-  unsigned Index = Sym - symbol_begin(dot_symtab_sec);
+  unsigned Index = Sym - symbol_begin(SymTab);
 
   // FIXME: error checking
-  const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word *>(
-      base() + SymbolTableSectionHeaderIndex->sh_offset);
   return ShndxTable[Index];
 }
 
 template <class ELFT>
 ErrorOr<const typename ELFFile<ELFT>::Elf_Shdr *>
-ELFFile<ELFT>::getSection(const Elf_Sym *symb) const {
-  uint32_t Index = symb->st_shndx;
+ELFFile<ELFT>::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+                          ArrayRef<Elf_Word> ShndxTable) const {
+  uint32_t Index = Sym->st_shndx;
   if (Index == ELF::SHN_XINDEX)
-    return getSection(getExtendedSymbolTableIndex(symb));
+    return getSection(getExtendedSymbolTableIndex(Sym, SymTab, ShndxTable));
+
   if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)
     return nullptr;
-  return getSection(symb->st_shndx);
+  return getSection(Sym->st_shndx);
 }
 
 template <class ELFT>
@@ -355,29 +359,6 @@ ELFFile<ELFT>::ELFFile(StringRef Object,
     return;
   }
 
-  // Scan sections for special sections.
-
-  for (const Elf_Shdr &Sec : sections()) {
-    switch (Sec.sh_type) {
-    case ELF::SHT_SYMTAB_SHNDX:
-      if (SymbolTableSectionHeaderIndex) {
-        // More than one .symtab_shndx!
-        EC = object_error::parse_failed;
-        return;
-      }
-      SymbolTableSectionHeaderIndex = &Sec;
-      break;
-    case ELF::SHT_SYMTAB: {
-      if (dot_symtab_sec) {
-        // More than one .symtab!
-        EC = object_error::parse_failed;
-        return;
-      }
-      dot_symtab_sec = &Sec;
-    } break;
-    }
-  }
-
   // Get string table sections.
   uintX_t StringTableIndex = getStringTableIndex();
   if (StringTableIndex) {
@@ -485,6 +466,21 @@ ELFFile<ELFT>::getStringTable(const Elf_
 }
 
 template <class ELFT>
+ErrorOr<ArrayRef<typename ELFFile<ELFT>::Elf_Word>>
+ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section) const {
+  assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);
+  const Elf_Word *ShndxTableBegin =
+      reinterpret_cast<const Elf_Word *>(base() + Section.sh_offset);
+  uintX_t Size = Section.sh_offset;
+  if (Size % sizeof(uintX_t))
+    return object_error::parse_failed;
+  const Elf_Word *ShndxTableEnd = ShndxTableBegin + Size / sizeof(uintX_t);
+  if (reinterpret_cast<const char *>(ShndxTableEnd) > Buf.end())
+    return object_error::parse_failed;
+  return ArrayRef<Elf_Word>(ShndxTableBegin, ShndxTableEnd);
+}
+
+template <class ELFT>
 ErrorOr<StringRef>
 ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec) const {
   if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)

Modified: llvm/trunk/include/llvm/Object/ELFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFObjectFile.h?rev=244510&r1=244509&r2=244510&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ELFObjectFile.h Mon Aug 10 16:29:35 2015
@@ -194,6 +194,7 @@ protected:
 
   const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section.
   const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
+  ArrayRef<Elf_Word> ShndxTable;
 
   void moveSymbolNext(DataRefImpl &Symb) const override;
   ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override;
@@ -205,7 +206,8 @@ protected:
   uint8_t getSymbolOther(DataRefImpl Symb) const override;
   uint8_t getSymbolELFType(DataRefImpl Symb) const override;
   SymbolRef::Type getSymbolType(DataRefImpl Symb) const override;
-  ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb) const;
+  ErrorOr<section_iterator> getSymbolSection(const Elf_Sym *Symb,
+                                             const Elf_Shdr *SymTab) const;
   ErrorOr<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
 
   void moveSectionNext(DataRefImpl &Sec) const override;
@@ -399,9 +401,11 @@ ELFObjectFile<ELFT>::getSymbolAddress(Da
   }
 
   const Elf_Ehdr *Header = EF.getHeader();
+  const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
 
   if (Header->e_type == ELF::ET_REL) {
-    ErrorOr<const Elf_Shdr *> SectionOrErr = EF.getSection(ESym);
+    ErrorOr<const Elf_Shdr *> SectionOrErr =
+        EF.getSection(ESym, SymTab, ShndxTable);
     if (std::error_code EC = SectionOrErr.getError())
       return EC;
     const Elf_Shdr *Section = *SectionOrErr;
@@ -508,8 +512,9 @@ uint32_t ELFObjectFile<ELFT>::getSymbolF
 
 template <class ELFT>
 ErrorOr<section_iterator>
-ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
-  ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym);
+ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym,
+                                      const Elf_Shdr *SymTab) const {
+  ErrorOr<const Elf_Shdr *> ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable);
   if (std::error_code EC = ESecOrErr.getError())
     return EC;
 
@@ -525,7 +530,9 @@ ELFObjectFile<ELFT>::getSymbolSection(co
 template <class ELFT>
 ErrorOr<section_iterator>
 ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const {
-  return getSymbolSection(getSymbol(Symb));
+  const Elf_Sym *Sym = getSymbol(Symb);
+  const Elf_Shdr *SymTab = *EF.getSection(Symb.d.a);
+  return getSymbolSection(Sym, SymTab);
 }
 
 template <class ELFT>
@@ -756,6 +763,13 @@ ELFObjectFile<ELFT>::ELFObjectFile(Memor
       DotSymtabSec = &Sec;
       break;
     }
+    case ELF::SHT_SYMTAB_SHNDX: {
+      ErrorOr<ArrayRef<Elf_Word>> TableOrErr = EF.getSHNDXTable(Sec);
+      if ((EC = TableOrErr.getError()))
+        return;
+      ShndxTable = *TableOrErr;
+      break;
+    }
     }
   }
 }

Modified: llvm/trunk/tools/llvm-readobj/ARMEHABIPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ARMEHABIPrinter.h?rev=244510&r1=244509&r2=244510&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ARMEHABIPrinter.h (original)
+++ llvm/trunk/tools/llvm-readobj/ARMEHABIPrinter.h Mon Aug 10 16:29:35 2015
@@ -308,10 +308,12 @@ class PrinterContext {
   typedef typename object::ELFFile<ET>::Elf_Sym Elf_Sym;
   typedef typename object::ELFFile<ET>::Elf_Shdr Elf_Shdr;
   typedef typename object::ELFFile<ET>::Elf_Rel Elf_Rel;
+  typedef typename object::ELFFile<ET>::Elf_Word Elf_Word;
 
   StreamWriter &SW;
   const object::ELFFile<ET> *ELF;
   const Elf_Shdr *Symtab;
+  ArrayRef<Elf_Word> ShndxTable;
 
   static const size_t IndexTableEntrySize;
 
@@ -385,7 +387,8 @@ PrinterContext<ET>::FindExceptionTable(u
       std::pair<const Elf_Shdr *, const Elf_Sym *> Symbol =
         ELF->getRelocationSymbol(&Sec, &RelA);
 
-      ErrorOr<const Elf_Shdr *> Ret = ELF->getSection(Symbol.second);
+      ErrorOr<const Elf_Shdr *> Ret =
+          ELF->getSection(Symbol.second, Symbol.first, ShndxTable);
       if (std::error_code EC = Ret.getError())
         report_fatal_error(EC.message());
       return *Ret;

Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=244510&r1=244509&r2=244510&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Mon Aug 10 16:29:35 2015
@@ -77,6 +77,7 @@ private:
   typedef typename ELFO::Elf_Phdr Elf_Phdr;
   typedef typename ELFO::Elf_Hash Elf_Hash;
   typedef typename ELFO::Elf_Ehdr Elf_Ehdr;
+  typedef typename ELFO::Elf_Word Elf_Word;
   typedef typename ELFO::uintX_t uintX_t;
   typedef typename ELFO::Elf_Versym Elf_Versym;
   typedef typename ELFO::Elf_Verneed Elf_Verneed;
@@ -94,7 +95,8 @@ private:
     uintX_t EntSize;
   };
 
-  void printSymbol(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic);
+  void printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
+                   StringRef StrTable, bool IsDynamic);
 
   void printRelocations(const Elf_Shdr *Sec);
   void printRelocation(const Elf_Shdr *Sec, Elf_Rela Rel);
@@ -135,6 +137,7 @@ private:
   const Elf_Hash *HashTable = nullptr;
   const Elf_Shdr *DotDynSymSec = nullptr;
   const Elf_Shdr *DotSymtabSec = nullptr;
+  ArrayRef<Elf_Word> ShndxTable;
 
   const Elf_Shdr *dot_gnu_version_sec = nullptr;   // .gnu.version
   const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r
@@ -167,6 +170,8 @@ public:
   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; }
 };
 
 template <class T> T errorOrDefault(ErrorOr<T> Val, T Default = T()) {
@@ -368,6 +373,8 @@ 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,
+                    ArrayRef<typename ELFO::Elf_Word> ShndxTable,
                     StringRef &SectionName, unsigned &SectionIndex) {
   SectionIndex = Symbol->st_shndx;
   if (Symbol->isUndefined())
@@ -384,7 +391,8 @@ getSectionNameIndex(const ELFO &Obj, con
     SectionName = "Reserved";
   else {
     if (SectionIndex == SHN_XINDEX)
-      SectionIndex = Obj.getExtendedSymbolTableIndex(Symbol);
+      SectionIndex =
+          Obj.getExtendedSymbolTableIndex(Symbol, SymTab, ShndxTable);
     ErrorOr<const typename ELFO::Elf_Shdr *> Sec = Obj.getSection(SectionIndex);
     error(Sec.getError());
     SectionName = errorOrDefault(Obj.getSectionName(*Sec));
@@ -897,6 +905,12 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
         reportError("Multilpe SHT_SYMTAB");
       DotSymtabSec = &Sec;
       break;
+    case ELF::SHT_SYMTAB_SHNDX: {
+      ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj->getSHNDXTable(Sec);
+      error(TableOrErr.getError());
+      ShndxTable = *TableOrErr;
+      break;
+    }
     }
   }
 }
@@ -1009,11 +1023,12 @@ void ELFDumper<ELFT>::printSections() {
       StringRef StrTable = *StrTableOrErr;
 
       for (const Elf_Sym &Sym : Obj->symbols(Symtab)) {
-        ErrorOr<const Elf_Shdr *> SymSec = Obj->getSection(&Sym);
+        ErrorOr<const Elf_Shdr *> SymSec =
+            Obj->getSection(&Sym, Symtab, ShndxTable);
         if (!SymSec)
           continue;
         if (*SymSec == &Sec)
-          printSymbol(&Sym, StrTable, false);
+          printSymbol(&Sym, Symtab, StrTable, false);
       }
     }
 
@@ -1104,7 +1119,8 @@ void ELFDumper<ELFT>::printRelocation(co
   std::pair<const Elf_Shdr *, const Elf_Sym *> Sym =
       Obj->getRelocationSymbol(Sec, &Rel);
   if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) {
-    ErrorOr<const Elf_Shdr *> Sec = Obj->getSection(Sym.second);
+    ErrorOr<const Elf_Shdr *> Sec =
+        Obj->getSection(Sym.second, Sym.first, ShndxTable);
     error(Sec.getError());
     ErrorOr<StringRef> SecName = Obj->getSectionName(*Sec);
     if (SecName)
@@ -1140,7 +1156,7 @@ void ELFDumper<ELFT>::printSymbols() {
   error(StrTableOrErr.getError());
   StringRef StrTable = *StrTableOrErr;
   for (const Elf_Sym &Sym : Obj->symbols(Symtab))
-    printSymbol(&Sym, StrTable, false);
+    printSymbol(&Sym, Symtab, StrTable, false);
 }
 
 template<class ELFT>
@@ -1152,15 +1168,16 @@ void ELFDumper<ELFT>::printDynamicSymbol
   error(StrTableOrErr.getError());
   StringRef StrTable = *StrTableOrErr;
   for (const Elf_Sym &Sym : Obj->symbols(Symtab))
-    printSymbol(&Sym, StrTable, true);
+    printSymbol(&Sym, Symtab, StrTable, true);
 }
 
 template <class ELFT>
-void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, StringRef StrTable,
-                                  bool IsDynamic) {
+void ELFDumper<ELFT>::printSymbol(const Elf_Sym *Symbol, const Elf_Shdr *SymTab,
+                                  StringRef StrTable, bool IsDynamic) {
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Symbol, SectionName, SectionIndex);
+  getSectionNameIndex(*Obj, Symbol, SymTab, ShndxTable, SectionName,
+                      SectionIndex);
   std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic);
   unsigned char SymbolType = Symbol->getType();
 
@@ -1824,7 +1841,8 @@ void MipsGOTParser<ELFT>::printGlobalGot
 
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
+  getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+                      Dumper->getShndxTable(), SectionName, SectionIndex);
   W.printHex("Section", SectionName, SectionIndex);
 
   std::string FullSymbolName =
@@ -1857,7 +1875,8 @@ void MipsGOTParser<ELFT>::printPLTEntry(
 
   unsigned SectionIndex = 0;
   StringRef SectionName;
-  getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
+  getSectionNameIndex(*Obj, Sym, Dumper->getDotDynSymSec(),
+                      Dumper->getShndxTable(), SectionName, SectionIndex);
   W.printHex("Section", SectionName, SectionIndex);
 
   std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);

Modified: llvm/trunk/tools/obj2yaml/elf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/elf2yaml.cpp?rev=244510&r1=244509&r2=244510&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/elf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/elf2yaml.cpp Mon Aug 10 16:29:35 2015
@@ -26,9 +26,10 @@ class ELFDumper {
   typedef typename object::ELFFile<ELFT>::Elf_Word Elf_Word;
 
   const object::ELFFile<ELFT> &Obj;
+  ArrayRef<Elf_Word> ShndxTable;
 
-  std::error_code dumpSymbol(const Elf_Sym *Sym, StringRef StrTable,
-                             ELFYAML::Symbol &S);
+  std::error_code dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+                             StringRef StrTable, ELFYAML::Symbol &S);
   std::error_code dumpCommonSection(const Elf_Shdr *Shdr, ELFYAML::Section &S);
   std::error_code dumpCommonRelocationSection(const Elf_Shdr *Shdr,
                                               ELFYAML::RelocationSection &S);
@@ -81,6 +82,13 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELF
     case ELF::SHT_SYMTAB:
       Symtab = &Sec;
       break;
+    case ELF::SHT_SYMTAB_SHNDX: {
+      ErrorOr<ArrayRef<Elf_Word>> TableOrErr = Obj.getSHNDXTable(Sec);
+      if (std::error_code EC = TableOrErr.getError())
+        return EC;
+      ShndxTable = *TableOrErr;
+      break;
+    }
     case ELF::SHT_RELA: {
       ErrorOr<ELFYAML::RelocationSection *> S = dumpRelaSection(&Sec);
       if (std::error_code EC = S.getError())
@@ -139,7 +147,8 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELF
     }
 
     ELFYAML::Symbol S;
-    if (std::error_code EC = ELFDumper<ELFT>::dumpSymbol(&Sym, StrTable, S))
+    if (std::error_code EC =
+            ELFDumper<ELFT>::dumpSymbol(&Sym, Symtab, StrTable, S))
       return EC;
 
     switch (Sym.getBinding())
@@ -162,9 +171,9 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELF
 }
 
 template <class ELFT>
-std::error_code ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym,
-                                            StringRef StrTable,
-                                            ELFYAML::Symbol &S) {
+std::error_code
+ELFDumper<ELFT>::dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
+                            StringRef StrTable, ELFYAML::Symbol &S) {
   S.Type = Sym->getType();
   S.Value = Sym->st_value;
   S.Size = Sym->st_size;
@@ -175,7 +184,7 @@ std::error_code ELFDumper<ELFT>::dumpSym
     return EC;
   S.Name = NameOrErr.get();
 
-  ErrorOr<const Elf_Shdr *> ShdrOrErr = Obj.getSection(Sym);
+  ErrorOr<const Elf_Shdr *> ShdrOrErr = Obj.getSection(Sym, SymTab, ShndxTable);
   if (std::error_code EC = ShdrOrErr.getError())
     return EC;
   const Elf_Shdr *Shdr = *ShdrOrErr;




More information about the llvm-commits mailing list