[llvm] r263952 - [llvm-readobj] Impl GNU style symbols printing
Hemant Kulkarni via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 21 10:18:23 PDT 2016
Author: khemant
Date: Mon Mar 21 12:18:23 2016
New Revision: 263952
URL: http://llvm.org/viewvc/llvm-project?rev=263952&view=rev
Log:
[llvm-readobj] Impl GNU style symbols printing
Implements "readelf -sW and readelf -DsW"
Differential Revision: http://reviews.llvm.org/D18224
Added:
llvm/trunk/test/tools/llvm-readobj/Inputs/symbols-proc-specific.elf-hexagon
llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test
Modified:
llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
Added: llvm/trunk/test/tools/llvm-readobj/Inputs/symbols-proc-specific.elf-hexagon
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/symbols-proc-specific.elf-hexagon?rev=263952&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/symbols-proc-specific.elf-hexagon (added) and llvm/trunk/test/tools/llvm-readobj/Inputs/symbols-proc-specific.elf-hexagon Mon Mar 21 12:18:23 2016 differ
Added: llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test?rev=263952&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test Mon Mar 21 12:18:23 2016
@@ -0,0 +1,46 @@
+RUN: llvm-readobj -symbols %p/Inputs/symbols-proc-specific.elf-hexagon \
+RUN: --elf-output-style=GNU | FileCheck %s -check-prefix ELF32
+RUN: llvm-readobj -symbols %p/Inputs/relocs.obj.elf-x86_64 --elf-output-style=GNU \
+RUN: | FileCheck %s -check-prefix ELF64
+RUN: llvm-readobj -symbols %p/Inputs/gnuhash.so.elf-x86_64 --elf-output-style=GNU \
+RUN: | FileCheck %s -check-prefix DYN
+
+ELF32: Symbol table '.symtab' contains 5 entries:
+ELF32-NEXT: Num: Value Size Type Bind Vis Ndx Name
+ELF32-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ELF32-NEXT: 1: 00000000 0 FILE LOCAL DEFAULT ABS a.c
+ELF32-NEXT: 2: 00000000 20 FUNC GLOBAL DEFAULT 2 main
+ELF32-NEXT: 3: 00000004 4 OBJECT GLOBAL DEFAULT PRC[0xff03] x
+ELF32-NEXT: 4: 00000000 4 OBJECT GLOBAL DEFAULT 3 y
+
+ELF64: Symbol table '.symtab' contains 6 entries:
+ELF64-NEXT: Num: Value Size Type Bind Vis Ndx Name
+ELF64-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+ELF64-NEXT: 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
+ELF64-NEXT: 2: 0000000000000000 0 SECTION LOCAL DEFAULT 3
+ELF64-NEXT: 3: 0000000000000000 0 SECTION LOCAL DEFAULT 4
+ELF64-NEXT: 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
+ELF64-NEXT: 5: 0000000000000000 0 TLS GLOBAL DEFAULT UND sym
+
+DYN:Symbol table '.dynsym' contains 5 entries:
+DYN-NEXT: Num: Value Size Type Bind Vis Ndx Name
+DYN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+DYN-NEXT: 1: 00000000000001b8 0 NOTYPE GLOBAL DEFAULT 4 foo
+DYN-NEXT: 2: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _edata
+DYN-NEXT: 3: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _end
+DYN-NEXT: 4: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 __bss_start
+
+DYN: Symbol table '.symtab' contains 12 entries:
+DYN-NEXT: Num: Value Size Type Bind Vis Ndx Name
+DYN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+DYN-NEXT: 1: 00000000000000e8 0 SECTION LOCAL DEFAULT 1
+DYN-NEXT: 2: 0000000000000120 0 SECTION LOCAL DEFAULT 2
+DYN-NEXT: 3: 0000000000000198 0 SECTION LOCAL DEFAULT 3
+DYN-NEXT: 4: 00000000000001b8 0 SECTION LOCAL DEFAULT 4
+DYN-NEXT: 5: 00000000002001b8 0 SECTION LOCAL DEFAULT 5
+DYN-NEXT: 6: 00000000002001b8 0 OBJECT LOCAL DEFAULT 5 _DYNAMIC
+DYN-NEXT: 7: 0000000000200268 0 OBJECT LOCAL DEFAULT 5 _GLOBAL_OFFSET_TABLE_
+DYN-NEXT: 8: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 __bss_start
+DYN-NEXT: 9: 00000000000001b8 0 NOTYPE GLOBAL DEFAULT 4 foo
+DYN-NEXT: 10: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _edata
+DYN-NEXT: 11: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _end
Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=263952&r1=263951&r2=263952&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Mon Mar 21 12:18:23 2016
@@ -159,9 +159,6 @@ private:
void parseDynamicTable(ArrayRef<const Elf_Phdr *> LoadSegments);
- void printSymbol(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
- StringRef StrTable, bool IsDynamic);
-
void printValue(uint64_t Type, uint64_t Value);
StringRef getDynamicString(uint64_t Offset) const;
@@ -182,6 +179,7 @@ private:
const Elf_Hash *HashTable = nullptr;
const Elf_GnuHash *GnuHashTable = nullptr;
const Elf_Shdr *DotSymtabSec = nullptr;
+ StringRef DynSymtabName;
ArrayRef<Elf_Word> ShndxTable;
const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version
@@ -224,6 +222,8 @@ public:
Elf_Rela_Range dyn_relas() const;
std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
bool IsDynamic) const;
+
+ void printSymbolsHelper(bool IsDynamic) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; }
StringRef getDynamicStringTable() const { return DynamicStringTable; }
@@ -232,19 +232,54 @@ public:
const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; }
};
+template <class ELFT>
+void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
+ StringRef StrTable, SymtabName;
+ size_t Entries = 0;
+ Elf_Sym_Range Syms(nullptr, nullptr);
+ if (IsDynamic) {
+ StrTable = DynamicStringTable;
+ Syms = dynamic_symbols();
+ SymtabName = DynSymtabName;
+ if (DynSymRegion.Addr)
+ Entries = DynSymRegion.Size / DynSymRegion.EntSize;
+ } else {
+ if (!DotSymtabSec)
+ return;
+ StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
+ Syms = Obj->symbols(DotSymtabSec);
+ SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec));
+ Entries = DotSymtabSec->getEntityCount();
+ }
+ if (Syms.begin() == Syms.end())
+ return;
+ ELFDumperStyle->printSymtabMessage(Obj, SymtabName, Entries);
+ for (const auto &Sym : Syms)
+ ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
+}
+
template <typename ELFT> class DumpStyle {
public:
- virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0;
- virtual ~DumpStyle() { }
+ using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr;
+ using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym;
+
DumpStyle(ELFDumper<ELFT> *Dumper) : Dumper(Dumper) {}
+ virtual ~DumpStyle() {}
+ virtual void printFileHeaders(const ELFFile<ELFT> *Obj) = 0;
virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0;
virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0;
virtual void printSections(const ELFFile<ELFT> *Obj) = 0;
virtual void printSymbols(const ELFFile<ELFT> *Obj) = 0;
virtual void printDynamicSymbols(const ELFFile<ELFT> *Obj) = 0;
virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printSymtabMessage(const ELFFile<ELFT> *obj, StringRef Name,
+ size_t Offset) {
+ return;
+ }
+ virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol,
+ const Elf_Sym *FirstSym, StringRef StrTable,
+ bool IsDynamic) = 0;
const ELFDumper<ELFT> *dumper() const { return Dumper; }
-
private:
const ELFDumper<ELFT> *Dumper;
};
@@ -262,6 +297,8 @@ public:
void printSymbols(const ELFO *Obj) override;
void printDynamicSymbols(const ELFO *Obj) override;
void printDynamicRelocations(const ELFO *Obj) override;
+ virtual void printSymtabMessage(const ELFO *Obj, StringRef Name,
+ size_t Offset) override;
private:
struct Field {
@@ -278,6 +315,7 @@ private:
return EnumItem.AltName;
return to_hexString(Value, false);
}
+
formatted_raw_ostream &printField(struct Field F) {
if (F.Column != 0)
OS.PadToColumn(F.Column);
@@ -287,6 +325,10 @@ private:
}
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,
+ StringRef StrTable, bool IsDynamic) override;
+ std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
+ const Elf_Sym *FirstSym);
};
template <typename ELFT> class LLVMStyle : public DumpStyle<ELFT> {
@@ -300,17 +342,15 @@ public:
void printRelocations(const ELFO *Obj) override;
void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj);
void printSections(const ELFO *Obj) override;
- void printSymbolsHelper(const ELFO *Obj, bool IsDynamic);
void printSymbols(const ELFO *Obj) override;
void printDynamicSymbols(const ELFO *Obj) override;
void printDynamicRelocations(const ELFO *Obj) override;
private:
void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
- void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
- StringRef StrTable, bool IsDynamic);
void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel);
-
+ void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
+ StringRef StrTable, bool IsDynamic) override;
StreamWriter &W;
};
@@ -840,15 +880,21 @@ static const EnumEntry<unsigned> ElfSymb
{"Weak", "WEAK", ELF::STB_WEAK},
{"Unique", "UNIQUE", ELF::STB_GNU_UNIQUE}};
+static const EnumEntry<unsigned> ElfSymbolVisibilities[] = {
+ {"DEFAULT", "DEFAULT", ELF::STV_DEFAULT},
+ {"INTERNAL", "INTERNAL", ELF::STV_INTERNAL},
+ {"HIDDEN", "HIDDEN", ELF::STV_HIDDEN},
+ {"PROTECTED", "PROTECTED", ELF::STV_PROTECTED}};
+
static const EnumEntry<unsigned> ElfSymbolTypes[] = {
- {"None", "NOTYPE", ELF::STT_NOTYPE},
- {"Object", "OBJECT", ELF::STT_OBJECT},
- {"Function", "FUNCTION", ELF::STT_FUNC},
- {"Section", "SECTION", ELF::STT_SECTION},
- {"File", "FILE", ELF::STT_FILE},
- {"Common", "COMMON", ELF::STT_COMMON},
- {"TLS", "TLS", ELF::STT_TLS},
- {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}};
+ {"None", "NOTYPE", ELF::STT_NOTYPE},
+ {"Object", "OBJECT", ELF::STT_OBJECT},
+ {"Function", "FUNC", ELF::STT_FUNC},
+ {"Section", "SECTION", ELF::STT_SECTION},
+ {"File", "FILE", ELF::STT_FILE},
+ {"Common", "COMMON", ELF::STT_COMMON},
+ {"TLS", "TLS", ELF::STT_TLS},
+ {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}};
static const EnumEntry<unsigned> AMDGPUSymbolTypes[] = {
{ "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL },
@@ -1108,6 +1154,8 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
if (DynSymRegion.Size)
reportError("Multilpe SHT_DYNSYM");
DynSymRegion = createDRIFrom(&Sec);
+ // This is only used (if Elf_Shdr present)for naming section in GNU style
+ DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec));
break;
case ELF::SHT_SYMTAB_SHNDX:
ShndxTable = unwrapOrError(Obj->getSHNDXTable(Sec));
@@ -2468,13 +2516,117 @@ template <class ELFT> void GNUStyle<ELFT
p (processor specific)\n";
}
+template <class ELFT>
+void GNUStyle<ELFT>::printSymtabMessage(const ELFO *Obj, StringRef Name,
+ size_t Entries) {
+ if (Name.size())
+ OS << "\nSymbol table '" << Name << "' contains " << Entries
+ << " entries:\n";
+ else
+ OS << "\n Symbol table for image:\n";
+
+ if (ELFT::Is64Bits)
+ OS << " Num: Value Size Type Bind Vis Ndx Name\n";
+ else
+ OS << " Num: Value Size Type Bind Vis Ndx Name\n";
+}
+
+template <class ELFT>
+std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj,
+ const Elf_Sym *Symbol,
+ const Elf_Sym *FirstSym) {
+ unsigned SectionIndex = Symbol->st_shndx;
+ switch (SectionIndex) {
+ case ELF::SHN_UNDEF:
+ return "UND";
+ case ELF::SHN_ABS:
+ return "ABS";
+ case ELF::SHN_COMMON:
+ return "COM";
+ case ELF::SHN_XINDEX:
+ SectionIndex = Obj->getExtendedSymbolTableIndex(
+ Symbol, FirstSym, this->dumper()->getShndxTable());
+ default:
+ // Find if:
+ // Processor specific
+ if (SectionIndex >= ELF::SHN_LOPROC && SectionIndex <= ELF::SHN_HIPROC)
+ return std::string("PRC[0x") +
+ to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
+ // OS specific
+ if (SectionIndex >= ELF::SHN_LOOS && SectionIndex <= ELF::SHN_HIOS)
+ return std::string("OS[0x") +
+ to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
+ // Architecture reserved:
+ if (SectionIndex >= ELF::SHN_LORESERVE &&
+ SectionIndex <= ELF::SHN_HIRESERVE)
+ return std::string("RSV[0x") +
+ to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
+ // A normal section with an index
+ return to_string(format_decimal(SectionIndex, 3));
+ }
+}
+
+template <class ELFT>
+void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol,
+ const Elf_Sym *FirstSym, StringRef StrTable,
+ bool IsDynamic) {
+ static int Idx = 0;
+ static bool Dynamic = true;
+ size_t Width;
+
+ // If this function was called with a different value from IsDynamic
+ // from last call, happens when we move from dynamic to static symbol
+ // table, "Num" field should be reset.
+ if (!Dynamic != !IsDynamic) {
+ Idx = 0;
+ Dynamic = false;
+ }
+ std::string Num, Name, Value, Size, Binding, Type, Visibility, Section;
+ unsigned Bias = 0;
+ if (ELFT::Is64Bits) {
+ Bias = 8;
+ Width = 16;
+ } else {
+ Bias = 0;
+ Width = 8;
+ }
+ Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,
+ 31 + Bias, 38 + Bias, 47 + Bias, 51 + Bias};
+ Num = to_string(format_decimal(Idx++, 6)) + ":";
+ 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, IsDynamic);
+ Fields[0].Str = Num;
+ Fields[1].Str = Value;
+ Fields[2].Str = Size;
+ Fields[3].Str = Type;
+ Fields[4].Str = Binding;
+ Fields[5].Str = Visibility;
+ Fields[6].Str = Section;
+ Fields[7].Str = Name;
+ for (auto &Entry : Fields)
+ printField(Entry);
+ OS << "\n";
+}
+
template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) {
- OS << "GNU style symbols not implemented!\n";
+ this->dumper()->printSymbolsHelper(true);
+ this->dumper()->printSymbolsHelper(false);
}
template <class ELFT>
void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
- OS << "GNU style dynamic symbols not implemented!\n";
+ this->dumper()->printSymbolsHelper(true);
}
template <class ELFT>
@@ -2735,33 +2887,15 @@ void LLVMStyle<ELFT>::printSymbol(const
W.printHex("Section", SectionName, SectionIndex);
}
-template <class ELFT>
-void LLVMStyle<ELFT>::printSymbolsHelper(const ELFO *Obj, bool IsDynamic) {
- StringRef StrTable;
- typename ELFO::Elf_Sym_Range Syms(nullptr, nullptr);
- if (IsDynamic) {
- StrTable = this->dumper()->getDynamicStringTable();
- Syms = this->dumper()->dynamic_symbols();
- } else {
- if (!this->dumper()->getDotSymtabSec())
- return;
- const auto DotSymtabSec = this->dumper()->getDotSymtabSec();
- StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
- Syms = Obj->symbols(DotSymtabSec);
- }
- for (const Elf_Sym &Sym : Syms)
- printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
-}
-
template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) {
ListScope Group(W, "Symbols");
- printSymbolsHelper(Obj, false);
+ this->dumper()->printSymbolsHelper(false);
}
template <class ELFT>
void LLVMStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
ListScope Group(W, "DynamicSymbols");
- printSymbolsHelper(Obj, true);
+ this->dumper()->printSymbolsHelper(true);
}
template <class ELFT>
More information about the llvm-commits
mailing list