summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-readobj/ELFDumper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-readobj/ELFDumper.cpp')
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp109
1 files changed, 108 insertions, 1 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 0fdf3919470..5d7f92212ad 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -328,6 +328,8 @@ private:
OS.flush();
return OS;
}
+ void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym,
+ StringRef StrTable, uint32_t Bucket);
void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
@@ -2812,15 +2814,120 @@ void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
printField(Entry);
OS << "\n";
}
+template <class ELFT>
+void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym,
+ uint32_t Sym, StringRef StrTable,
+ uint32_t Bucket) {
+ std::string Num, Buc, Name, Value, Size, Binding, Type, Visibility, Section;
+ unsigned Width, Bias = 0;
+ if (ELFT::Is64Bits) {
+ Bias = 8;
+ Width = 16;
+ } else {
+ Bias = 0;
+ Width = 8;
+ }
+ Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias,
+ 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};
+ Num = to_string(format_decimal(Sym, 5));
+ Buc = to_string(format_decimal(Bucket, 3)) + ":";
+
+ const auto Symbol = FirstSym + Sym;
+ Value = to_string(format_hex_no_prefix(Symbol->st_value, Width));
+ Size = to_string(format_decimal(Symbol->st_size, 5));
+ unsigned char SymbolType = Symbol->getType();
+ if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
+ SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
+ Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
+ else
+ Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes));
+ unsigned Vis = Symbol->getVisibility();
+ Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
+ Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities));
+ Section = getSymbolSectionNdx(Obj, Symbol, FirstSym);
+ Name = this->dumper()->getFullSymbolName(Symbol, StrTable, true);
+ Fields[0].Str = Num;
+ Fields[1].Str = Buc;
+ Fields[2].Str = Value;
+ Fields[3].Str = Size;
+ Fields[4].Str = Type;
+ Fields[5].Str = Binding;
+ Fields[6].Str = Visibility;
+ Fields[7].Str = Section;
+ Fields[8].Str = Name;
+ for (auto &Entry : Fields)
+ printField(Entry);
+ OS << "\n";
+}
template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) {
+ if (opts::DynamicSymbols)
+ return;
this->dumper()->printSymbolsHelper(true);
this->dumper()->printSymbolsHelper(false);
}
template <class ELFT>
void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
- this->dumper()->printSymbolsHelper(true);
+ if (this->dumper()->getDynamicStringTable().size() == 0)
+ return;
+ auto StringTable = this->dumper()->getDynamicStringTable();
+ auto DynSyms = this->dumper()->dynamic_symbols();
+ auto GnuHash = this->dumper()->getGnuHashTable();
+ auto SysVHash = this->dumper()->getHashTable();
+
+ // If no hash or .gnu.hash found, try using symbol table
+ if (GnuHash == nullptr && SysVHash == nullptr)
+ this->dumper()->printSymbolsHelper(true);
+
+ // Try printing .hash
+ if (this->dumper()->getHashTable()) {
+ OS << "\n Symbol table of .hash for image:\n";
+ if (ELFT::Is64Bits)
+ OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
+ else
+ OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
+ OS << "\n";
+
+ uint32_t NBuckets = SysVHash->nbucket;
+ uint32_t NChains = SysVHash->nchain;
+ auto Buckets = SysVHash->buckets();
+ auto Chains = SysVHash->chains();
+ for (uint32_t Buc = 0; Buc < NBuckets; Buc++) {
+ if (Buckets[Buc] == ELF::STN_UNDEF)
+ continue;
+ for (uint32_t Ch = Buckets[Buc]; Ch < NChains; Ch = Chains[Ch]) {
+ if (Ch == ELF::STN_UNDEF)
+ break;
+ printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc);
+ }
+ }
+ }
+
+ // Try printing .gnu.hash
+ if (GnuHash) {
+ OS << "\n Symbol table of .gnu.hash for image:\n";
+ if (ELFT::Is64Bits)
+ OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
+ else
+ OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
+ OS << "\n";
+ uint32_t NBuckets = GnuHash->nbuckets;
+ auto Buckets = GnuHash->buckets();
+ for (uint32_t Buc = 0; Buc < NBuckets; Buc++) {
+ if (Buckets[Buc] == ELF::STN_UNDEF)
+ continue;
+ uint32_t Index = Buckets[Buc];
+ uint32_t GnuHashable = Index - GnuHash->symndx;
+ // Print whole chain
+ while (true) {
+ printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc);
+ // Chain ends at symbol with stopper bit
+ if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
+ break;
+ }
+ }
+ }
}
static inline std::string printPhdrFlags(unsigned Flag) {
OpenPOWER on IntegriCloud