[llvm] 948ef5b - [llvm-objdump] Teach `llvm-objdump` dump dynamic symbols.
via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 4 19:44:47 PDT 2020
Author: vgxbj
Date: 2020-04-05T10:46:59+08:00
New Revision: 948ef5b1a60459220aa1a4fa0c7483780deebb4e
URL: https://github.com/llvm/llvm-project/commit/948ef5b1a60459220aa1a4fa0c7483780deebb4e
DIFF: https://github.com/llvm/llvm-project/commit/948ef5b1a60459220aa1a4fa0c7483780deebb4e.diff
LOG: [llvm-objdump] Teach `llvm-objdump` dump dynamic symbols.
Summary:
This patch is to teach `llvm-objdump` dump dynamic symbols (`-T` and `--dynamic-syms`). Currently, this patch is not fully compatible with `gnu-objdump`, but I would like to continue working on this in next few patches. It has two issues.
1. Some symbols shouldn't be marked as global(g). (`-t/--syms` has same issue as well) (Fixed by D75659)
2. `gnu-objdump` can dump version information and *dynamically* insert before symbol name field.
`objdump -T a.out` gives:
```
DYNAMIC SYMBOL TABLE:
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 printf
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __libc_start_main
0000000000000000 w D *UND* 0000000000000000 __gmon_start__
0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF *UND* 0000000000000000 GLIBC_2.2.5 __cxa_finalize
```
`llvm-objdump -T a.out` gives:
```
DYNAMIC SYMBOL TABLE:
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 g DF *UND* 0000000000000000 printf
0000000000000000 g DF *UND* 0000000000000000 __libc_start_main
0000000000000000 w D *UND* 0000000000000000 __gmon_start__
0000000000000000 w D *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000000000 w DF *UND* 0000000000000000 __cxa_finalize
```
Reviewers: jhenderson, grimar, MaskRay, espindola
Reviewed By: jhenderson, grimar
Subscribers: emaste, rupprecht, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D75756
Added:
llvm/test/tools/llvm-objdump/X86/elf-dynamic-symbols.test
llvm/test/tools/llvm-objdump/unimplemented-features.test
Modified:
llvm/docs/CommandGuide/llvm-objdump.rst
llvm/tools/llvm-objdump/llvm-objdump.cpp
llvm/tools/llvm-objdump/llvm-objdump.h
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-objdump.rst b/llvm/docs/CommandGuide/llvm-objdump.rst
index 04c76491101d..c236d2dfa5be 100644
--- a/llvm/docs/CommandGuide/llvm-objdump.rst
+++ b/llvm/docs/CommandGuide/llvm-objdump.rst
@@ -85,6 +85,10 @@ combined with other commands:
Display the symbol table.
+.. option:: -T, --dynamic-syms
+
+ Display the contents of the dynamic symbol table.
+
.. option:: -u, --unwind-info
Display the unwind info of the input(s).
diff --git a/llvm/test/tools/llvm-objdump/X86/elf-dynamic-symbols.test b/llvm/test/tools/llvm-objdump/X86/elf-dynamic-symbols.test
new file mode 100644
index 000000000000..580ac8507f0e
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/elf-dynamic-symbols.test
@@ -0,0 +1,107 @@
+## Test that llvm-objdump can dump dynamic symbols.
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-objdump --dynamic-syms %t1 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=DYNSYM
+# RUN: llvm-objdump -T %t1 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=DYNSYM
+
+# DYNSYM:DYNAMIC SYMBOL TABLE:
+# DYNSYM-NEXT:0000000000000000 l DO .data 0000000000000000 localsym
+# DYNSYM-NEXT:0000000000000000 g DO .data 0000000000000000 globalsym
+# DYNSYM-NEXT:0000000000000000 u DO .data 0000000000000000 uniqueglobalsym
+# DYNSYM-NEXT:0000000000000000 w DO .data 0000000000000000 weaksym
+# DYNSYM-NEXT:0000000000000000 g Df .data 0000000000000000 filesym
+# DYNSYM-NEXT:0000000000000000 g DF .data 0000000000000000 funcsym
+# DYNSYM-EMPTY:
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+DynamicSymbols:
+ - Name: localsym
+ Type: STT_OBJECT
+ Section: .data
+ Binding: STB_LOCAL
+ - Name: globalsym
+ Type: STT_OBJECT
+ Section: .data
+ Binding: STB_GLOBAL
+ - Name: uniqueglobalsym
+ Type: STT_OBJECT
+ Section: .data
+ Binding: STB_GNU_UNIQUE
+ - Name: weaksym
+ Type: STT_OBJECT
+ Section: .data
+ Binding: STB_WEAK
+ - Name: filesym
+ Type: STT_FILE
+ Section: .data
+ Binding: STB_GLOBAL
+ - Name: funcsym
+ Type: STT_FUNC
+ Section: .data
+ Binding: STB_GLOBAL
+
+## Test dumping ELF files with no .dynsym section.
+# RUN: yaml2obj --docnum=2 %s -o %t2
+# RUN: llvm-objdump --dynamic-syms %t2 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=NODYNSYM
+# RUN: llvm-objdump -T %t2 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=NODYNSYM
+
+# NODYNSYM:DYNAMIC SYMBOL TABLE:
+# NODYNSYM-EMPTY:
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+
+## Test dumping ELF files with logically empty .dynsym section (only has a 0-index NULL symbol).
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-objdump --dynamic-syms %t3 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=ONLY-NULL
+# RUN: llvm-objdump -T %t3 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=ONLY-NULL
+
+# ONLY-NULL:DYNAMIC SYMBOL TABLE:
+# ONLY-NULL-EMPTY:
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+DynamicSymbols: []
+
+## Test dumping ELF files with truly empty .dynsym section (size of .dynsym section is 0).
+# RUN: yaml2obj --docnum=4 %s -o %t4
+# RUN: llvm-objdump --dynamic-syms %t4 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=EMPTY
+# RUN: llvm-objdump -T %t4 | \
+# RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=EMPTY
+
+# EMPTY:DYNAMIC SYMBOL TABLE:
+# EMPTY-EMPTY:
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+Sections:
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+ Size: 0
diff --git a/llvm/test/tools/llvm-objdump/unimplemented-features.test b/llvm/test/tools/llvm-objdump/unimplemented-features.test
new file mode 100644
index 000000000000..87366e1ef65d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/unimplemented-features.test
@@ -0,0 +1,31 @@
+## Test dumping dynamic symbols reports a warning if the operation is unsupported for the file format.
+# RUN: yaml2obj %s --docnum=1 -o %t.macho.o
+# RUN: llvm-objdump --dynamic-syms %t.macho.o 2>&1 | \
+# RUN: FileCheck %s -DFILE=%t.macho.o
+# RUN: yaml2obj %s --docnum=2 -o %t.coff.o
+# RUN: llvm-objdump --dynamic-syms %t.coff.o 2>&1 | \
+# RUN: FileCheck %s -DFILE=%t.coff.o
+# RUN: llvm-objdump --dynamic-syms %p/XCOFF/Inputs/xcoff-section-headers.o 2>&1 | \
+# RUN: FileCheck %s -DFILE=%p/XCOFF/Inputs/xcoff-section-headers.o
+
+# CHECK:DYNAMIC SYMBOL TABLE:
+# CHECK-NEXT:{{.*}}llvm-objdump: warning: '[[FILE]]': this operation is not currently supported for this file format
+# CHECK-EMPTY:
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00218085
+ reserved: 0x00000000
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections: []
+symbols: []
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 6f284159cb21..69967db9ad56 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -321,6 +321,15 @@ static cl::alias SymbolTableShort("t", cl::desc("Alias for --syms"),
cl::NotHidden, cl::Grouping,
cl::aliasopt(SymbolTable));
+cl::opt<bool> DynamicSymbolTable(
+ "dynamic-syms",
+ cl::desc("Display the contents of the dynamic symbol table"),
+ cl::cat(ObjdumpCat));
+static cl::alias DynamicSymbolTableShort("T",
+ cl::desc("Alias for --dynamic-syms"),
+ cl::NotHidden, cl::Grouping,
+ cl::aliasopt(DynamicSymbolTable));
+
cl::opt<std::string> TripleName("triple",
cl::desc("Target triple to disassemble for, "
"see -version for available targets"),
@@ -1857,143 +1866,167 @@ void printSectionContents(const ObjectFile *Obj) {
}
void printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
- StringRef ArchitectureName) {
- outs() << "SYMBOL TABLE:\n";
-
- if (const COFFObjectFile *Coff = dyn_cast<const COFFObjectFile>(O)) {
- printCOFFSymbolTable(Coff);
+ StringRef ArchitectureName, bool DumpDynamic) {
+ if (O->isCOFF() && !DumpDynamic) {
+ outs() << "SYMBOL TABLE:\n";
+ printCOFFSymbolTable(cast<const COFFObjectFile>(O));
return;
}
const StringRef FileName = O->getFileName();
- const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
- for (auto I = O->symbol_begin(), E = O->symbol_end(); I != E; ++I) {
- const SymbolRef &Symbol = *I;
- uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName, ArchiveName,
- ArchitectureName);
- if ((Address < StartAddress) || (Address > StopAddress))
- continue;
- SymbolRef::Type Type = unwrapOrError(Symbol.getType(), FileName,
- ArchiveName, ArchitectureName);
- uint32_t Flags = Symbol.getFlags();
- // Don't ask a Mach-O STAB symbol for its section unless you know that
- // STAB symbol's section field refers to a valid section index. Otherwise
- // the symbol may error trying to load a section that does not exist.
- bool isSTAB = false;
- if (MachO) {
- DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
- uint8_t NType = (MachO->is64Bit() ?
- MachO->getSymbol64TableEntry(SymDRI).n_type:
- MachO->getSymbolTableEntry(SymDRI).n_type);
- if (NType & MachO::N_STAB)
- isSTAB = true;
- }
- section_iterator Section = isSTAB ? O->section_end() :
- unwrapOrError(Symbol.getSection(), FileName,
- ArchiveName, ArchitectureName);
+ if (!DumpDynamic) {
+ outs() << "SYMBOL TABLE:\n";
+ for (auto I = O->symbol_begin(); I != O->symbol_end(); ++I)
+ printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+ return;
+ }
- StringRef Name;
- if (Type == SymbolRef::ST_Debug && Section != O->section_end()) {
- if (Expected<StringRef> NameOrErr = Section->getName())
- Name = *NameOrErr;
- else
- consumeError(NameOrErr.takeError());
+ outs() << "DYNAMIC SYMBOL TABLE:\n";
+ if (!O->isELF()) {
+ reportWarning(
+ "this operation is not currently supported for this file format",
+ FileName);
+ return;
+ }
- } else {
- Name = unwrapOrError(Symbol.getName(), FileName, ArchiveName,
- ArchitectureName);
- }
+ const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(O);
+ for (auto I = ELF->getDynamicSymbolIterators().begin();
+ I != ELF->getDynamicSymbolIterators().end(); ++I)
+ printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
+}
- bool Global = Flags & SymbolRef::SF_Global;
- bool Weak = Flags & SymbolRef::SF_Weak;
- bool Absolute = Flags & SymbolRef::SF_Absolute;
- bool Common = Flags & SymbolRef::SF_Common;
- bool Hidden = Flags & SymbolRef::SF_Hidden;
-
- char GlobLoc = ' ';
- if ((Section != O->section_end() || Absolute) && !Weak)
- GlobLoc = Global ? 'g' : 'l';
- char IFunc = ' ';
- if (isa<ELFObjectFileBase>(O)) {
- if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
- IFunc = 'i';
- if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
- GlobLoc = 'u';
- }
- char Debug = (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
- ? 'd' : ' ';
- char FileFunc = ' ';
- if (Type == SymbolRef::ST_File)
- FileFunc = 'f';
- else if (Type == SymbolRef::ST_Function)
- FileFunc = 'F';
- else if (Type == SymbolRef::ST_Data)
- FileFunc = 'O';
-
- const char *Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 :
- "%08" PRIx64;
-
- outs() << format(Fmt, Address) << " "
- << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
- << (Weak ? 'w' : ' ') // Weak?
- << ' ' // Constructor. Not supported yet.
- << ' ' // Warning. Not supported yet.
- << IFunc
- << Debug // Debugging (d) or dynamic (D) symbol.
- << FileFunc // Name of function (F), file (f) or object (O).
- << ' ';
- if (Absolute) {
- outs() << "*ABS*";
- } else if (Common) {
- outs() << "*COM*";
- } else if (Section == O->section_end()) {
- outs() << "*UND*";
- } else {
- if (const MachOObjectFile *MachO =
- dyn_cast<const MachOObjectFile>(O)) {
- DataRefImpl DR = Section->getRawDataRefImpl();
- StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
- outs() << SegmentName << ",";
- }
- StringRef SectionName =
- unwrapOrError(Section->getName(), O->getFileName());
- outs() << SectionName;
- }
+void printSymbol(const ObjectFile *O, const SymbolRef &Symbol,
+ StringRef FileName, StringRef ArchiveName,
+ StringRef ArchitectureName, bool DumpDynamic) {
+ const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
+ uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName, ArchiveName,
+ ArchitectureName);
+ if ((Address < StartAddress) || (Address > StopAddress))
+ return;
+ SymbolRef::Type Type =
+ unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName);
+ uint32_t Flags = Symbol.getFlags();
+
+ // Don't ask a Mach-O STAB symbol for its section unless you know that
+ // STAB symbol's section field refers to a valid section index. Otherwise
+ // the symbol may error trying to load a section that does not exist.
+ bool IsSTAB = false;
+ if (MachO) {
+ DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
+ uint8_t NType =
+ (MachO->is64Bit() ? MachO->getSymbol64TableEntry(SymDRI).n_type
+ : MachO->getSymbolTableEntry(SymDRI).n_type);
+ if (NType & MachO::N_STAB)
+ IsSTAB = true;
+ }
+ section_iterator Section = IsSTAB
+ ? O->section_end()
+ : unwrapOrError(Symbol.getSection(), FileName,
+ ArchiveName, ArchitectureName);
+
+ StringRef Name;
+ if (Type == SymbolRef::ST_Debug && Section != O->section_end()) {
+ if (Expected<StringRef> NameOrErr = Section->getName())
+ Name = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
- if (Common || isa<ELFObjectFileBase>(O)) {
- uint64_t Val =
- Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize();
- outs() << '\t' << format(Fmt, Val);
+ } else {
+ Name = unwrapOrError(Symbol.getName(), FileName, ArchiveName,
+ ArchitectureName);
+ }
+
+ bool Global = Flags & SymbolRef::SF_Global;
+ bool Weak = Flags & SymbolRef::SF_Weak;
+ bool Absolute = Flags & SymbolRef::SF_Absolute;
+ bool Common = Flags & SymbolRef::SF_Common;
+ bool Hidden = Flags & SymbolRef::SF_Hidden;
+
+ char GlobLoc = ' ';
+ if ((Section != O->section_end() || Absolute) && !Weak)
+ GlobLoc = Global ? 'g' : 'l';
+ char IFunc = ' ';
+ if (isa<ELFObjectFileBase>(O)) {
+ if (ELFSymbolRef(Symbol).getELFType() == ELF::STT_GNU_IFUNC)
+ IFunc = 'i';
+ if (ELFSymbolRef(Symbol).getBinding() == ELF::STB_GNU_UNIQUE)
+ GlobLoc = 'u';
+ }
+
+ char Debug = ' ';
+ if (DumpDynamic)
+ Debug = 'D';
+ else if (Type == SymbolRef::ST_Debug || Type == SymbolRef::ST_File)
+ Debug = 'd';
+
+ char FileFunc = ' ';
+ if (Type == SymbolRef::ST_File)
+ FileFunc = 'f';
+ else if (Type == SymbolRef::ST_Function)
+ FileFunc = 'F';
+ else if (Type == SymbolRef::ST_Data)
+ FileFunc = 'O';
+
+ const char *Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
+
+ outs() << format(Fmt, Address) << " "
+ << GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
+ << (Weak ? 'w' : ' ') // Weak?
+ << ' ' // Constructor. Not supported yet.
+ << ' ' // Warning. Not supported yet.
+ << IFunc // Indirect reference to another symbol.
+ << Debug // Debugging (d) or dynamic (D) symbol.
+ << FileFunc // Name of function (F), file (f) or object (O).
+ << ' ';
+ if (Absolute) {
+ outs() << "*ABS*";
+ } else if (Common) {
+ outs() << "*COM*";
+ } else if (Section == O->section_end()) {
+ outs() << "*UND*";
+ } else {
+ if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O)) {
+ DataRefImpl DR = Section->getRawDataRefImpl();
+ StringRef SegmentName = MachO->getSectionFinalSegmentName(DR);
+ outs() << SegmentName << ",";
}
+ StringRef SectionName = unwrapOrError(Section->getName(), FileName);
+ outs() << SectionName;
+ }
- if (isa<ELFObjectFileBase>(O)) {
- uint8_t Other = ELFSymbolRef(Symbol).getOther();
- switch (Other) {
- case ELF::STV_DEFAULT:
- break;
- case ELF::STV_INTERNAL:
- outs() << " .internal";
- break;
- case ELF::STV_HIDDEN:
- outs() << " .hidden";
- break;
- case ELF::STV_PROTECTED:
- outs() << " .protected";
- break;
- default:
- outs() << format(" 0x%02x", Other);
- break;
- }
- } else if (Hidden) {
+ if (Common || isa<ELFObjectFileBase>(O)) {
+ uint64_t Val =
+ Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize();
+ outs() << '\t' << format(Fmt, Val);
+ }
+
+ if (isa<ELFObjectFileBase>(O)) {
+ uint8_t Other = ELFSymbolRef(Symbol).getOther();
+ switch (Other) {
+ case ELF::STV_DEFAULT:
+ break;
+ case ELF::STV_INTERNAL:
+ outs() << " .internal";
+ break;
+ case ELF::STV_HIDDEN:
outs() << " .hidden";
+ break;
+ case ELF::STV_PROTECTED:
+ outs() << " .protected";
+ break;
+ default:
+ outs() << format(" 0x%02x", Other);
+ break;
}
-
- if (Demangle)
- outs() << ' ' << demangle(std::string(Name)) << '\n';
- else
- outs() << ' ' << Name << '\n';
+ } else if (Hidden) {
+ outs() << " .hidden";
}
+
+ if (Demangle)
+ outs() << ' ' << demangle(std::string(Name)) << '\n';
+ else
+ outs() << ' ' << Name << '\n';
}
static void printUnwindInfo(const ObjectFile *O) {
@@ -2237,6 +2270,9 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr,
printSectionHeaders(O);
if (SymbolTable)
printSymbolTable(O, ArchiveName);
+ if (DynamicSymbolTable)
+ printSymbolTable(O, ArchiveName, /*ArchitectureName=*/"",
+ /*DumpDynamic=*/true);
if (DwarfDumpType != DIDT_Null) {
std::unique_ptr<DIContext> DICtx = DWARFContext::create(*O);
// Dump the complete DWARF structure.
@@ -2378,7 +2414,7 @@ int main(int argc, char **argv) {
if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null &&
!DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&
!Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&
- !UnwindInfo && !FaultMapSection &&
+ !DynamicSymbolTable && !UnwindInfo && !FaultMapSection &&
!(MachOOpt &&
(Bind || DataInCode || DylibId || DylibsUsed || ExportsTrie ||
FirstPrivateHeader || IndirectSymbols || InfoPlist || LazyBind ||
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index f834f11def39..7863689f91ac 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -133,7 +133,11 @@ void printDynamicRelocations(const object::ObjectFile *O);
void printSectionHeaders(const object::ObjectFile *O);
void printSectionContents(const object::ObjectFile *O);
void printSymbolTable(const object::ObjectFile *O, StringRef ArchiveName,
- StringRef ArchitectureName = StringRef());
+ StringRef ArchitectureName = StringRef(),
+ bool DumpDynamic = false);
+void printSymbol(const object::ObjectFile *O, const object::SymbolRef &Symbol,
+ StringRef FileName, StringRef ArchiveName,
+ StringRef ArchitectureName, bool DumpDynamic);
LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Twine Message);
LLVM_ATTRIBUTE_NORETURN void reportError(Error E, StringRef FileName,
StringRef ArchiveName = "",
More information about the llvm-commits
mailing list