mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-04 08:27:50 +00:00
[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.
This commit is contained in:
parent
76af6e77c0
commit
eb81493e95
@ -77,6 +77,10 @@ OPTIONS
|
||||
``GNU`` (the default) output mimics the equivalent GNU :program:`readelf`
|
||||
output. ``JSON`` is JSON formatted output intended for machine consumption.
|
||||
|
||||
.. option:: --extra-sym-info
|
||||
|
||||
Display extra information (section name) when showing symbols.
|
||||
|
||||
.. option:: --section-groups, -g
|
||||
|
||||
Display section groups.
|
||||
|
@ -166,6 +166,8 @@ Changes to the LLVM tools
|
||||
|
||||
* llvm-symbolizer now treats invalid input as an address for which source
|
||||
information is not found.
|
||||
* llvm-readelf now supports ``--extra-sym-info`` (``-X``) to display extra
|
||||
information (section name) when showing symbols.
|
||||
|
||||
Changes to LLDB
|
||||
---------------------------------
|
||||
|
@ -4,6 +4,7 @@
|
||||
# RUN: llvm-readobj --symbols %t.o | FileCheck %s --check-prefix=LLVM
|
||||
# RUN: llvm-readobj --symbols %t.o --elf-output-style=JSON --pretty-print | FileCheck %s --check-prefix=JSON
|
||||
# RUN: llvm-readelf --symbols %t.o | FileCheck %s --check-prefix=GNU
|
||||
# RUN: llvm-readelf --symbols --extra-sym-info %t.o | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=GNUX
|
||||
|
||||
# LLVM: Name: foo1
|
||||
# LLVM: Other [ (0x80)
|
||||
@ -29,6 +30,14 @@
|
||||
# GNU-NEXT: 3: 0000000000000000 0 NOTYPE LOCAL PROTECTED [VARIANT_PCS] UND foo3
|
||||
# GNU-NEXT: 4: 0000000000000000 0 NOTYPE LOCAL PROTECTED UND foo4
|
||||
|
||||
# GNUX:Symbol table '.symtab' contains 5 entries:
|
||||
# GNUX-NEXT: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
# GNUX-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# GNUX-NEXT: 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_PCS] UND foo1
|
||||
# GNUX-NEXT: 2: 0000000000000000 0 NOTYPE LOCAL DEFAULT [VARIANT_PCS | 40] UND foo2
|
||||
# GNUX-NEXT: 3: 0000000000000000 0 NOTYPE LOCAL PROTECTED [VARIANT_PCS] UND foo3
|
||||
# GNUX-NEXT: 4: 0000000000000000 0 NOTYPE LOCAL PROTECTED UND foo4
|
||||
|
||||
# JSON: "Name": "foo1",
|
||||
# JSON: "Other": {
|
||||
# JSON-NEXT: "Value": 128,
|
||||
|
@ -7,6 +7,8 @@
|
||||
# RUN: FileCheck %s -DFILE=%t1 --check-prefix=LLVM1 --implicit-check-not="warning:"
|
||||
# RUN: llvm-readelf %t1 --symbols --relocations 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t1 --check-prefix=GNU1 --implicit-check-not="warning:"
|
||||
# RUN: llvm-readelf %t1 --symbols -X 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t1 --check-prefix=GNUX1 --implicit-check-not="warning:"
|
||||
|
||||
# LLVM1: Relocations [
|
||||
# LLVM1-NEXT: Section (5) .rela.foo {
|
||||
@ -62,6 +64,22 @@
|
||||
# GNU1-NEXT: warning: '[[FILE]]': a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table
|
||||
# GNU1-NEXT: 9: {{.*}} SECTION {{.*}} 3 <section 3>
|
||||
|
||||
# GNUX1: Symbol table '.symtab' contains 10 entries:
|
||||
# GNUX1-NEXT: Num: {{.*}} Type {{.*}} Ndx(SecName) Name
|
||||
# GNUX1-NEXT: 0: {{.*}} NOTYPE {{.*}} UND {{$}}
|
||||
# GNUX1-NEXT: 1: {{.*}} SECTION {{.*}} 1 (.foo) .foo
|
||||
# GNUX1-NEXT: 2: {{.*}} SECTION {{.*}} 1 (.foo) symbol1
|
||||
# GNUX1-NEXT: warning: '[[FILE]]': invalid section index: 67
|
||||
# GNUX1-NEXT: 3: {{.*}} SECTION {{.*}} 67 <section 67>
|
||||
# GNUX1-NEXT: 4: {{.*}} SECTION {{.*}} 67 symbol2
|
||||
# GNUX1-NEXT: 5: {{.*}} SECTION {{.*}} 2 (.bar) .bar
|
||||
# GNUX1-NEXT: 6: {{.*}} SECTION {{.*}} 2 (.bar) symbol3
|
||||
# GNUX1-NEXT: warning: '[[FILE]]': invalid section index: 66
|
||||
# GNUX1-NEXT: 7: {{.*}} SECTION {{.*}} 66 <section 66>
|
||||
# GNUX1-NEXT: 8: {{.*}} SECTION {{.*}} 66 symbol4
|
||||
# GNUX1-NEXT: warning: '[[FILE]]': a section [index 3] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table
|
||||
# GNUX1-NEXT: 9: {{.*}} SECTION {{.*}} 3 <section 3>
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS32
|
||||
|
@ -13,13 +13,18 @@
|
||||
# RUN: yaml2obj %s -DBITS=64 -DTYPE=ET_REL -o %t64
|
||||
# RUN: llvm-readobj --symbols %t64 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-LLVM
|
||||
# RUN: llvm-readelf --symbols %t64 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU64
|
||||
# RUN: llvm-readelf -s --extra-sym-info %t64 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU64X
|
||||
# RUN: yaml2obj %s -DBITS=32 -DTYPE=ET_REL -o %t32
|
||||
# RUN: llvm-readobj --symbols %t32 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-LLVM
|
||||
# RUN: llvm-readelf --symbols %t32 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU32
|
||||
# RUN: llvm-readelf -s -X %t32 | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU32X
|
||||
## b) Check dynamic objects.
|
||||
# RUN: yaml2obj %s -DBITS=64 -DTYPE=ET_DYN -o %t64.so
|
||||
# RUN: llvm-readobj --symbols %t64.so | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-LLVM
|
||||
# RUN: llvm-readobj --symbols %t64.so > %t64llvm.txt
|
||||
# RUN: FileCheck --input-file=%t64llvm.txt %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-LLVM
|
||||
# RUN: llvm-readelf --symbols %t64.so | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU64
|
||||
## --extra-sym-info is a no-op for llvm-readobj.
|
||||
# RUN: llvm-readobj --symbols --extra-sym-info %t64.so | diff %t64llvm.txt -
|
||||
# RUN: yaml2obj %s -DBITS=32 -DTYPE=ET_DYN -o %t32.so
|
||||
# RUN: llvm-readobj --symbols %t32.so | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-LLVM
|
||||
# RUN: llvm-readelf --symbols %t32.so | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SYMBOLS-GNU32
|
||||
@ -41,7 +46,7 @@
|
||||
# SYMBOLS-LLVM-NEXT: Binding: Local (0x0)
|
||||
# SYMBOLS-LLVM-NEXT: Type: None (0x0)
|
||||
# SYMBOLS-LLVM-NEXT: Other: 0
|
||||
# SYMBOLS-LLVM-NEXT: Section: Undefined (0x0)
|
||||
# SYMBOLS-LLVM-NEXT: Section: .text (0x1)
|
||||
# SYMBOLS-LLVM-NEXT: }
|
||||
# SYMBOLS-LLVM-NEXT: Symbol {
|
||||
# SYMBOLS-LLVM-NEXT: Name: bar (1)
|
||||
@ -52,19 +57,44 @@
|
||||
# SYMBOLS-LLVM-NEXT: Other: 0
|
||||
# SYMBOLS-LLVM-NEXT: Section: Undefined (0x0)
|
||||
# SYMBOLS-LLVM-NEXT: }
|
||||
# SYMBOLS-LLVM-NEXT: Symbol {
|
||||
# SYMBOLS-LLVM-NEXT: Name: data (9)
|
||||
# SYMBOLS-LLVM-NEXT: Value: 0x3
|
||||
# SYMBOLS-LLVM-NEXT: Size: 0
|
||||
# SYMBOLS-LLVM-NEXT: Binding: Global (0x1)
|
||||
# SYMBOLS-LLVM-NEXT: Type: None (0x0)
|
||||
# SYMBOLS-LLVM-NEXT: Other: 0
|
||||
# SYMBOLS-LLVM-NEXT: Section: .data (0x2)
|
||||
# SYMBOLS-LLVM-NEXT: }
|
||||
# SYMBOLS-LLVM-NEXT:]
|
||||
|
||||
# SYMBOLS-GNU64:Symbol table '.symtab' contains 3 entries:
|
||||
# SYMBOLS-GNU64:Symbol table '.symtab' contains 4 entries:
|
||||
# SYMBOLS-GNU64-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# SYMBOLS-GNU64-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# SYMBOLS-GNU64-NEXT: 1: 0000000000000001 0 NOTYPE LOCAL DEFAULT UND foo
|
||||
# SYMBOLS-GNU64-NEXT: 1: 0000000000000001 0 NOTYPE LOCAL DEFAULT 1 foo
|
||||
# SYMBOLS-GNU64-NEXT: 2: 0000000000000002 0 NOTYPE LOCAL DEFAULT UND bar
|
||||
# SYMBOLS-GNU64-NEXT: 3: 0000000000000003 0 NOTYPE GLOBAL DEFAULT 2 data
|
||||
|
||||
# SYMBOLS-GNU32:Symbol table '.symtab' contains 3 entries:
|
||||
# SYMBOLS-GNU64X:Symbol table '.symtab' contains 4 entries:
|
||||
#SYMBOLS-GNU64X-NEXT: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
#SYMBOLS-GNU64X-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
#SYMBOLS-GNU64X-NEXT: 1: 0000000000000001 0 NOTYPE LOCAL DEFAULT 1 (.text) foo
|
||||
#SYMBOLS-GNU64X-NEXT: 2: 0000000000000002 0 NOTYPE LOCAL DEFAULT UND bar
|
||||
#SYMBOLS-GNU64X-NEXT: 3: 0000000000000003 0 NOTYPE GLOBAL DEFAULT 2 (.data) data
|
||||
|
||||
# SYMBOLS-GNU32:Symbol table '.symtab' contains 4 entries:
|
||||
# SYMBOLS-GNU32-NEXT: Num: Value Size Type Bind Vis Ndx Name
|
||||
# SYMBOLS-GNU32-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# SYMBOLS-GNU32-NEXT: 1: 00000001 0 NOTYPE LOCAL DEFAULT UND foo
|
||||
# SYMBOLS-GNU32-NEXT: 1: 00000001 0 NOTYPE LOCAL DEFAULT 1 foo
|
||||
# SYMBOLS-GNU32-NEXT: 2: 00000002 0 NOTYPE LOCAL DEFAULT UND bar
|
||||
# SYMBOLS-GNU32-NEXT: 3: 00000003 0 NOTYPE GLOBAL DEFAULT 2 data
|
||||
|
||||
# SYMBOLS-GNU32X:Symbol table '.symtab' contains 4 entries:
|
||||
#SYMBOLS-GNU32X-NEXT: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
#SYMBOLS-GNU32X-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
#SYMBOLS-GNU32X-NEXT: 1: 00000001 0 NOTYPE LOCAL DEFAULT 1 (.text) foo
|
||||
#SYMBOLS-GNU32X-NEXT: 2: 00000002 0 NOTYPE LOCAL DEFAULT UND bar
|
||||
#SYMBOLS-GNU32X-NEXT: 3: 00000003 0 NOTYPE GLOBAL DEFAULT 2 (.data) data
|
||||
|
||||
## Case 2: Check flag aliases produce identical output
|
||||
# RUN: llvm-readobj --symbols %t64 > %t.symbols
|
||||
@ -100,10 +130,10 @@
|
||||
## Case 6: Test that the Num index starts from zero at every new symbol table.
|
||||
# RUN: llvm-readelf --symbols %t64 %t64 | FileCheck %s --check-prefix=NUM-INDEX
|
||||
|
||||
# NUM-INDEX: Symbol table '.symtab' contains 3 entries:
|
||||
# NUM-INDEX: Symbol table '.symtab' contains 4 entries:
|
||||
# NUM-INDEX-NEXT: Num: {{.*}}
|
||||
# NUM-INDEX-NEXT: 0: {{.*}}
|
||||
# NUM-INDEX: Symbol table '.symtab' contains 3 entries:
|
||||
# NUM-INDEX: Symbol table '.symtab' contains 4 entries:
|
||||
# NUM-INDEX-NEXT: Num: {{.*}}
|
||||
# NUM-INDEX-NEXT: 0: {{.*}}
|
||||
|
||||
@ -112,11 +142,21 @@ FileHeader:
|
||||
Class: ELFCLASS[[BITS]]
|
||||
Data: ELFDATA2LSB
|
||||
Type: [[TYPE]]
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
Symbols:
|
||||
- Name: foo
|
||||
Value: 0x1
|
||||
- Name: bar
|
||||
Value: 0x2
|
||||
- Name: foo
|
||||
Value: 0x1
|
||||
Section: .text
|
||||
- Name: bar
|
||||
Value: 0x2
|
||||
- Name: data
|
||||
Value: 0x3
|
||||
Binding: STB_GLOBAL
|
||||
Section: .data
|
||||
DynamicSymbols:
|
||||
- Name: zed
|
||||
|
||||
@ -232,6 +272,13 @@ Symbols:
|
||||
## Test a symbol defined relative to a section with an invalid name.
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t64.err4
|
||||
# RUN: llvm-readelf -s %t64.err4 2>&1 | FileCheck /dev/null --implicit-check-not=warning:
|
||||
# RUN: llvm-readelf -s -X %t64.err4 2>&1 | \
|
||||
# RUN: FileCheck %s -DFILE=%t64.err4 --check-prefix=INVALID-SECNAME-GNU --implicit-check-not=warning:
|
||||
|
||||
# INVALID-SECNAME-GNU: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
# INVALID-SECNAME-GNU-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# INVALID-SECNAME-GNU-NEXT: warning: '[[FILE]]': a section [index 1] has an invalid sh_name (0xffff) offset which goes past the end of the section name string table
|
||||
# INVALID-SECNAME-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 1 foo
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readelf --symbols --dyn-syms %t1 2>&1 | FileCheck %s --check-prefix=GNU
|
||||
# RUN: llvm-readelf --symbols --dyn-syms --extra-sym-info %t1 2>&1 | FileCheck %s --check-prefix=GNUX
|
||||
# RUN: llvm-readobj --symbols --dyn-syms %t1 2>&1 | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
# GNU: Symbol table '.dynsym' contains 3 entries:
|
||||
@ -20,6 +21,17 @@
|
||||
# GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 2 sym1
|
||||
# GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 1 sym2
|
||||
|
||||
# GNUX: Symbol table '.dynsym' contains 3 entries:
|
||||
# GNUX-NEXT: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
# GNUX-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# GNUX-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 3 (.section3) dynsym1
|
||||
# GNUX-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 2 (.section2) dynsym2
|
||||
# GNUX: Symbol table '.symtab' contains 3 entries:
|
||||
# GNUX-NEXT: Num: Value Size Type Bind Vis+Other Ndx(SecName) Name [+ Version Info]
|
||||
# GNUX-NEXT: 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
|
||||
# GNUX-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT 2 (.section2) sym1
|
||||
# GNUX-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT 1 (.section1) sym2
|
||||
|
||||
# LLVM: Symbols [
|
||||
# LLVM-NEXT: Symbol {
|
||||
# LLVM-NEXT: Name: (0)
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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) {}
|
||||
|
@ -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>">;
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
|
Loading…
x
Reference in New Issue
Block a user