In r287786, a bug was introduced into llvm-readelf where it didn't print
the static symbol table if both --symbols and --dyn-symbols were
specified, even if there was no dynamic symbol table. This is obviously
incorrect.
This patch fixes this issue, by delegating the decision of which symbol
tables should be printed to the final dumper, rather than trying to
decide in the command-line option handling layer. The decision was made
to follow the approach taken in this patch because the LLVM style dumper
uses a different order to the original GNU style behaviour (and GNU
readelf) for ELF output. Other approaches resulted in behaviour changes
for other dumpers which felt wrong. In particular, I wanted to avoid
changing the order of the output for --symbols --dyn-symbols for LLVM
style, keep what is emitted by --symbols unchanged for all dumpers, and
avoid having different orders of .dynsym and .symtab dumping for GNU
"--symbols" and "--symbols --dyn-symbols".
Reviewed by: grimar, rupprecht
Differential Revision: https://reviews.llvm.org/D57016
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351960
91177308-0d34-0410-b5e6-
96231b3b80d8
# LLVM-COMMON-NEXT: ]
## Check GNU output style.
-## FIXME: The extra run for --symbols is because GNU mode only prints the dynamic symbols,
-## if --dyn-symbols is specified, even if --symbols is specified.
-# RUN: llvm-readelf --relocations --dyn-symbols --dyn-relocations \
+# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups --demangle %t.so > %t.gnu.long
-# RUN: llvm-readelf --symbols --demangle %t.so >> %t.gnu.long
-# RUN: llvm-readelf --relocations --dyn-symbols --dyn-relocations \
+# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups -C %t.so > %t.gnu.short
-# RUN: llvm-readelf --symbols -C %t.so >> %t.gnu.short
# RUN: FileCheck %s --input-file %t.gnu.long --check-prefixes=GNU-COMMON,GNU-DEMANGLE
# RUN: diff %t.gnu.long %t.gnu.short
## Check that default is no demangling.
-# RUN: llvm-readelf --relocations --dyn-symbols --dyn-relocations \
+# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups %t.so > %t.gnu.default
-# RUN: llvm-readelf --symbols %t.so >> %t.gnu.default
-# RUN: llvm-readelf --relocations --dyn-symbols --dyn-relocations \
+# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups --demangle=false %t.so > %t.gnu.nodemangle
-# RUN: llvm-readelf --symbols --demangle=false %t.so >> %t.gnu.nodemangle
# RUN: FileCheck %s --input-file %t.gnu.default --check-prefixes=GNU-COMMON,GNU-MANGLED
# RUN: diff %t.gnu.default %t.gnu.nodemangle
# GNU-DEMANGLE-NEXT: foo(int){{$}}
# GNU-MANGLED-NEXT: _Z3fooi{{$}}
-# GNU-COMMON: COMDAT group section [{{.*}}] `.group'
-# GNU-DEMANGLE-SAME: [foo(char)]
-# GNU-MANGLED-SAME: [_Z3fooc]
-
# GNU-COMMON: Symbol table '.symtab' contains 3 entries:
# GNU-COMMON-NEXT: Num: Value Size Type Bind Vis Ndx Name
# GNU-COMMON-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
# GNU-MANGLED-NEXT: _Z3fooc{{$}}
# GNU-MANGLED-NEXT: _Z4blahf{{$}}
+# GNU-COMMON: COMDAT group section [{{.*}}] `.group'
+# GNU-DEMANGLE-SAME: [foo(char)]
+# GNU-MANGLED-SAME: [_Z3fooc]
+
!ELF
FileHeader:
Class: ELFCLASS64
RUN: | FileCheck %s --check-prefixes=SYMTAB,DYN
RUN: llvm-readobj --dyn-symbols %p/Inputs/gnuhash.so.elf-x86_64 --elf-output-style=GNU \
RUN: | FileCheck %s --check-prefixes=NO-SYMTAB,DYN
+RUN: llvm-readobj --symbols --dyn-symbols %p/Inputs/gnuhash.so.elf-x86_64 --elf-output-style=GNU \
+RUN: | FileCheck %s --check-prefixes=SYMTAB,DYN
ELF32: Symbol table '.symtab' contains 5 entries:
ELF32-NEXT: Num: Value Size Type Bind Vis Ndx Name
NO-SYMTAB-NOT: Symbol table '.symtab'
-DYN:Symbol table '.dynsym' contains 5 entries:
+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: 3: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _end
DYN-NEXT: 4: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 __bss_start
+DYN-NOT: .dynsym
NO-SYMTAB-NOT: Symbol table '.symtab'
SYMTAB: Symbol table '.symtab' contains 12 entries:
SYMTAB-NEXT: 9: 00000000000001b8 0 NOTYPE GLOBAL DEFAULT 4 foo
SYMTAB-NEXT: 10: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _edata
SYMTAB-NEXT: 11: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 _end
+
+DYN-NOT: .dynsym
void printFileHeaders() override;
void printSectionHeaders() override;
void printRelocations() override;
- void printSymbols() override;
- void printDynamicSymbols() override;
void printUnwindInfo() override;
void printNeededLibraries() override;
void printStackMap() const override;
void printAddrsig() override;
private:
+ void printSymbols() override;
+ void printDynamicSymbols() override;
void printSymbol(const SymbolRef &Sym);
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,
uint64_t Bias = 0);
void printSectionHeaders() override;
void printRelocations() override;
void printDynamicRelocations() override;
- void printSymbols() override;
- void printDynamicSymbols() override;
+ void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
void printHashSymbols() override;
void printUnwindInfo() override;
virtual void printGroupSections(const ELFFile<ELFT> *Obj) = 0;
virtual void printRelocations(const ELFFile<ELFT> *Obj) = 0;
virtual void printSectionHeaders(const ELFFile<ELFT> *Obj) = 0;
- virtual void printSymbols(const ELFFile<ELFT> *Obj) = 0;
- virtual void printDynamicSymbols(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printSymbols(const ELFFile<ELFT> *Obj, bool PrintSymbols,
+ bool PrintDynamicSymbols) = 0;
virtual void printHashSymbols(const ELFFile<ELFT> *Obj) {}
virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
void printGroupSections(const ELFFile<ELFT> *Obj) override;
void printRelocations(const ELFO *Obj) override;
void printSectionHeaders(const ELFO *Obj) override;
- void printSymbols(const ELFO *Obj) override;
- void printDynamicSymbols(const ELFO *Obj) override;
+ void printSymbols(const ELFO *Obj, bool PrintSymbols,
+ bool PrintDynamicSymbols) override;
void printHashSymbols(const ELFO *Obj) override;
void printDynamicRelocations(const ELFO *Obj) override;
void printSymtabMessage(const ELFO *Obj, StringRef Name,
void printRelocations(const ELFO *Obj) override;
void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj);
void printSectionHeaders(const ELFO *Obj) override;
- void printSymbols(const ELFO *Obj) override;
- void printDynamicSymbols(const ELFO *Obj) override;
+ void printSymbols(const ELFO *Obj, bool PrintSymbols,
+ bool PrintDynamicSymbols) override;
void printDynamicRelocations(const ELFO *Obj) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
private:
void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel);
+ void printSymbols(const ELFO *Obj);
+ void printDynamicSymbols(const ELFO *Obj);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
StringRef StrTable, bool IsDynamic) override;
ELFDumperStyle->printDynamicRelocations(ObjF->getELFFile());
}
-template<class ELFT>
-void ELFDumper<ELFT>::printSymbols() {
- ELFDumperStyle->printSymbols(ObjF->getELFFile());
-}
-
-template<class ELFT>
-void ELFDumper<ELFT>::printDynamicSymbols() {
- ELFDumperStyle->printDynamicSymbols(ObjF->getELFFile());
+template <class ELFT>
+void ELFDumper<ELFT>::printSymbols(bool PrintSymbols,
+ bool PrintDynamicSymbols) {
+ ELFDumperStyle->printSymbols(ObjF->getELFFile(), PrintSymbols,
+ PrintDynamicSymbols);
}
template<class ELFT>
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) {
+void GNUStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols,
+ bool PrintDynamicSymbols) {
+ if (!PrintSymbols && !PrintDynamicSymbols)
+ return;
+ // GNU readelf prints both the .dynsym and .symtab with --symbols.
this->dumper()->printSymbolsHelper(true);
+ if (PrintSymbols)
+ this->dumper()->printSymbolsHelper(false);
}
template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
W.printHex("Section", SectionName, SectionIndex);
}
+template <class ELFT>
+void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj, bool PrintSymbols,
+ bool PrintDynamicSymbols) {
+ if (PrintSymbols)
+ printSymbols(Obj);
+ if (PrintDynamicSymbols)
+ printDynamicSymbols(Obj);
+}
+
template <class ELFT> void LLVMStyle<ELFT>::printSymbols(const ELFO *Obj) {
ListScope Group(W, "Symbols");
this->dumper()->printSymbolsHelper(false);
void printFileHeaders() override;
void printSectionHeaders() override;
void printRelocations() override;
- void printSymbols() override;
- void printDynamicSymbols() override;
void printUnwindInfo() override;
void printStackMap() const override;
template<class MachHeader>
void printFileHeaders(const MachHeader &Header);
+ void printSymbols() override;
+ void printDynamicSymbols() override;
void printSymbol(const SymbolRef &Symbol);
void printRelocation(const RelocationRef &Reloc);
virtual void printFileHeaders() = 0;
virtual void printSectionHeaders() = 0;
virtual void printRelocations() = 0;
- virtual void printSymbols() = 0;
- virtual void printDynamicSymbols() = 0;
+ virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) {
+ if (PrintSymbols)
+ printSymbols();
+ if (PrintDynamicSymbols)
+ printDynamicSymbols();
+ }
virtual void printUnwindInfo() = 0;
// Only implemented for ELF at this time.
protected:
ScopedPrinter &W;
+
+private:
+ virtual void printSymbols() {};
+ virtual void printDynamicSymbols() {};
};
std::error_code createCOFFDumper(const object::ObjectFile *Obj,
void printFileHeaders() override;
void printSectionHeaders() override;
void printRelocations() override;
- void printSymbols() override;
- void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
void printStackMap() const override { llvm_unreachable("unimplemented"); }
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
private:
+ void printSymbols() override;
+ void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
+
const WasmObjectFile *Obj;
};
// -symbols
// Also -s in llvm-readelf mode, or -t in llvm-readobj mode.
- cl::opt<bool> Symbols("symbols",
- cl::desc("Display the symbol table"));
+ cl::opt<bool>
+ Symbols("symbols",
+ cl::desc("Display the symbol table. Also display the dynamic "
+ "symbol table when using GNU output style for ELF"));
cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"),
cl::aliasopt(Symbols));
Dumper->printRelocations();
if (opts::DynRelocs)
Dumper->printDynamicRelocations();
- if (opts::Symbols)
- Dumper->printSymbols();
- if (opts::DynamicSymbols)
- Dumper->printDynamicSymbols();
+ if (opts::Symbols || opts::DynamicSymbols)
+ Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols);
if (opts::HashSymbols)
Dumper->printHashSymbols();
if (opts::UnwindInfo)
extern llvm::cl::opt<bool> SectionRelocations;
extern llvm::cl::opt<bool> SectionSymbols;
extern llvm::cl::opt<bool> SectionData;
- extern llvm::cl::opt<bool> DynamicSymbols;
extern llvm::cl::opt<bool> ExpandRelocs;
extern llvm::cl::opt<bool> RawRelr;
extern llvm::cl::opt<bool> CodeViewSubsectionBytes;