summaryrefslogtreecommitdiff
path: root/lib/Object/ELFObjectFile.cpp
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2011-10-11 02:57:48 +0000
committerNick Lewycky <nicholas@mxc.ca>2011-10-11 02:57:48 +0000
commit15c3f727aeff6a80e3f9e7e6b1284748e5f3322a (patch)
tree02d175d144594f554ff925e49af61f15385c2a76 /lib/Object/ELFObjectFile.cpp
parenta02bfced06b4cc700e50bc497cc42667653f091a (diff)
downloadllvm-15c3f727aeff6a80e3f9e7e6b1284748e5f3322a.tar.gz
llvm-15c3f727aeff6a80e3f9e7e6b1284748e5f3322a.tar.bz2
llvm-15c3f727aeff6a80e3f9e7e6b1284748e5f3322a.tar.xz
Add support for .symtab_shnidx. Unfortunately, doing this required breaking a
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
Diffstat (limited to 'lib/Object/ELFObjectFile.cpp')
-rw-r--r--lib/Object/ELFObjectFile.cpp51
1 files changed, 42 insertions, 9 deletions
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index 16e9d14ce6..a0ba0a0938 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -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