aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2023-09-11 11:08:58 -0700
committerGitHub <noreply@github.com>2023-09-11 11:08:58 -0700
commiteb81493e95c9f0e7feecd699758caa56b7d3514e (patch)
tree5a65de89e004eed486caeea9b0e8c38283bbbc6f /llvm/tools
parent76af6e77c0e5d8c444daa3aea07f381c07b17da7 (diff)
downloadllvm-eb81493e95c9f0e7feecd699758caa56b7d3514e.zip
llvm-eb81493e95c9f0e7feecd699758caa56b7d3514e.tar.gz
llvm-eb81493e95c9f0e7feecd699758caa56b7d3514e.tar.bz2
[llvm-readelf] Add --extra-sym-info (#65580)
GNU readelf introduced --extra-sym-info/-X to display the section name for --syms (https://sourceware.org/PR30684). Port the feature, which is currently llvm-readelf only. For STO_AARCH64_VARIANT_PCS/STO_RISCV_VARIANT_PCS, the Ndx and Name columns may not be aligned.
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-readobj/COFFDumper.cpp4
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp109
-rw-r--r--llvm/tools/llvm-readobj/MachODumper.cpp6
-rw-r--r--llvm/tools/llvm-readobj/ObjDumper.h10
-rw-r--r--llvm/tools/llvm-readobj/Opts.td2
-rw-r--r--llvm/tools/llvm-readobj/WasmDumper.cpp4
-rw-r--r--llvm/tools/llvm-readobj/XCOFFDumper.cpp4
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.cpp5
8 files changed, 95 insertions, 49 deletions
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 2c8b6e0..6e32a7e 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -110,7 +110,7 @@ public:
private:
StringRef getSymbolName(uint32_t Index);
- void printSymbols() override;
+ void printSymbols(bool ExtraSymInfo) override;
void printDynamicSymbols() override;
void printSymbol(const SymbolRef &Sym);
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,
@@ -1609,7 +1609,7 @@ void COFFDumper::printRelocation(const SectionRef &Section,
}
}
-void COFFDumper::printSymbols() {
+void COFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
ListScope Group(W, "Symbols");
for (const SymbolRef &Symbol : Obj->symbols())
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 4872d05..e3387d0 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -298,11 +298,13 @@ protected:
llvm::function_ref<void(const Elf_Relr &)> RelrFn);
virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
- bool NonVisibilityBitsUsed) const {};
+ bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const {};
virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable, bool IsDynamic,
- bool NonVisibilityBitsUsed) const = 0;
+ bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const = 0;
virtual void printMipsABIFlags() = 0;
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
@@ -406,7 +408,7 @@ protected:
std::string getStaticSymbolName(uint32_t Index) const;
StringRef getDynamicString(uint64_t Value) const;
- void printSymbolsHelper(bool IsDynamic) const;
+ void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const;
std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,
@@ -508,7 +510,8 @@ ELFDumper<ELFT>::getVersionTable(const Elf_Shdr &Sec, ArrayRef<Elf_Sym> *SymTab,
}
template <class ELFT>
-void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
+void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic,
+ bool ExtraSymInfo) const {
std::optional<StringRef> StrTable;
size_t Entries = 0;
Elf_Sym_Range Syms(nullptr, nullptr);
@@ -549,10 +552,10 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
this->getElfObject().getELFFile().end())
: DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));
- printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed);
+ printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo);
for (const Elf_Sym &Sym : Syms)
printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,
- NonVisibilityBitsUsed);
+ NonVisibilityBitsUsed, ExtraSymInfo);
}
template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
@@ -574,14 +577,16 @@ public:
void printGroupSections() override;
void printRelocations() override;
void printSectionHeaders() override;
- void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
+ void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+ bool ExtraSymInfo) override;
void printHashSymbols() override;
void printSectionDetails() override;
void printDependentLibs() override;
void printDynamicTable() override;
void printDynamicRelocations() override;
void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
- bool NonVisibilityBitsUsed) const override;
+ bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const override;
void printProgramHeaders(bool PrintProgramHeaders,
cl::boolOrDefault PrintSectionMapping) override;
void printVersionSymbolSection(const Elf_Shdr *Sec) override;
@@ -656,12 +661,14 @@ private:
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable, bool IsDynamic,
- bool NonVisibilityBitsUsed) const override;
+ bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const override;
void printDynamicRelocHeader(unsigned Type, StringRef Name,
const DynRegionInfo &Reg) override;
std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,
- DataRegion<Elf_Word> ShndxTable) const;
+ DataRegion<Elf_Word> ShndxTable,
+ bool ExtraSymInfo = false) const;
void printProgramHeaders() override;
void printSectionMapping() override;
void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
@@ -686,7 +693,8 @@ public:
void printGroupSections() override;
void printRelocations() override;
void printSectionHeaders() override;
- void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
+ void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+ bool ExtraSymInfo) override;
void printDependentLibs() override;
void printDynamicTable() override;
void printDynamicRelocations() override;
@@ -719,7 +727,8 @@ private:
void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable, bool IsDynamic,
- bool /*NonVisibilityBitsUsed*/) const override;
+ bool /*NonVisibilityBitsUsed*/,
+ bool /*ExtraSymInfo*/) const override;
void printProgramHeaders() override;
void printSectionMapping() override {}
void printStackSizeEntry(uint64_t Size,
@@ -3998,7 +4007,8 @@ template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {
template <class ELFT>
void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,
size_t Entries,
- bool NonVisibilityBitsUsed) const {
+ bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const {
StringRef Name;
if (Symtab)
Name = this->getPrintableSectionName(*Symtab);
@@ -4008,21 +4018,27 @@ void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,
OS << "\nSymbol table for image";
OS << " contains " << Entries << " entries:\n";
- if (ELFT::Is64Bits)
+ if (ELFT::Is64Bits) {
OS << " Num: Value Size Type Bind Vis";
- else
+ if (ExtraSymInfo)
+ OS << "+Other";
+ } else {
OS << " Num: Value Size Type Bind Vis";
+ if (ExtraSymInfo)
+ OS << "+Other";
+ }
- if (NonVisibilityBitsUsed)
- OS << " ";
- OS << " Ndx Name\n";
+ OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0));
+ if (ExtraSymInfo)
+ OS << "Ndx(SecName) Name [+ Version Info]\n";
+ else
+ OS << "Ndx Name\n";
}
template <class ELFT>
-std::string
-GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
- unsigned SymIndex,
- DataRegion<Elf_Word> ShndxTable) const {
+std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(
+ const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,
+ bool ExtraSymInfo) const {
unsigned SectionIndex = Symbol.st_shndx;
switch (SectionIndex) {
case ELF::SHN_UNDEF:
@@ -4041,7 +4057,8 @@ GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
this->reportUniqueWarning(IndexOrErr.takeError());
return "RSV[0xffff]";
}
- return to_string(format_decimal(*IndexOrErr, 3));
+ SectionIndex = *IndexOrErr;
+ break;
}
default:
// Find if:
@@ -4058,17 +4075,31 @@ GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
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));
+ break;
}
+
+ std::string Extra;
+ if (ExtraSymInfo) {
+ auto Sec = this->Obj.getSection(SectionIndex);
+ if (!Sec) {
+ this->reportUniqueWarning(Sec.takeError());
+ } else {
+ auto SecName = this->Obj.getSectionName(**Sec);
+ if (!SecName)
+ this->reportUniqueWarning(SecName.takeError());
+ else
+ Extra = Twine(" (" + *SecName + ")").str();
+ }
+ }
+ return to_string(format_decimal(SectionIndex, 3)) + Extra;
}
template <class ELFT>
void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable,
- bool IsDynamic,
- bool NonVisibilityBitsUsed) const {
+ bool IsDynamic, bool NonVisibilityBitsUsed,
+ bool ExtraSymInfo) const {
unsigned Bias = ELFT::Is64Bits ? 8 : 0;
Field Fields[8] = {0, 8, 17 + Bias, 23 + Bias,
31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};
@@ -4115,8 +4146,10 @@ void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
}
Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;
- Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex, ShndxTable);
+ Fields[6].Str =
+ getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo);
+ Fields[7].Column += ExtraSymInfo ? 10 : 0;
Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,
StrTable, IsDynamic);
for (const Field &Entry : Fields)
@@ -4162,13 +4195,14 @@ void GNUELFDumper<ELFT>::printHashedSymbol(const Elf_Sym *Symbol,
template <class ELFT>
void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols,
- bool PrintDynamicSymbols) {
+ bool PrintDynamicSymbols,
+ bool ExtraSymInfo) {
if (!PrintSymbols && !PrintDynamicSymbols)
return;
// GNU readelf prints both the .dynsym and .symtab with --symbols.
- this->printSymbolsHelper(true);
+ this->printSymbolsHelper(true, ExtraSymInfo);
if (PrintSymbols)
- this->printSymbolsHelper(false);
+ this->printSymbolsHelper(false, ExtraSymInfo);
}
template <class ELFT>
@@ -7011,7 +7045,8 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printSectionHeaders() {
this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));
if (SymSec == &Sec)
printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,
- false);
+ /*NonVisibilityBitsUsed=*/false,
+ /*ExtraSymInfo=*/false);
}
}
}
@@ -7098,7 +7133,8 @@ void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
DataRegion<Elf_Word> ShndxTable,
std::optional<StringRef> StrTable,
bool IsDynamic,
- bool /*NonVisibilityBitsUsed*/) const {
+ bool /*NonVisibilityBitsUsed*/,
+ bool /*ExtraSymInfo*/) const {
std::string FullSymbolName = this->getFullSymbolName(
Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);
unsigned char SymbolType = Symbol.getType();
@@ -7122,14 +7158,15 @@ void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
template <class ELFT>
void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols,
- bool PrintDynamicSymbols) {
+ bool PrintDynamicSymbols,
+ bool ExtraSymInfo) {
if (PrintSymbols) {
ListScope Group(W, "Symbols");
- this->printSymbolsHelper(false);
+ this->printSymbolsHelper(false, ExtraSymInfo);
}
if (PrintDynamicSymbols) {
ListScope Group(W, "DynamicSymbols");
- this->printSymbolsHelper(true);
+ this->printSymbolsHelper(true, ExtraSymInfo);
}
}
diff --git a/llvm/tools/llvm-readobj/MachODumper.cpp b/llvm/tools/llvm-readobj/MachODumper.cpp
index 5b38501..ce5ba46 100644
--- a/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -59,7 +59,7 @@ private:
StringRef getSymbolName(const SymbolRef &Symbol) const;
uint8_t getSymbolType(const SymbolRef &Symbol) const;
- void printSymbols() override;
+ void printSymbols(bool ExtraSymInfo) override;
void printSymbols(std::optional<SymbolComparator> SymComp) override;
void printDynamicSymbols() override;
void printDynamicSymbols(std::optional<SymbolComparator> SymComp) override;
@@ -632,7 +632,9 @@ bool MachODumper::compareSymbolsByType(SymbolRef LHS, SymbolRef RHS) const {
return getSymbolType(LHS) < getSymbolType(RHS);
}
-void MachODumper::printSymbols() { printSymbols(std::nullopt); }
+void MachODumper::printSymbols(bool /*ExtraSymInfo*/) {
+ printSymbols(std::nullopt);
+}
void MachODumper::printSymbols(std::optional<SymbolComparator> SymComp) {
ListScope Group(W, "Symbols");
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 921792f..a44fa42 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -77,13 +77,15 @@ public:
virtual void printFileHeaders() = 0;
virtual void printSectionHeaders() = 0;
virtual void printRelocations() = 0;
- virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) {
+ virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+ bool ExtraSymInfo) {
if (PrintSymbols)
- printSymbols();
+ printSymbols(ExtraSymInfo);
if (PrintDynamicSymbols)
printDynamicSymbols();
}
virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+ bool ExtraSymInfo,
std::optional<SymbolComparator> SymComp) {
if (SymComp) {
if (PrintSymbols)
@@ -91,7 +93,7 @@ public:
if (PrintDynamicSymbols)
printDynamicSymbols(SymComp);
} else {
- printSymbols(PrintSymbols, PrintDynamicSymbols);
+ printSymbols(PrintSymbols, PrintDynamicSymbols, ExtraSymInfo);
}
}
virtual void printProgramHeaders(bool PrintProgramHeaders,
@@ -187,7 +189,7 @@ protected:
ScopedPrinter &W;
private:
- virtual void printSymbols() {}
+ virtual void printSymbols(bool ExtraSymInfo) {}
virtual void printSymbols(std::optional<SymbolComparator> Comp) {}
virtual void printDynamicSymbols() {}
virtual void printDynamicSymbols(std::optional<SymbolComparator> Comp) {}
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index fec0adb..e2d93c6 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -25,6 +25,7 @@ def dependent_libraries : FF<"dependent-libraries", "Display the dependent libra
def dyn_relocations : FF<"dyn-relocations", "Display the dynamic relocation entries in the file">;
def dyn_syms : FF<"dyn-syms", "Display the dynamic symbol table">;
def expand_relocs : FF<"expand-relocs", "Expand each shown relocation to multiple lines">;
+def extra_sym_info : FF<"extra-sym-info", "Display extra information when showing symbols">;
def file_header : FF<"file-header", "Display file header">;
def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">;
defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"<name or index>">;
@@ -135,5 +136,6 @@ def : F<"S", "Alias for --section-headers">, Alias<section_headers>;
def : F<"s", "Alias for --symbols">, Alias<symbols>;
def : F<"t", "Alias for --section-details">, Alias<section_details>;
def : F<"u", "Alias for --unwind">, Alias<unwind>;
+def : F<"X", "Alias for --extra-sym-info">, Alias<extra_sym_info>, Group<grp_elf>;
def : F<"V", "Alias for --version-info">, Alias<version_info>, Group<grp_elf>;
def : JoinedOrSeparate<["-"], "x">, Alias<hex_dump_EQ>, HelpText<"Alias for --hex-dump">, MetaVarName<"<name or index>">;
diff --git a/llvm/tools/llvm-readobj/WasmDumper.cpp b/llvm/tools/llvm-readobj/WasmDumper.cpp
index e6f0ac7..5d7639b0 100644
--- a/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -70,7 +70,7 @@ protected:
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
private:
- void printSymbols() override;
+ void printSymbols(bool ExtraSymInfo) override;
void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
const WasmObjectFile *Obj;
@@ -144,7 +144,7 @@ void WasmDumper::printRelocations() {
}
}
-void WasmDumper::printSymbols() {
+void WasmDumper::printSymbols(bool /*ExtraSymInfo*/) {
ListScope Group(W, "Symbols");
for (const SymbolRef &Symbol : Obj->symbols())
diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 74ebcc4..8ebd670 100644
--- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -33,7 +33,7 @@ public:
void printAuxiliaryHeader() override;
void printSectionHeaders() override;
void printRelocations() override;
- void printSymbols() override;
+ void printSymbols(bool ExtraSymInfo) override;
void printDynamicSymbols() override;
void printUnwindInfo() override;
void printStackMap() const override;
@@ -903,7 +903,7 @@ void XCOFFDumper::printSymbol(const SymbolRef &S) {
}
}
-void XCOFFDumper::printSymbols() {
+void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
ListScope Group(W, "Symbols");
for (const SymbolRef &S : Obj.symbols())
printSymbol(S);
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 8a10df4..ca633ce 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -102,6 +102,7 @@ bool Demangle;
static bool DependentLibraries;
static bool DynRelocs;
static bool DynamicSymbols;
+static bool ExtraSymInfo;
static bool FileHeaders;
static bool Headers;
static std::vector<std::string> HexDump;
@@ -217,6 +218,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
+ opts::ExtraSymInfo = Args.hasArg(OPT_extra_sym_info);
opts::FileHeaders = Args.hasArg(OPT_file_header);
opts::Headers = Args.hasArg(OPT_headers);
opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
@@ -435,7 +437,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
if (opts::UnwindInfo)
Dumper->printUnwindInfo();
if (opts::Symbols || opts::DynamicSymbols)
- Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols, SymComp);
+ Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols,
+ opts::ExtraSymInfo, SymComp);
if (!opts::StringDump.empty())
Dumper->printSectionsAsString(Obj, opts::StringDump);
if (!opts::HexDump.empty())