Add support for .symtab_shnidx. Unfortunately, doing this required breaking a
authorNick Lewycky <nicholas@mxc.ca>
Tue, 11 Oct 2011 02:57:48 +0000 (02:57 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Tue, 11 Oct 2011 02:57:48 +0000 (02:57 +0000)
layer of abstraction around SymbolRef where you can read its private
SymbolPimpl member.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141636 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ObjectFile.h
lib/Object/ELFObjectFile.cpp

index 84ef8632cd449e030b31e848d20a0895992c5d0e..83854a0d6c282c4e9e5614ded9b865186cc2823c 100644 (file)
@@ -120,6 +120,8 @@ public:
   /// Returns true for symbols that can be used in another objects,
   /// such as library functions
   error_code isGlobal(bool &Result) const;
+
+  DataRefImpl getRawDataRefImpl() const;
 };
 typedef content_iterator<SymbolRef> symbol_iterator;
 
@@ -345,6 +347,10 @@ inline error_code SymbolRef::getSymbolType(SymbolRef::SymbolType &Result) const
   return OwningObject->getSymbolType(SymbolPimpl, Result);
 }
 
+inline DataRefImpl SymbolRef::getRawDataRefImpl() const {
+  return SymbolPimpl;
+}
+
 
 /// SectionRef
 inline SectionRef::SectionRef(DataRefImpl SectionP,
index 16e9d14ce607e9d1c9eb4a17add99316f9b80a86..a0ba0a09381144416a69d8bbd6d8bf1d1b946357 100644 (file)
@@ -296,6 +296,7 @@ class ELFObjectFile : public ObjectFile {
   const Elf_Shdr *dot_strtab_sec;   // Symbol header string table.
   Sections_t SymbolTableSections;
   IndexMap_t SymbolTableSectionsIndexMap;
+  DenseMap<const Elf_Sym*, Elf_Word> ExtendedSymbolTable;
 
   /// @brief Map sections to an array of relocation sections that reference
   ///        them sorted by section index.
@@ -371,6 +372,8 @@ public:
   virtual uint8_t getBytesInAddress() const;
   virtual StringRef getFileFormatName() const;
   virtual unsigned getArch() const;
+
+  uint64_t getSymbolTableIndex(const Elf_Sym *symb) const;
 };
 } // end namespace
 
@@ -422,18 +425,26 @@ error_code ELFObjectFile<target_endianness, is64Bits>
                         ::getSymbolName(DataRefImpl Symb,
                                         StringRef &Result) const {
   validateSymbol(Symb);
-  const Elf_Sym  *symb = getSymbol(Symb);
+  const Elf_Sym *symb = getSymbol(Symb);
   return getSymbolName(symb, Result);
 }
 
+template<support::endianness target_endianness, bool is64Bits>
+uint64_t ELFObjectFile<target_endianness, is64Bits>
+                      ::getSymbolTableIndex(const Elf_Sym *symb) const {
+  if (symb->st_shndx == ELF::SHN_XINDEX)
+    return ExtendedSymbolTable.lookup(symb);
+  return symb->st_shndx;
+}
+
 template<support::endianness target_endianness, bool is64Bits>
 error_code ELFObjectFile<target_endianness, is64Bits>
                         ::getSymbolOffset(DataRefImpl Symb,
-                                           uint64_t &Result) const {
+                                          uint64_t &Result) const {
   validateSymbol(Symb);
   const Elf_Sym  *symb = getSymbol(Symb);
   const Elf_Shdr *Section;
-  switch (symb->st_shndx) {
+  switch (getSymbolTableIndex(symb)) {
   case ELF::SHN_COMMON:
    // Undefined symbols have no address yet.
   case ELF::SHN_UNDEF:
@@ -467,7 +478,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
   validateSymbol(Symb);
   const Elf_Sym  *symb = getSymbol(Symb);
   const Elf_Shdr *Section;
-  switch (symb->st_shndx) {
+  switch (getSymbolTableIndex(symb)) {
   case ELF::SHN_COMMON: // Fall through.
    // Undefined symbols have no address yet.
   case ELF::SHN_UNDEF:
@@ -476,7 +487,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
   case ELF::SHN_ABS:
     Result = reinterpret_cast<uintptr_t>(base()+symb->st_value);
     return object_error::success;
-  default: Section = getSection(symb->st_shndx);
+  default: Section = getSection(getSymbolTableIndex(symb));
   }
   const uint8_t* addr = base();
   if (Section)
@@ -515,7 +526,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
                                               char &Result) const {
   validateSymbol(Symb);
   const Elf_Sym  *symb = getSymbol(Symb);
-  const Elf_Shdr *Section = getSection(symb->st_shndx);
+  const Elf_Shdr *Section = getSection(getSymbolTableIndex(symb));
 
   char ret = '?';
 
@@ -581,7 +592,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
   validateSymbol(Symb);
   const Elf_Sym  *symb = getSymbol(Symb);
 
-  if (symb->st_shndx == ELF::SHN_UNDEF) {
+  if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) {
     Result = SymbolRef::ST_External;
     return object_error::success;
   }
@@ -1074,9 +1085,16 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
     report_fatal_error("Section table goes past end of file!");
 
 
-  // To find the symbol tables we walk the section table to find SHT_STMTAB.
+  // To find the symbol tables we walk the section table to find SHT_SYMTAB.
+  const Elf_Shdr* SymbolTableSectionHeaderIndex = 0;
   const Elf_Shdr* sh = reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable);
   for (unsigned i = 0; i < Header->e_shnum; ++i) {
+    if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) {
+      if (SymbolTableSectionHeaderIndex)
+        // FIXME: Proper error handling.
+        report_fatal_error("More than one .symtab_shndx!");
+      SymbolTableSectionHeaderIndex = sh;
+    }
     if (sh->sh_type == ELF::SHT_SYMTAB) {
       SymbolTableSectionsIndexMap[i] = SymbolTableSections.size();
       SymbolTableSections.push_back(sh);
@@ -1122,6 +1140,21 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
       }
     }
   }
+
+  // Build symbol name side-mapping if there is one.
+  if (SymbolTableSectionHeaderIndex) {
+    const Elf_Word *ShndxTable = reinterpret_cast<const Elf_Word*>(base() +
+                                      SymbolTableSectionHeaderIndex->sh_offset);
+    error_code ec;
+    for (symbol_iterator si = begin_symbols(),
+                         se = end_symbols(); si != se; si.increment(ec)) {
+      if (ec)
+        report_fatal_error("Fewer extended symbol table entries than symbols!");
+      if (*ShndxTable != ELF::SHN_UNDEF)
+        ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable;
+      ++ShndxTable;
+    }
+  }
 }
 
 template<support::endianness target_endianness, bool is64Bits>
@@ -1303,7 +1336,7 @@ error_code ELFObjectFile<target_endianness, is64Bits>
                         ::getSymbolName(const Elf_Sym *symb,
                                         StringRef &Result) const {
   if (symb->st_name == 0) {
-    const Elf_Shdr *section = getSection(symb->st_shndx);
+    const Elf_Shdr *section = getSection(getSymbolTableIndex(symb));
     if (!section)
       Result = "";
     else