1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[llvm-readelf]Revert --dyn-symbols behaviour to make it GNU compatible, and add new --hash-symbols switch for old behaviour

In r287786, the behaviour of --dyn-symbols in llvm-readelf (but not
llvm-readobj) was changed to print the dynamic symbols as derived from
the hash table, rather than to print the dynamic symbol table contents
directly. The original change was initially submitted without review,
and some comments were made on the commit mailing list implying that the
new behavious is GNU compatible. I argue that it is not:

  1) It does not include a null symbol.
  2) It prints the symbols based on an order derived from the hash
     table.
  3) It prints an extra column indicating which bucket it came from.
     This could break parsers that expect a fixed number of columns,
     with the first column being the symbol index.
  4) If the input happens to have both .hash and .gnu.hash section, it
     prints interpretations of them both, resulting in most symbols
     being printed twice.
  5) There is no way of just printing the raw dynamic symbol table,
     because --symbols also prints the static symbol table.

This patch reverts the --dyn-symbols behaviour back to its old behaviour
of just printing the contents of the dynamic symbol table, similar to
what is printed by --symbols. As the hashed interpretation is still
desirable to validate the hash table, it puts it under a new switch
"--hash-symbols". This is a no-op on all output forms except for GNU
output style for ELF. If there is no hash table, it does nothing,
unlike the previous behaviour which printed the raw dynamic symbol
table, since the raw dynsym is available under --dyn-symbols.

The yaml input for the test is based on that in
test/tools/llvm-readobj/demangle.test, but stripped down to the bare
minimum to provide a valid dynamic symbol.

Note: some LLD tests needed updating. I will commit a separate patch for
those.

Reviewed by: grimar, rupprecht

Differential Revision: https://reviews.llvm.org/D56910

llvm-svn: 351789
This commit is contained in:
James Henderson 2019-01-22 09:35:35 +00:00
parent 316c1b9dc6
commit ac2839a57d
5 changed files with 150 additions and 49 deletions

View File

@ -0,0 +1,107 @@
# RUN: llvm-readelf --hash-symbols %p/Inputs/dynamic-table-exe.x86 \
# RUN: | FileCheck %s --check-prefix HASH
# HASH: Symbol table of .hash for image:
# HASH-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name
# HASH-NEXT: 9 0: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0@CXXABI_1.3
# HASH-NEXT: 13 0: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS _edata{{$}}
# HASH-NEXT: 7 0: 00000000 0 FUNC GLOBAL DEFAULT UND _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode@GLIBCXX_3.4
# HASH-NEXT: 2 0: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses{{$}}
# HASH-NEXT: 1 0: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__{{$}}
# HASH-NEXT: 16 1: 00000850 81 FUNC GLOBAL DEFAULT 14 main{{$}}
# HASH-NEXT: 10 1: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume@GCC_3.0
# HASH-NEXT: 8 1: 00000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.0
# HASH-NEXT: 12 1: 00001b68 0 NOTYPE GLOBAL DEFAULT ABS _end{{$}}
# HASH-NEXT: 6 1: 00000000 0 FUNC GLOBAL DEFAULT UND _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev@GLIBCXX_3.4
# HASH-NEXT: 5 1: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable{{$}}
# HASH-NEXT: 4 1: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable{{$}}
# HASH-NEXT: 3 1: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0
# HASH-NEXT: 11 2: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.1.3
# HASH-NEXT: 15 2: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS __bss_start{{$}}
# HASH-NEXT: 14 2: 0000093c 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used{{$}}
# HASH: Symbol table of .gnu.hash for image:
# HASH-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name
# HASH-NEXT: 12 0: 00001b68 0 NOTYPE GLOBAL DEFAULT ABS _end{{$}}
# HASH-NEXT: 13 0: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS _edata{{$}}
# HASH-NEXT: 14 1: 0000093c 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used{{$}}
# HASH-NEXT: 15 1: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS __bss_start{{$}}
# HASH-NEXT: 16 1: 00000850 81 FUNC GLOBAL DEFAULT 14 main{{$}}
## Show that if there are no hash sections, we do not print anything.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-readelf --hash-symbols %t.o \
# RUN: | FileCheck %s --check-prefix NO-HASH --allow-empty
# NO-HASH-NOT: {{.}}
## Sanity check that we can still find the dynamic symbols (i.e. the above test
## doesn't pass due to a mistake in the dynamic section).
# RUN: llvm-readelf --dyn-symbols %t.o | FileCheck %s --check-prefix DYNSYMS
# DYNSYMS: Symbol table '.dynsym' contains 2 entries:
!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
## TODO: Replace the raw section contents with more meaningful dynamic
## tags/symbols/etc, once yaml2obj supports it.
## FIXME: yaml2obj does not currently allow custom addresses for .dynstr and
## .dynsym if DynamicSymbols are specified.
## See https://bugs.llvm.org/show_bug.cgi?id=40339
- Name: .dynstr
Type: SHT_STRTAB
Flags: [ SHF_ALLOC ]
AddressAlign: 0x100
EntSize: 0x1
## "\0_Z3fooi\0"
Content: "005f5a33666f6f6900"
- Name: .dynsym
Type: SHT_DYNSYM
Flags: [ SHF_ALLOC ]
Link: .dynstr
Info: 1
Address: 0x100
AddressAlign: 0x100
EntSize: 0x18
## Null symbol;
## st_name: 1; st_info: Global | Func; st_other: 0;
## st_shndx: .text.foo; st_value: 0x2000; st_size: 0
Content: "000000000000000000000000000000000000000000000000010000001200040000200000000000000000000000000000"
- Name: .dynamic
Type: SHT_DYNAMIC
Flags: [ SHF_ALLOC ]
Link: .dynstr
Address: 0x1000
AddressAlign: 0x1000
## DT_STRTAB - 0x0
## DT_STRSZ - 0x9
## DT_SYMTAB - 0x100
## DT_SYMENT - 0x18
## DT_NULL - 0x0
Content: "050000000000000000000000000000000a000000000000000900000000000000060000000000000000010000000000000b00000000000000180000000000000000000000000000000000000000000000"
- Name: .text.foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
Size: 0x40
Address: 0x2000
AddressAlign: 0x2000
ProgramHeaders:
- Type: PT_LOAD
Flags: [ PF_R, PF_X ]
VAddr: 0x0
PAddr: 0x0
Sections:
- Section: .dynsym
- Section: .dynstr
- Section: .dynamic
- Section: .text.foo
- Type: PT_DYNAMIC
Flags: [ PF_R ]
VAddr: 0x1000
PAddr: 0x1000
Sections:
- Section: .dynamic

