[lld] r247625 - Add content to the .hash section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 14 16:14:05 PDT 2015


On Mon, Sep 14, 2015 at 3:08 PM, Rafael Espindola via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: rafael
> Date: Mon Sep 14 17:08:55 2015
> New Revision: 247625
>
> URL: http://llvm.org/viewvc/llvm-project?rev=247625&view=rev
> Log:
> Add content to the .hash section.
>
> This also sets DT_HASH.
>
> With this simple shared libraries created by lld can be loaded by the
> dynamic
> linker.
>
> Modified:
>     lld/trunk/ELF/Writer.cpp
>     lld/trunk/test/elf2/shared.s
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247625&r1=247624&r2=247625&view=diff
>
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Mon Sep 14 17:08:55 2015
> @@ -177,7 +177,7 @@ public:
>    }
>
>    void finalize() override {
> -    this->Header.sh_size = (NumVisible + 1) * sizeof(Elf_Sym);
> +    this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
>      this->Header.sh_link = StrTabSec.getSectionIndex();
>    }
>
> @@ -191,6 +191,7 @@ public:
>    }
>
>    StringTableSection<ELFT::Is64Bits> &getStrTabSec() { return StrTabSec; }
> +  unsigned getNumSymbols() const { return NumVisible + 1; }
>
>  private:
>    SymbolTable &Table;
> @@ -204,21 +205,71 @@ class HashTableSection final : public Ou
>    typedef typename ELFFile<ELFT>::Elf_Word Elf_Word;
>
>  public:
> -  HashTableSection(const SymbolTableSection<ELFT> &DynSymSec)
> +  HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
>        : OutputSectionBase<ELFT::Is64Bits>(".hash", SHT_HASH, SHF_ALLOC),
>          DynSymSec(DynSymSec) {
>      this->Header.sh_entsize = sizeof(Elf_Word);
>      this->Header.sh_addralign = sizeof(Elf_Word);
>    }
>
> +  void addSymbol(StringRef Name) {
> +    DynSymSec.addSymbol(Name);
> +    Hashes.push_back(hash(Name));
> +  }
> +
>    void finalize() override {
>      this->Header.sh_link = DynSymSec.getSectionIndex();
> +
> +    assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
> +    unsigned NumEntries = 2;                 // nbucket and nchain.
> +    NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
> +
> +    // Create as many buckets as there are symbols.
> +    // FIXME: This is simplistic. We can try to optimize it, but
> implementing
> +    // support for SHT_GNU_HASH is probably even more profitable.
> +    NumEntries += DynSymSec.getNumSymbols();
> +    this->Header.sh_size = NumEntries * sizeof(Elf_Word);
> +  }
> +
> +  void writeTo(uint8_t *Buf) override {
> +    unsigned NumSymbols = DynSymSec.getNumSymbols();
> +    auto *P = reinterpret_cast<Elf_Word *>(Buf);
> +    *P++ = NumSymbols; // nbucket
> +    *P++ = NumSymbols; // nchain
> +
> +    std::vector<uint32_t> Buckets;
> +    Buckets.resize(NumSymbols);
> +    std::vector<uint32_t> Chains;
> +    Chains.resize(NumSymbols);
>

Is there any reason not to write like

  std::vector<uint32_t> Buckets(NumSymbols);

instead of the two lines?

+
> +    for (unsigned I = 1; I < NumSymbols; ++I) {
> +      uint32_t Hash = Hashes[I - 1] % NumSymbols;
> +      Chains[I] = Buckets[Hash];
> +      Buckets[Hash] = I;
> +    }
> +
> +    for (uint32_t V : Buckets)
> +      *P++ = V;
> +    for (uint32_t V : Chains)
> +      *P++ = V;
>    }
>
> -  void writeTo(uint8_t *Buf) override {}
> +  SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
>
>  private:
> -  const SymbolTableSection<ELFT> &DynSymSec;
> +  uint32_t hash(StringRef Name) {
> +    uint32_t H = 0;
> +    for (char C : Name) {
> +      H = (H << 4) + C;
> +      uint32_t G = H & 0xf0000000;
> +      if (G)
> +        H ^= G >> 24;
> +      H &= ~G;
> +    }
> +    return H;
> +  }
> +  SymbolTableSection<ELFT> &DynSymSec;
> +  std::vector<uint32_t> Hashes;
>  };
>
>  template <class ELFT>
> @@ -228,11 +279,11 @@ class DynamicSection final : public Outp
>    typedef typename Base::Elf_Dyn Elf_Dyn;
>
>  public:
> -  DynamicSection(SymbolTable &SymTab, SymbolTableSection<ELFT> &DynSymSec)
> +  DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec)
>        : OutputSectionBase<ELFT::Is64Bits>(".dynamic", SHT_DYNAMIC,
>                                            SHF_ALLOC | SHF_WRITE),
> -        DynStrSec(DynSymSec.getStrTabSec()), DynSymSec(DynSymSec),
> -        SymTab(SymTab) {
> +        HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
> +        DynStrSec(DynSymSec.getStrTabSec()), SymTab(SymTab) {
>      typename Base::HeaderT &Header = this->Header;
>      Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
>      Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
> @@ -242,6 +293,7 @@ public:
>      ++NumEntries; // DT_SYMTAB
>      ++NumEntries; // DT_STRTAB
>      ++NumEntries; // DT_STRSZ
> +    ++NumEntries; // DT_HASH
>
>      StringRef RPath = Config->RPath;
>      if (!RPath.empty()) {
> @@ -279,6 +331,10 @@ public:
>      P->d_un.d_val = DynStrSec.data().size();
>      ++P;
>
> +    P->d_tag = DT_HASH;
> +    P->d_un.d_ptr = HashSec.getVA();
> +    ++P;
> +
>      StringRef RPath = Config->RPath;
>      if (!RPath.empty()) {
>        P->d_tag = DT_RUNPATH;
> @@ -300,8 +356,9 @@ public:
>    }
>
>  private:
> -  StringTableSection<ELFT::Is64Bits> &DynStrSec;
> +  HashTableSection<ELFT> &HashSec;
>    SymbolTableSection<ELFT> &DynSymSec;
> +  StringTableSection<ELFT::Is64Bits> &DynStrSec;
>    SymbolTable &SymTab;
>  };
>
> @@ -315,7 +372,7 @@ public:
>    typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
>    Writer(SymbolTable *T)
>        : SymTabSec(*this, *T, StrTabSec), DynSymSec(*this, *T, DynStrSec),
> -        DynamicSec(*T, DynSymSec), HashSec(DynSymSec) {}
> +        HashSec(DynSymSec), DynamicSec(*T, HashSec) {}
>    void run();
>
>    const OutputSection<ELFT> &getBSS() const {
> @@ -354,10 +411,10 @@ private:
>    SymbolTableSection<ELFT> SymTabSec;
>    SymbolTableSection<ELFT> DynSymSec;
>
> -  DynamicSection<ELFT> DynamicSec;
> -
>    HashTableSection<ELFT> HashSec;
>
> +  DynamicSection<ELFT> DynamicSec;
> +
>    InterpSection<ELFT::Is64Bits> InterpSec;
>
>    OutputSection<ELFT> *BSSSec = nullptr;
> @@ -651,7 +708,7 @@ template <class ELFT> void Writer<ELFT>:
>      // need to add the symbols use by dynamic relocations when producing
>      // an executable (ignoring --export-dynamic).
>      if (needsDynamicSections())
> -      DynSymSec.addSymbol(Name);
> +      HashSec.addSymbol(Name);
>    }
>
>    // Sort the common symbols by alignment as an heuristic to pack them
> better.
>
> Modified: lld/trunk/test/elf2/shared.s
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247625&r1=247624&r2=247625&view=diff
>
> ==============================================================================
> --- lld/trunk/test/elf2/shared.s (original)
> +++ lld/trunk/test/elf2/shared.s Mon Sep 14 17:08:55 2015
> @@ -3,48 +3,16 @@
>  // RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so
>  // RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s
>  // RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2
> -rpath foo -rpath bar %t.o %t2.so -o %t
> -// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols
> -section-data %t | FileCheck %s
> +// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols
> -section-data -hash-table %t | FileCheck %s
>  // REQUIRES: x86
>
> -
> -// test that .hash is linked to .dynsym
> -// SO:        Index: 4
> -// SO-NEXT:   Name: .dynsym
> -// SO-NEXT:   Type: SHT_DYNSYM
> -// SO-NEXT:   Flags [
> -// SO-NEXT:     SHF_ALLOC
> -// SO-NEXT:   ]
> -// SO-NEXT:   Address:
> -// SO-NEXT:   Offset:
> -// SO-NEXT:   Size:
> -// SO-NEXT:   Link:
> -// SO-NEXT:   Info:
> -// SO-NEXT:   AddressAlignment: 4
> -// SO-NEXT:   EntrySize: 16
> -// SO-NEXT: }
> -// SO-NEXT: Section {
> -// SO-NEXT:   Index: 5
> -// SO-NEXT:   Name: .hash
> -// SO-NEXT:   Type: SHT_HASH
> -// SO-NEXT:   Flags [
> -// SO-NEXT:     SHF_ALLOC
> -// SO-NEXT:   ]
> -// SO-NEXT:   Address:
> -// SO-NEXT:   Offset:
> -// SO-NEXT:   Size: 0
> -// SO-NEXT:   Link: 4
> -// SO-NEXT:   Info: 0
> -// SO-NEXT:   AddressAlignment: 4
> -// SO-NEXT:   EntrySize: 4
> -// SO-NEXT: }
> -
>  // Make sure .symtab is properly aligned.
>  // SO:      Name: .symtab
>  // SO-NEXT: Type: SHT_SYMTAB
>  // SO-NEXT: Flags [
>  // SO-NEXT: ]
>  // SO-NEXT: Address:
> -// SO-NEXT: Offset: 0x300C
> +// SO-NEXT: Offset: 0x400C
>  // SO-NEXT: Size:
>  // SO-NEXT: Link:
>  // SO-NEXT: Info:
> @@ -68,7 +36,9 @@
>  // CHECK-NEXT:   )
>  // CHECK-NEXT: }
>
> -// CHECK:        Name: .dynsym
> +// test that .hash is linked to .dynsym
> +// CHECK:        Index: 5
> +// CHECK-NEXT:   Name: .dynsym
>  // CHECK-NEXT:   Type: SHT_DYNSYM
>  // CHECK-NEXT:   Flags [
>  // CHECK-NEXT:     SHF_ALLOC
> @@ -86,6 +56,21 @@
>  // CHECK-NEXT:     0020:
>  // CHECK-NEXT:   )
>  // CHECK-NEXT: }
> +// CHECK-NEXT: Section {
> +// CHECK-NEXT:   Index: 6
> +// CHECK-NEXT:    Name: .hash
> +// CHECK-NEXT:    Type: SHT_HASH
> +// CHECK-NEXT:    Flags [
> +// CHECK-NEXT:      SHF_ALLOC
> +// CHECK-NEXT:    ]
> +// CHECK-NEXT:    Address: [[HASHADDR:.*]]
> +// CHECK-NEXT:    Offset:
> +// CHECK-NEXT:    Size:
> +// CHECK-NEXT:    Link: 5
> +// CHECK-NEXT:    Info: 0
> +// CHECK-NEXT:    AddressAlignment: 4
> +// CHECK-NEXT:    EntrySize: 4
> +
>
>  // CHECK:        Name: .dynamic
>  // CHECK-NEXT:   Type: SHT_DYNAMIC
> @@ -101,10 +86,7 @@
>  // CHECK-NEXT:   AddressAlignment: [[ALIGN:.*]]
>  // CHECK-NEXT:   EntrySize: 8
>  // CHECK-NEXT:   SectionData (
> -// CHECK-NEXT:     0000:
> -// CHECK-NEXT:     0010:
> -// CHECK-NEXT:     0020:
> -// CHECK-NEXT:   )
> +// CHECK:        )
>  // CHECK-NEXT: }
>
>  // CHECK:        Index: [[DYNSTR]]
> @@ -190,6 +172,7 @@
>  // CHECK-NEXT:   0x00000006 SYMTAB               [[DYNSYMADDR]]
>  // CHECK-NEXT:   0x00000005 STRTAB               [[DYNSTRADDR]]
>  // CHECK-NEXT:   0x0000000A STRSZ
> +// CHECK-NEXT:   0x00000004 HASH                 [[HASHADDR]]
>  // CHECK-NEXT:   0x0000001D RUNPATH              foo:bar
>  // CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary
> ({{.*}}2.so)
>  // CHECK-NEXT:   0x00000000 NULL                 0x0
> @@ -221,6 +204,13 @@
>  // CHECK-NEXT:   Alignment: [[ALIGN]]
>  // CHECK-NEXT: }
>
> +// CHECK:      HashTable {
> +// CHECK-NEXT:   Num Buckets: 3
> +// CHECK-NEXT:   Num Chains: 3
> +// CHECK-NEXT:   Buckets: [2, 0, 1]
> +// CHECK-NEXT:   Chains: [0, 0, 0]
> +// CHECK-NEXT: }
> +
>  .global _start
>  _start:
>  .long bar
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150914/0b829203/attachment.html>


More information about the llvm-commits mailing list