diff options
| -rw-r--r-- | llvm/include/llvm/Object/ELF.h | 70 | ||||
| -rw-r--r-- | llvm/include/llvm/Object/ELFObjectFile.h | 24 | ||||
| -rw-r--r-- | llvm/tools/llvm-readobj/ARMEHABIPrinter.h | 5 | ||||
| -rw-r--r-- | llvm/tools/llvm-readobj/ELFDumper.cpp | 43 | ||||
| -rw-r--r-- | llvm/tools/obj2yaml/elf2yaml.cpp | 23 |
5 files changed, 103 insertions, 62 deletions
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index 833f4a7ba86..9750d3be175 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/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<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) { @@ -485,6 +466,21 @@ ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { } 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) diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index d345c96a404..3a9739afbeb 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/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<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; + } } } } diff --git a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h index 85b2f2906ca..39bcdaae651 100644 --- a/llvm/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/llvm/tools/llvm-readobj/ARMEHABIPrinter.h @@ -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; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 8fab52e79dd..7feb6e038a7 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/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<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); diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp index 214148d41b8..6aea437aba7 100644 --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -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; |

