[llvm] r287786 - llvm-readobj: Use hash tables to print dynamic symbols.
Hemant Kulkarni via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 23 11:33:50 PST 2016
This is not objdump change. This is ELFDumper change in llvm-readobj.
The GNU style used symbols by using DT_* tags based sections alone. With this change, GNU style will go over the hash sections and print using the DT_* tags based sections. AFAIK there is no tool that can help validate if there is any issue with these linker created hash sections without running the binary.
Are there any issues with this change ?
--
Hemant Kulkarni
khemant at codeaurora.org
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation
-----Original Message-----
From: davide.italiano at gmail.com [mailto:davide.italiano at gmail.com] On Behalf Of Davide Italiano
Sent: Wednesday, November 23, 2016 1:03 PM
To: Hemant Kulkarni <khemant at codeaurora.org>
Cc: llvm-commits <llvm-commits at lists.llvm.org>
Subject: Re: [llvm] r287786 - llvm-readobj: Use hash tables to print dynamic symbols.
On Wed, Nov 23, 2016 at 10:04 AM, Hemant Kulkarni via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> Author: khemant
> Date: Wed Nov 23 12:04:23 2016
> New Revision: 287786
>
> URL: http://llvm.org/viewvc/llvm-project?rev=287786&view=rev
> Log:
> llvm-readobj: Use hash tables to print dynamic symbols.
>
> -symbols prints both .symtab and .dynsym symbols for GNU style in ELF.
> -dyn-symbols prints symbols looking up through hash tables. This helps validate hash tables.
>
hrmm, what's the rationale behind this change? Are you trying to be compatible with what GNU objdump produces or what?
Maybe next time you can discuss it first or send a review? There are many people who can review (me/Michael/Eric/Rafael etc..).
> Modified:
> llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test
> llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
>
> Modified: llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj
> /gnu-symbols.test?rev=287786&r1=287785&r2=287786&view=diff
> ======================================================================
> ========
> --- llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test (original)
> +++ llvm/trunk/test/tools/llvm-readobj/gnu-symbols.test Wed Nov 23
> +++ 12:04:23 2016
> @@ -4,6 +4,8 @@ RUN: llvm-readobj -symbols %p/Inputs/rel
> 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
>
> ELF32: Symbol table '.symtab' contains 5 entries:
> ELF32-NEXT: Num: Value Size Type Bind Vis Ndx Name
> @@ -44,3 +46,29 @@ DYN-NEXT: 8: 0000000000200268 0
> 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
> +
> +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 at 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 at 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 at GCC_3.0
> +HASH-NEXT: 8 1: 00000000 0 FUNC GLOBAL DEFAULT UND puts at 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 at 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 at GLIBC_2.0
> +HASH-NEXT: 11 2: 00000000 0 FUNC WEAK DEFAULT UND __cxa_finalize at 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@
>
> Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFD
> umper.cpp?rev=287786&r1=287785&r2=287786&view=diff
> ======================================================================
> ========
> --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
> +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Wed Nov 23 12:04:23
> +++ 2016
> @@ -328,6 +328,8 @@ private:
> OS.flush();
> return OS;
> }
> + void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym,
> + StringRef StrTable, uint32_t Bucket);
> void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
> const Elf_Rela &R, bool IsRela);
> void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const
> Elf_Sym *First, @@ -2812,15 +2814,120 @@ void GNUStyle<ELFT>::printSymbol(const E
> printField(Entry);
> OS << "\n";
> }
> +template <class ELFT>
> +void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym,
> + uint32_t Sym, StringRef StrTable,
> + uint32_t Bucket) {
> + std::string Num, Buc, Name, Value, Size, Binding, Type, Visibility,
> +Section;
> + unsigned Width, Bias = 0;
> + if (ELFT::Is64Bits) {
> + Bias = 8;
> + Width = 16;
> + } else {
> + Bias = 0;
> + Width = 8;
> + }
> + Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias,
> + 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias};
> + Num = to_string(format_decimal(Sym, 5));
> + Buc = to_string(format_decimal(Bucket, 3)) + ":";
> +
> + const auto Symbol = FirstSym + Sym;
> + Value = to_string(format_hex_no_prefix(Symbol->st_value, Width));
> + Size = to_string(format_decimal(Symbol->st_size, 5));
> + unsigned char SymbolType = Symbol->getType();
> + if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU &&
> + SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
> + Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
> + else
> + Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes));
> + unsigned Vis = Symbol->getVisibility();
> + Binding = printEnum(Symbol->getBinding(),
> +makeArrayRef(ElfSymbolBindings));
> + Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities));
> + Section = getSymbolSectionNdx(Obj, Symbol, FirstSym);
> + Name = this->dumper()->getFullSymbolName(Symbol, StrTable, true);
> + Fields[0].Str = Num;
> + Fields[1].Str = Buc;
> + Fields[2].Str = Value;
> + Fields[3].Str = Size;
> + Fields[4].Str = Type;
> + Fields[5].Str = Binding;
> + Fields[6].Str = Visibility;
> + Fields[7].Str = Section;
> + Fields[8].Str = Name;
> + for (auto &Entry : Fields)
> + printField(Entry);
> + 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) {
> - this->dumper()->printSymbolsHelper(true);
> + if (this->dumper()->getDynamicStringTable().size() == 0)
> + 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()) {
> + OS << "\n Symbol table of .hash for image:\n";
> + if (ELFT::Is64Bits)
> + OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
> + else
> + OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
> + OS << "\n";
> +
> + uint32_t NBuckets = SysVHash->nbucket;
> + uint32_t NChains = SysVHash->nchain;
> + auto Buckets = SysVHash->buckets();
> + auto Chains = SysVHash->chains();
> + for (uint32_t Buc = 0; Buc < NBuckets; Buc++) {
> + if (Buckets[Buc] == ELF::STN_UNDEF)
> + continue;
> + for (uint32_t Ch = Buckets[Buc]; Ch < NChains; Ch = Chains[Ch]) {
> + if (Ch == ELF::STN_UNDEF)
> + break;
> + printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc);
> + }
> + }
> + }
> +
> + // Try printing .gnu.hash
> + if (GnuHash) {
> + OS << "\n Symbol table of .gnu.hash for image:\n";
> + if (ELFT::Is64Bits)
> + OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
> + else
> + OS << " Num Buc: Value Size Type Bind Vis Ndx Name";
> + OS << "\n";
> + uint32_t NBuckets = GnuHash->nbuckets;
> + auto Buckets = GnuHash->buckets();
> + for (uint32_t Buc = 0; Buc < NBuckets; Buc++) {
> + if (Buckets[Buc] == ELF::STN_UNDEF)
> + continue;
> + uint32_t Index = Buckets[Buc];
> + uint32_t GnuHashable = Index - GnuHash->symndx;
> + // Print whole chain
> + while (true) {
> + printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc);
> + // Chain ends at symbol with stopper bit
> + if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1)
> + break;
> + }
> + }
> + }
> }
>
> static inline std::string printPhdrFlags(unsigned Flag) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
--
Davide
"There are no solved problems; there are only problems that are more or less solved" -- Henri Poincare
More information about the llvm-commits
mailing list