void printNeededLibraries() override;
void printProgramHeaders() override;
void printHashTable() override;
+ void printGnuHashTable() override;
void printLoadName() override;
void printAttributes() override;
typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range;
typedef typename ELFO::Elf_Phdr Elf_Phdr;
typedef typename ELFO::Elf_Hash Elf_Hash;
+ typedef typename ELFO::Elf_GnuHash Elf_GnuHash;
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;
uintX_t EntSize;
};
- void printSymbol(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic);
+ void printSymbolsHelper(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);
+ void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab);
void printValue(uint64_t Type, uint64_t Value);
const Elf_Rela *dyn_rela_begin() const;
const Elf_Sym *DynSymStart = nullptr;
StringRef SOName;
const Elf_Hash *HashTable = nullptr;
+ const Elf_GnuHash *GnuHashTable = 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
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()) {
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())
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));
HashTable =
reinterpret_cast<const Elf_Hash *>(toMappedAddr(Dyn.getPtr()));
break;
+ case ELF::DT_GNU_HASH:
+ GnuHashTable =
+ reinterpret_cast<const Elf_GnuHash *>(toMappedAddr(Dyn.getPtr()));
+ break;
case ELF::DT_RELA:
DynRelaRegion.Addr = toMappedAddr(Dyn.getPtr());
break;
reportError("Multilpe SHT_GNU_verneed");
dot_gnu_version_r_sec = &Sec;
break;
+ case ELF::SHT_DYNSYM:
+ if (DotDynSymSec != nullptr)
+ reportError("Multilpe SHT_DYNSYM");
+ DotDynSymSec = &Sec;
+ break;
+ case ELF::SHT_SYMTAB:
+ if (DotSymtabSec != nullptr)
+ 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;
+ }
}
}
}
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
- const Elf_Shdr *Symtab = Obj->getDotSymtabSec();
+ const Elf_Shdr *Symtab = DotSymtabSec;
ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
error(StrTableOrErr.getError());
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);
}
}
template <class ELFT>
void ELFDumper<ELFT>::printRelocations(const Elf_Shdr *Sec) {
+ ErrorOr<const Elf_Shdr *> SymTabOrErr = Obj->getSection(Sec->sh_link);
+ error(SymTabOrErr.getError());
+ const Elf_Shdr *SymTab = *SymTabOrErr;
+
switch (Sec->sh_type) {
case ELF::SHT_REL:
for (const Elf_Rel &R : Obj->rels(Sec)) {
Rela.r_offset = R.r_offset;
Rela.r_info = R.r_info;
Rela.r_addend = 0;
- printRelocation(Sec, Rela);
+ printRelocation(Rela, SymTab);
}
break;
case ELF::SHT_RELA:
for (const Elf_Rela &R : Obj->relas(Sec))
- printRelocation(Sec, R);
+ printRelocation(R, SymTab);
break;
}
}
template <class ELFT>
-void ELFDumper<ELFT>::printRelocation(const Elf_Shdr *Sec, Elf_Rela Rel) {
+void ELFDumper<ELFT>::printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab) {
SmallString<32> RelocName;
Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
StringRef TargetName;
- 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);
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab);
+ if (Sym && Sym->getType() == ELF::STT_SECTION) {
+ ErrorOr<const Elf_Shdr *> Sec = Obj->getSection(Sym, SymTab, ShndxTable);
error(Sec.getError());
ErrorOr<StringRef> SecName = Obj->getSectionName(*Sec);
if (SecName)
TargetName = SecName.get();
- } else if (Sym.first) {
- const Elf_Shdr *SymTable = Sym.first;
- ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*SymTable);
+ } else if (Sym) {
+ ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*SymTab);
error(StrTableOrErr.getError());
- TargetName = errorOrDefault(Sym.second->getName(*StrTableOrErr));
+ TargetName = errorOrDefault(Sym->getName(*StrTableOrErr));
}
if (opts::ExpandRelocs) {
}
template<class ELFT>
-void ELFDumper<ELFT>::printSymbols() {
- ListScope Group(W, "Symbols");
-
- const Elf_Shdr *Symtab = Obj->getDotSymtabSec();
+void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) {
+ const Elf_Shdr *Symtab = (IsDynamic) ? DotDynSymSec : DotSymtabSec;
+ if (!Symtab)
+ return;
ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
error(StrTableOrErr.getError());
StringRef StrTable = *StrTableOrErr;
for (const Elf_Sym &Sym : Obj->symbols(Symtab))
- printSymbol(&Sym, StrTable, false);
+ printSymbol(&Sym, Symtab, StrTable, IsDynamic);
+}
+
+template<class ELFT>
+void ELFDumper<ELFT>::printSymbols() {
+ ListScope Group(W, "Symbols");
+ printSymbolsHelper(false);
}
template<class ELFT>
void ELFDumper<ELFT>::printDynamicSymbols() {
ListScope Group(W, "DynamicSymbols");
-
- const Elf_Shdr *Symtab = Obj->getDotDynSymSec();
- ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(*Symtab);
- error(StrTableOrErr.getError());
- StringRef StrTable = *StrTableOrErr;
- for (const Elf_Sym &Sym : Obj->symbols(Symtab))
- printSymbol(&Sym, StrTable, true);
+ printSymbolsHelper(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();
LLVM_READOBJ_TYPE_CASE(SYMENT);
LLVM_READOBJ_TYPE_CASE(SYMTAB);
LLVM_READOBJ_TYPE_CASE(TEXTREL);
+ LLVM_READOBJ_TYPE_CASE(VERDEF);
+ LLVM_READOBJ_TYPE_CASE(VERDEFNUM);
LLVM_READOBJ_TYPE_CASE(VERNEED);
LLVM_READOBJ_TYPE_CASE(VERNEEDNUM);
LLVM_READOBJ_TYPE_CASE(VERSYM);
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
case DT_DEBUG:
+ case DT_VERDEF:
case DT_VERNEED:
case DT_VERSYM:
case DT_GNU_HASH:
OS << format("0x%" PRIX64, Value);
break;
case DT_RELCOUNT:
+ case DT_VERDEFNUM:
case DT_VERNEEDNUM:
case DT_MIPS_RLD_VERSION:
case DT_MIPS_LOCAL_GOTNO:
template <> void ELFDumper<ELFType<support::little, false>>::printUnwindInfo() {
const unsigned Machine = Obj->getHeader()->e_machine;
if (Machine == EM_ARM) {
- ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(W, Obj);
+ ARM::EHABI::PrinterContext<ELFType<support::little, false>> Ctx(
+ W, Obj, DotSymtabSec);
return Ctx.PrintUnwindInformation();
}
W.startLine() << "UnwindInfo not implemented.\n";
<< " " << "Name/Value\n";
while (I != E) {
const Elf_Dyn &Entry = *I;
+ uintX_t Tag = Entry.getTag();
++I;
- W.startLine()
- << " "
- << format(Is64 ? "0x%016" PRIX64 : "0x%08" PRIX64, Entry.getTag())
- << " " << format("%-21s", getTypeString(Entry.getTag()));
- printValue(Entry.getTag(), Entry.getVal());
+ W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, true) << " "
+ << format("%-21s", getTypeString(Tag));
+ printValue(Tag, Entry.getVal());
OS << "\n";
}
W.printList("Chains", HashTable->chains());
}
+template <typename ELFT>
+void ELFDumper<ELFT>::printGnuHashTable() {
+ DictScope D(W, "GnuHashTable");
+ if (!GnuHashTable)
+ return;
+ W.printNumber("Num Buckets", GnuHashTable->nbuckets);
+ W.printNumber("First Hashed Symbol Index", GnuHashTable->symndx);
+ W.printNumber("Num Mask Words", GnuHashTable->maskwords);
+ W.printNumber("Shift Count", GnuHashTable->shift2);
+ W.printHexList("Bloom Filter", GnuHashTable->filter());
+ W.printList("Buckets", GnuHashTable->buckets());
+ if (!DotDynSymSec)
+ reportError("No dynamic symbol section");
+ W.printHexList("Values",
+ GnuHashTable->values(DotDynSymSec->getEntityCount()));
+}
+
template <typename ELFT> void ELFDumper<ELFT>::printLoadName() {
outs() << "LoadName: " << SOName << '\n';
}
return;
}
- const Elf_Shdr *DynSymSec = Obj->getDotDynSymSec();
+ const Elf_Shdr *DynSymSec = Dumper->getDotDynSymSec();
ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*DynSymSec);
error(StrTable.getError());
const Elf_Sym *DynSymBegin = Obj->symbol_begin(DynSymSec);
ErrorOr<const Elf_Shdr *> SymTableOrErr =
Obj->getSection(PLTRelShdr->sh_link);
error(SymTableOrErr.getError());
- ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(**SymTableOrErr);
+ const Elf_Shdr *SymTable = *SymTableOrErr;
+ ErrorOr<StringRef> StrTable = Obj->getStringTableForSymtab(*SymTable);
error(StrTable.getError());
const GOTEntry *PLTBegin = makeGOTIter(*PLT, 0);
for (const Elf_Rel *RI = Obj->rel_begin(PLTRelShdr),
*RE = Obj->rel_end(PLTRelShdr);
RI != RE && It != PLTEnd; ++RI, ++It) {
- const Elf_Sym *Sym =
- Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable);
printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym);
}
break;
for (const Elf_Rela *RI = Obj->rela_begin(PLTRelShdr),
*RE = Obj->rela_end(PLTRelShdr);
RI != RE && It != PLTEnd; ++RI, ++It) {
- const Elf_Sym *Sym =
- Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
+ const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable);
printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, *StrTable, Sym);
}
break;
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 =
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);