[llvm] r287786 - llvm-readobj: Use hash tables to print dynamic symbols.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 23 11:02:48 PST 2016


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/ELFDumper.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