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.

llvm-svn: 244510
This commit is contained in:
Rafael Espindola 2015-08-10 21:29:35 +00:00
parent cc6554361c
commit aae5541455
5 changed files with 103 additions and 62 deletions

View File

@ -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, false>> ELF32BEFile;
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, std::error_code &EC)
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) {
@ -484,6 +465,21 @@ ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const {
return Data;
}
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 {

View File

@ -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(DataRefImpl Symb) const {
}
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>::getSymbolFlags(DataRefImpl Sym) const {
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(const Elf_Sym *ESym) const {
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(MemoryBufferRef Object, std::error_code &EC)
DotSymtabSec = &Sec;
break;
}
case ELF::SHT_SYMTAB_SHNDX: {
ErrorOr<ArrayRef<Elf_Word>> TableOrErr = EF.getSHNDXTable(Sec);
if ((EC = TableOrErr.getError()))
return;
ShndxTable = *TableOrErr;
break;
}
}
}
}

View File

@ -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(unsigned IndexSectionIndex,
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;

View File

@ -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>::getFullSymbolName(const Elf_Sym *Symbol,
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, const typename ELFO::Elf_Sym *Symbol,
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<ELFT> *Obj, StreamWriter &Writer)
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(const Elf_Shdr *Sec, Elf_Rela Rel) {
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>::printDynamicSymbols() {
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>::printGlobalGotEntry(
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(uint64_t PLTAddr,
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);

View File

@ -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<ELFT>::dump() {
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<ELFT>::dump() {
}
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<ELFT>::dump() {
}
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>::dumpSymbol(const Elf_Sym *Sym,
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;