View File

@ -3,9 +3,9 @@ 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
RUN: llvm-readobj -dyn-symbols %p/Inputs/dynamic-table-exe.x86 --elf-output-style=GNU \
RUN: | FileCheck %s -check-prefix HASH
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
ELF32: Symbol table '.symtab' contains 5 entries:
ELF32-NEXT: Num: Value Size Type Bind Vis Ndx Name
@ -24,6 +24,8 @@ 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
NO-SYMTAB-NOT: Symbol table '.symtab'
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
@ -32,43 +34,19 @@ 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
NO-SYMTAB-NOT: Symbol table '.symtab'
HASH: Symbol table of .hash for image:
HASH-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name
HASH-NEXT: 9 0: 00000000 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0@CXXABI_1.3
HASH-NEXT: 13 0: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS _edata{{$}}
HASH-NEXT: 7 0: 00000000 0 FUNC GLOBAL DEFAULT UND _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1EPKcSt13_Ios_Openmode@GLIBCXX_3.4
HASH-NEXT: 2 0: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses{{$}}
HASH-NEXT: 1 0: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__{{$}}
HASH-NEXT: 16 1: 00000850 81 FUNC GLOBAL DEFAULT 14 main{{$}}
HASH-NEXT: 10 1: 00000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume@GCC_3.0
HASH-NEXT: 8 1: 00000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.0
HASH-NEXT: 12 1: 00001b68 0 NOTYPE GLOBAL DEFAULT ABS _end{{$}}
HASH-NEXT: 6 1: 00000000 0 FUNC GLOBAL DEFAULT UND _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev@GLIBCXX_3.4
HASH-NEXT: 5 1: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable{{$}}
HASH-NEXT: 4 1: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable{{$}}
HASH-NEXT: 3 1: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0
HASH-NEXT: 11 2: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.1.3
HASH-NEXT: 15 2: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS __bss_start{{$}}
HASH-NEXT: 14 2: 0000093c 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used{{$}}
HASH: Symbol table of .gnu.hash for image:
HASH-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name
HASH-NEXT: 12 0: 00001b68 0 NOTYPE GLOBAL DEFAULT ABS _end{{$}}
HASH-NEXT: 13 0: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS _edata{{$}}
HASH-NEXT: 14 1: 0000093c 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used{{$}}
HASH-NEXT: 15 1: 00001b64 0 NOTYPE GLOBAL DEFAULT ABS __bss_start{{$}}
HASH-NEXT: 16 1: 00000850 81 FUNC GLOBAL DEFAULT 14 main{{$}}
SYMTAB: Symbol table '.symtab' contains 12 entries:
SYMTAB-NEXT: Num: Value Size Type Bind Vis Ndx Name
SYMTAB-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
SYMTAB-NEXT: 1: 00000000000000e8 0 SECTION LOCAL DEFAULT 1
SYMTAB-NEXT: 2: 0000000000000120 0 SECTION LOCAL DEFAULT 2
SYMTAB-NEXT: 3: 0000000000000198 0 SECTION LOCAL DEFAULT 3
SYMTAB-NEXT: 4: 00000000000001b8 0 SECTION LOCAL DEFAULT 4
SYMTAB-NEXT: 5: 00000000002001b8 0 SECTION LOCAL DEFAULT 5
SYMTAB-NEXT: 6: 00000000002001b8 0 OBJECT LOCAL DEFAULT 5 _DYNAMIC
SYMTAB-NEXT: 7: 0000000000200268 0 OBJECT LOCAL DEFAULT 5 _GLOBAL_OFFSET_TABLE_
SYMTAB-NEXT: 8: 0000000000200268 0 NOTYPE GLOBAL DEFAULT 5 __bss_start
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

