[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