From 0d34e64f73e9a9588bf7260c3ed3671f30e3e7ce Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 10 Aug 2015 21:29:35 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244510 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 70 +++++++++++++--------------- include/llvm/Object/ELFObjectFile.h | 24 ++++++++-- tools/llvm-readobj/ARMEHABIPrinter.h | 5 +- tools/llvm-readobj/ELFDumper.cpp | 43 ++++++++++++----- tools/obj2yaml/elf2yaml.cpp | 23 ++++++--- 5 files changed, 103 insertions(+), 62 deletions(-) diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 833f4a7ba86..9750d3be175 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -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 @@ -81,6 +78,8 @@ public: ErrorOr getStringTable(const Elf_Shdr *Section) const; ErrorOr getStringTableForSymtab(const Elf_Shdr &Section) const; + ErrorOr> 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 ShndxTable) const; const Elf_Ehdr *getHeader() const { return Header; } - ErrorOr getSection(const Elf_Sym *symb) const; + ErrorOr getSection(const Elf_Sym *Sym, + const Elf_Shdr *SymTab, + ArrayRef ShndxTable) const; ErrorOr getSection(uint32_t Index) const; const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { @@ -217,26 +220,27 @@ typedef ELFFile> ELF32BEFile; typedef ELFFile> ELF64BEFile; template -ELF::Elf64_Word -ELFFile::getExtendedSymbolTableIndex(const Elf_Sym *Sym) const { +ELF::Elf64_Word ELFFile::getExtendedSymbolTableIndex( + const Elf_Sym *Sym, const Elf_Shdr *SymTab, + ArrayRef 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( - base() + SymbolTableSectionHeaderIndex->sh_offset); return ShndxTable[Index]; } template ErrorOr::Elf_Shdr *> -ELFFile::getSection(const Elf_Sym *symb) const { - uint32_t Index = symb->st_shndx; +ELFFile::getSection(const Elf_Sym *Sym, const Elf_Shdr *SymTab, + ArrayRef 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 @@ -355,29 +359,6 @@ ELFFile::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::getStringTable(const Elf_Shdr *Section) const { return Data; } +template +ErrorOr::Elf_Word>> +ELFFile::getSHNDXTable(const Elf_Shdr &Section) const { + assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX); + const Elf_Word *ShndxTableBegin = + reinterpret_cast(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(ShndxTableEnd) > Buf.end()) + return object_error::parse_failed; + return ArrayRef(ShndxTableBegin, ShndxTableEnd); +} + template ErrorOr ELFFile::getStringTableForSymtab(const Elf_Shdr &Sec) const { diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index d345c96a404..3a9739afbeb 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -194,6 +194,7 @@ protected: const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. + ArrayRef ShndxTable; void moveSymbolNext(DataRefImpl &Symb) const override; ErrorOr 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 getSymbolSection(const Elf_Sym *Symb) const; + ErrorOr getSymbolSection(const Elf_Sym *Symb, + const Elf_Shdr *SymTab) const; ErrorOr getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; @@ -399,9 +401,11 @@ ELFObjectFile::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 SectionOrErr = EF.getSection(ESym); + ErrorOr 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::getSymbolFlags(DataRefImpl Sym) const { template ErrorOr -ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { - ErrorOr ESecOrErr = EF.getSection(ESym); +ELFObjectFile::getSymbolSection(const Elf_Sym *ESym, + const Elf_Shdr *SymTab) const { + ErrorOr ESecOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (std::error_code EC = ESecOrErr.getError()) return EC; @@ -525,7 +530,9 @@ ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { template ErrorOr ELFObjectFile::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 @@ -756,6 +763,13 @@ ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) DotSymtabSec = &Sec; break; } + case ELF::SHT_SYMTAB_SHNDX: { + ErrorOr> TableOrErr = EF.getSHNDXTable(Sec); + if ((EC = TableOrErr.getError())) + return; + ShndxTable = *TableOrErr; + break; + } } } } diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h index 85b2f2906ca..39bcdaae651 100644 --- a/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/tools/llvm-readobj/ARMEHABIPrinter.h @@ -308,10 +308,12 @@ class PrinterContext { typedef typename object::ELFFile::Elf_Sym Elf_Sym; typedef typename object::ELFFile::Elf_Shdr Elf_Shdr; typedef typename object::ELFFile::Elf_Rel Elf_Rel; + typedef typename object::ELFFile::Elf_Word Elf_Word; StreamWriter &SW; const object::ELFFile *ELF; const Elf_Shdr *Symtab; + ArrayRef ShndxTable; static const size_t IndexTableEntrySize; @@ -385,7 +387,8 @@ PrinterContext::FindExceptionTable(unsigned IndexSectionIndex, std::pair Symbol = ELF->getRelocationSymbol(&Sec, &RelA); - ErrorOr Ret = ELF->getSection(Symbol.second); + ErrorOr Ret = + ELF->getSection(Symbol.second, Symbol.first, ShndxTable); if (std::error_code EC = Ret.getError()) report_fatal_error(EC.message()); return *Ret; diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 8fab52e79dd..7feb6e038a7 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -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 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 getShndxTable() { return ShndxTable; } }; template T errorOrDefault(ErrorOr Val, T Default = T()) { @@ -368,6 +373,8 @@ std::string ELFDumper::getFullSymbolName(const Elf_Sym *Symbol, template static void getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, + const typename ELFO::Elf_Shdr *SymTab, + ArrayRef 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 Sec = Obj.getSection(SectionIndex); error(Sec.getError()); SectionName = errorOrDefault(Obj.getSectionName(*Sec)); @@ -897,6 +905,12 @@ ELFDumper::ELFDumper(const ELFFile *Obj, StreamWriter &Writer) reportError("Multilpe SHT_SYMTAB"); DotSymtabSec = &Sec; break; + case ELF::SHT_SYMTAB_SHNDX: { + ErrorOr> TableOrErr = Obj->getSHNDXTable(Sec); + error(TableOrErr.getError()); + ShndxTable = *TableOrErr; + break; + } } } } @@ -1009,11 +1023,12 @@ void ELFDumper::printSections() { StringRef StrTable = *StrTableOrErr; for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { - ErrorOr SymSec = Obj->getSection(&Sym); + ErrorOr 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::printRelocation(const Elf_Shdr *Sec, Elf_Rela Rel) { std::pair Sym = Obj->getRelocationSymbol(Sec, &Rel); if (Sym.second && Sym.second->getType() == ELF::STT_SECTION) { - ErrorOr Sec = Obj->getSection(Sym.second); + ErrorOr Sec = + Obj->getSection(Sym.second, Sym.first, ShndxTable); error(Sec.getError()); ErrorOr SecName = Obj->getSectionName(*Sec); if (SecName) @@ -1140,7 +1156,7 @@ void ELFDumper::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 @@ -1152,15 +1168,16 @@ void ELFDumper::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 -void ELFDumper::printSymbol(const Elf_Sym *Symbol, StringRef StrTable, - bool IsDynamic) { +void ELFDumper::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::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::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); diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index 214148d41b8..6aea437aba7 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -26,9 +26,10 @@ class ELFDumper { typedef typename object::ELFFile::Elf_Word Elf_Word; const object::ELFFile &Obj; + ArrayRef 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 ELFDumper::dump() { case ELF::SHT_SYMTAB: Symtab = &Sec; break; + case ELF::SHT_SYMTAB_SHNDX: { + ErrorOr> TableOrErr = Obj.getSHNDXTable(Sec); + if (std::error_code EC = TableOrErr.getError()) + return EC; + ShndxTable = *TableOrErr; + break; + } case ELF::SHT_RELA: { ErrorOr S = dumpRelaSection(&Sec); if (std::error_code EC = S.getError()) @@ -139,7 +147,8 @@ ErrorOr ELFDumper::dump() { } ELFYAML::Symbol S; - if (std::error_code EC = ELFDumper::dumpSymbol(&Sym, StrTable, S)) + if (std::error_code EC = + ELFDumper::dumpSymbol(&Sym, Symtab, StrTable, S)) return EC; switch (Sym.getBinding()) @@ -162,9 +171,9 @@ ErrorOr ELFDumper::dump() { } template -std::error_code ELFDumper::dumpSymbol(const Elf_Sym *Sym, - StringRef StrTable, - ELFYAML::Symbol &S) { +std::error_code +ELFDumper::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::dumpSymbol(const Elf_Sym *Sym, return EC; S.Name = NameOrErr.get(); - ErrorOr ShdrOrErr = Obj.getSection(Sym); + ErrorOr ShdrOrErr = Obj.getSection(Sym, SymTab, ShndxTable); if (std::error_code EC = ShdrOrErr.getError()) return EC; const Elf_Shdr *Shdr = *ShdrOrErr; -- 2.34.1