View File

@ -149,6 +149,7 @@ public:
void printDynamicRelocations() override;
void printSymbols() override;
void printDynamicSymbols() override;
void printHashSymbols() override;
void printUnwindInfo() override;
void printDynamicTable() override;
@ -330,8 +331,9 @@ public:
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 printHashSymbols(const ELFFile<ELFT> *Obj) {}
virtual void printDynamicRelocations(const ELFFile<ELFT> *Obj) = 0;
virtual void printSymtabMessage(const ELFFile<ELFT> *obj, StringRef Name,
virtual void printSymtabMessage(const ELFFile<ELFT> *Obj, StringRef Name,
size_t Offset) {}
virtual void printSymbol(const ELFFile<ELFT> *Obj, const Elf_Sym *Symbol,
const Elf_Sym *FirstSym, StringRef StrTable,
@ -365,6 +367,7 @@ public:
void printSectionHeaders(const ELFO *Obj) override;
void printSymbols(const ELFO *Obj) override;
void printDynamicSymbols(const ELFO *Obj) override;
void printHashSymbols(const ELFO *Obj) override;
void printDynamicRelocations(const ELFO *Obj) override;
void printSymtabMessage(const ELFO *Obj, StringRef Name,
size_t Offset) override;
@ -1629,6 +1632,11 @@ void ELFDumper<ELFT>::printDynamicSymbols() {
ELFDumperStyle->printDynamicSymbols(ObjF->getELFFile());
}
template<class ELFT>
void ELFDumper<ELFT>::printHashSymbols() {
ELFDumperStyle->printHashSymbols(ObjF->getELFFile());
}
template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() {
ELFDumperStyle->printHashHistogram(ObjF->getELFFile());
}
@ -3176,19 +3184,18 @@ template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) {
template <class ELFT>
void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
this->dumper()->printSymbolsHelper(true);
}
template <class ELFT> void GNUStyle<ELFT>::printHashSymbols(const ELFO *Obj) {
if (this->dumper()->getDynamicStringTable().empty())
return;
auto StringTable = this->dumper()->getDynamicStringTable();
auto DynSyms = this->dumper()->dynamic_symbols();
auto GnuHash = this->dumper()->getGnuHashTable();
auto SysVHash = this->dumper()->getHashTable();
// If no hash or .gnu.hash found, try using symbol table
if (GnuHash == nullptr && SysVHash == nullptr)
this->dumper()->printSymbolsHelper(true);
// Try printing .hash
if (this->dumper()->getHashTable()) {
if (SysVHash) {
OS << "\n Symbol table of .hash for image:\n";
if (ELFT::Is64Bits)
OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
@ -3212,6 +3219,7 @@ void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) {
}
// Try printing .gnu.hash
auto GnuHash = this->dumper()->getGnuHashTable();
if (GnuHash) {
OS << "\n Symbol table of .gnu.hash for image:\n";
if (ELFT::Is64Bits)

View File

@ -46,6 +46,7 @@ public:
virtual void printSectionAsHex(StringRef SectionName) {}
virtual void printHashTable() { }
virtual void printGnuHashTable() { }
virtual void printHashSymbols() {}
virtual void printLoadName() {}
virtual void printVersionInfo() {}
virtual void printGroupSections() {}

View File

@ -136,6 +136,11 @@ namespace opts {
cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"),
cl::aliasopt(DynamicSymbols));
// -hash-symbols
cl::opt<bool> HashSymbols(
"hash-symbols",
cl::desc("Display the dynamic symbols derived from the hash section"));
// -unwind, -u
cl::opt<bool> UnwindInfo("unwind",
cl::desc("Display unwind information"));
@ -461,6 +466,8 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) {
Dumper->printSymbols();
if (opts::DynamicSymbols)
Dumper->printDynamicSymbols();
if (opts::HashSymbols)
Dumper->printHashSymbols();
if (opts::UnwindInfo)
Dumper->printUnwindInfo();
if (opts::DynamicTable)