<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Sep 14, 2015 at 3:08 PM, Rafael Espindola via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rafael<br>
Date: Mon Sep 14 17:08:55 2015<br>
New Revision: 247625<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=247625&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=247625&view=rev</a><br>
Log:<br>
Add content to the .hash section.<br>
<br>
This also sets DT_HASH.<br>
<br>
With this simple shared libraries created by lld can be loaded by the dynamic<br>
linker.<br>
<br>
Modified:<br>
    lld/trunk/ELF/Writer.cpp<br>
    lld/trunk/test/elf2/shared.s<br>
<br>
Modified: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247625&r1=247624&r2=247625&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247625&r1=247624&r2=247625&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (original)<br>
+++ lld/trunk/ELF/Writer.cpp Mon Sep 14 17:08:55 2015<br>
@@ -177,7 +177,7 @@ public:<br>
   }<br>
<br>
   void finalize() override {<br>
-    this->Header.sh_size = (NumVisible + 1) * sizeof(Elf_Sym);<br>
+    this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);<br>
     this->Header.sh_link = StrTabSec.getSectionIndex();<br>
   }<br>
<br>
@@ -191,6 +191,7 @@ public:<br>
   }<br>
<br>
   StringTableSection<ELFT::Is64Bits> &getStrTabSec() { return StrTabSec; }<br>
+  unsigned getNumSymbols() const { return NumVisible + 1; }<br>
<br>
 private:<br>
   SymbolTable &Table;<br>
@@ -204,21 +205,71 @@ class HashTableSection final : public Ou<br>
   typedef typename ELFFile<ELFT>::Elf_Word Elf_Word;<br>
<br>
 public:<br>
-  HashTableSection(const SymbolTableSection<ELFT> &DynSymSec)<br>
+  HashTableSection(SymbolTableSection<ELFT> &DynSymSec)<br>
       : OutputSectionBase<ELFT::Is64Bits>(".hash", SHT_HASH, SHF_ALLOC),<br>
         DynSymSec(DynSymSec) {<br>
     this->Header.sh_entsize = sizeof(Elf_Word);<br>
     this->Header.sh_addralign = sizeof(Elf_Word);<br>
   }<br>
<br>
+  void addSymbol(StringRef Name) {<br>
+    DynSymSec.addSymbol(Name);<br>
+    Hashes.push_back(hash(Name));<br>
+  }<br>
+<br>
   void finalize() override {<br>
     this->Header.sh_link = DynSymSec.getSectionIndex();<br>
+<br>
+    assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);<br>
+    unsigned NumEntries = 2;                 // nbucket and nchain.<br>
+    NumEntries += DynSymSec.getNumSymbols(); // The chain entries.<br>
+<br>
+    // Create as many buckets as there are symbols.<br>
+    // FIXME: This is simplistic. We can try to optimize it, but implementing<br>
+    // support for SHT_GNU_HASH is probably even more profitable.<br>
+    NumEntries += DynSymSec.getNumSymbols();<br>
+    this->Header.sh_size = NumEntries * sizeof(Elf_Word);<br>
+  }<br>
+<br>
+  void writeTo(uint8_t *Buf) override {<br>
+    unsigned NumSymbols = DynSymSec.getNumSymbols();<br>
+    auto *P = reinterpret_cast<Elf_Word *>(Buf);<br>
+    *P++ = NumSymbols; // nbucket<br>
+    *P++ = NumSymbols; // nchain<br>
+<br>
+    std::vector<uint32_t> Buckets;<br>
+    Buckets.resize(NumSymbols);<br>
+    std::vector<uint32_t> Chains;<br>
+    Chains.resize(NumSymbols);<br></blockquote><div><br></div><div>Is there any reason not to write like</div><div><br></div><div>  std::vector<uint32_t> Buckets(NumSymbols);</div><div><br></div><div>instead of the two lines?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+    for (unsigned I = 1; I < NumSymbols; ++I) {<br>
+      uint32_t Hash = Hashes[I - 1] % NumSymbols;<br>
+      Chains[I] = Buckets[Hash];<br>
+      Buckets[Hash] = I;<br>
+    }<br>
+<br>
+    for (uint32_t V : Buckets)<br>
+      *P++ = V;<br>
+    for (uint32_t V : Chains)<br>
+      *P++ = V;<br>
   }<br>
<br>
-  void writeTo(uint8_t *Buf) override {}<br>
+  SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }<br>
<br>
 private:<br>
-  const SymbolTableSection<ELFT> &DynSymSec;<br>
+  uint32_t hash(StringRef Name) {<br>
+    uint32_t H = 0;<br>
+    for (char C : Name) {<br>
+      H = (H << 4) + C;<br>
+      uint32_t G = H & 0xf0000000;<br>
+      if (G)<br>
+        H ^= G >> 24;<br>
+      H &= ~G;<br>
+    }<br>
+    return H;<br>
+  }<br>
+  SymbolTableSection<ELFT> &DynSymSec;<br>
+  std::vector<uint32_t> Hashes;<br>
 };<br>
<br>
 template <class ELFT><br>
@@ -228,11 +279,11 @@ class DynamicSection final : public Outp<br>
   typedef typename Base::Elf_Dyn Elf_Dyn;<br>
<br>
 public:<br>
-  DynamicSection(SymbolTable &SymTab, SymbolTableSection<ELFT> &DynSymSec)<br>
+  DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec)<br>
       : OutputSectionBase<ELFT::Is64Bits>(".dynamic", SHT_DYNAMIC,<br>
                                           SHF_ALLOC | SHF_WRITE),<br>
-        DynStrSec(DynSymSec.getStrTabSec()), DynSymSec(DynSymSec),<br>
-        SymTab(SymTab) {<br>
+        HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),<br>
+        DynStrSec(DynSymSec.getStrTabSec()), SymTab(SymTab) {<br>
     typename Base::HeaderT &Header = this->Header;<br>
     Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;<br>
     Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;<br>
@@ -242,6 +293,7 @@ public:<br>
     ++NumEntries; // DT_SYMTAB<br>
     ++NumEntries; // DT_STRTAB<br>
     ++NumEntries; // DT_STRSZ<br>
+    ++NumEntries; // DT_HASH<br>
<br>
     StringRef RPath = Config->RPath;<br>
     if (!RPath.empty()) {<br>
@@ -279,6 +331,10 @@ public:<br>
     P->d_un.d_val = DynStrSec.data().size();<br>
     ++P;<br>
<br>
+    P->d_tag = DT_HASH;<br>
+    P->d_un.d_ptr = HashSec.getVA();<br>
+    ++P;<br>
+<br>
     StringRef RPath = Config->RPath;<br>
     if (!RPath.empty()) {<br>
       P->d_tag = DT_RUNPATH;<br>
@@ -300,8 +356,9 @@ public:<br>
   }<br>
<br>
 private:<br>
-  StringTableSection<ELFT::Is64Bits> &DynStrSec;<br>
+  HashTableSection<ELFT> &HashSec;<br>
   SymbolTableSection<ELFT> &DynSymSec;<br>
+  StringTableSection<ELFT::Is64Bits> &DynStrSec;<br>
   SymbolTable &SymTab;<br>
 };<br>
<br>
@@ -315,7 +372,7 @@ public:<br>
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;<br>
   Writer(SymbolTable *T)<br>
       : SymTabSec(*this, *T, StrTabSec), DynSymSec(*this, *T, DynStrSec),<br>
-        DynamicSec(*T, DynSymSec), HashSec(DynSymSec) {}<br>
+        HashSec(DynSymSec), DynamicSec(*T, HashSec) {}<br>
   void run();<br>
<br>
   const OutputSection<ELFT> &getBSS() const {<br>
@@ -354,10 +411,10 @@ private:<br>
   SymbolTableSection<ELFT> SymTabSec;<br>
   SymbolTableSection<ELFT> DynSymSec;<br>
<br>
-  DynamicSection<ELFT> DynamicSec;<br>
-<br>
   HashTableSection<ELFT> HashSec;<br>
<br>
+  DynamicSection<ELFT> DynamicSec;<br>
+<br>
   InterpSection<ELFT::Is64Bits> InterpSec;<br>
<br>
   OutputSection<ELFT> *BSSSec = nullptr;<br>
@@ -651,7 +708,7 @@ template <class ELFT> void Writer<ELFT>:<br>
     // need to add the symbols use by dynamic relocations when producing<br>
     // an executable (ignoring --export-dynamic).<br>
     if (needsDynamicSections())<br>
-      DynSymSec.addSymbol(Name);<br>
+      HashSec.addSymbol(Name);<br>
   }<br>
<br>
   // Sort the common symbols by alignment as an heuristic to pack them better.<br>
<br>
Modified: lld/trunk/test/elf2/shared.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247625&r1=247624&r2=247625&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247625&r1=247624&r2=247625&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/elf2/shared.s (original)<br>
+++ lld/trunk/test/elf2/shared.s Mon Sep 14 17:08:55 2015<br>
@@ -3,48 +3,16 @@<br>
 // RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so<br>
 // RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s<br>
 // RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %t2.so -o %t<br>
-// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck %s<br>
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s<br>
 // REQUIRES: x86<br>
<br>
-<br>
-// test that .hash is linked to .dynsym<br>
-// SO:        Index: 4<br>
-// SO-NEXT:   Name: .dynsym<br>
-// SO-NEXT:   Type: SHT_DYNSYM<br>
-// SO-NEXT:   Flags [<br>
-// SO-NEXT:     SHF_ALLOC<br>
-// SO-NEXT:   ]<br>
-// SO-NEXT:   Address:<br>
-// SO-NEXT:   Offset:<br>
-// SO-NEXT:   Size:<br>
-// SO-NEXT:   Link:<br>
-// SO-NEXT:   Info:<br>
-// SO-NEXT:   AddressAlignment: 4<br>
-// SO-NEXT:   EntrySize: 16<br>
-// SO-NEXT: }<br>
-// SO-NEXT: Section {<br>
-// SO-NEXT:   Index: 5<br>
-// SO-NEXT:   Name: .hash<br>
-// SO-NEXT:   Type: SHT_HASH<br>
-// SO-NEXT:   Flags [<br>
-// SO-NEXT:     SHF_ALLOC<br>
-// SO-NEXT:   ]<br>
-// SO-NEXT:   Address:<br>
-// SO-NEXT:   Offset:<br>
-// SO-NEXT:   Size: 0<br>
-// SO-NEXT:   Link: 4<br>
-// SO-NEXT:   Info: 0<br>
-// SO-NEXT:   AddressAlignment: 4<br>
-// SO-NEXT:   EntrySize: 4<br>
-// SO-NEXT: }<br>
-<br>
 // Make sure .symtab is properly aligned.<br>
 // SO:      Name: .symtab<br>
 // SO-NEXT: Type: SHT_SYMTAB<br>
 // SO-NEXT: Flags [<br>
 // SO-NEXT: ]<br>
 // SO-NEXT: Address:<br>
-// SO-NEXT: Offset: 0x300C<br>
+// SO-NEXT: Offset: 0x400C<br>
 // SO-NEXT: Size:<br>
 // SO-NEXT: Link:<br>
 // SO-NEXT: Info:<br>
@@ -68,7 +36,9 @@<br>
 // CHECK-NEXT:   )<br>
 // CHECK-NEXT: }<br>
<br>
-// CHECK:        Name: .dynsym<br>
+// test that .hash is linked to .dynsym<br>
+// CHECK:        Index: 5<br>
+// CHECK-NEXT:   Name: .dynsym<br>
 // CHECK-NEXT:   Type: SHT_DYNSYM<br>
 // CHECK-NEXT:   Flags [<br>
 // CHECK-NEXT:     SHF_ALLOC<br>
@@ -86,6 +56,21 @@<br>
 // CHECK-NEXT:     0020:<br>
 // CHECK-NEXT:   )<br>
 // CHECK-NEXT: }<br>
+// CHECK-NEXT: Section {<br>
+// CHECK-NEXT:   Index: 6<br>
+// CHECK-NEXT:    Name: .hash<br>
+// CHECK-NEXT:    Type: SHT_HASH<br>
+// CHECK-NEXT:    Flags [<br>
+// CHECK-NEXT:      SHF_ALLOC<br>
+// CHECK-NEXT:    ]<br>
+// CHECK-NEXT:    Address: [[HASHADDR:.*]]<br>
+// CHECK-NEXT:    Offset:<br>
+// CHECK-NEXT:    Size:<br>
+// CHECK-NEXT:    Link: 5<br>
+// CHECK-NEXT:    Info: 0<br>
+// CHECK-NEXT:    AddressAlignment: 4<br>
+// CHECK-NEXT:    EntrySize: 4<br>
+<br>
<br>
 // CHECK:        Name: .dynamic<br>
 // CHECK-NEXT:   Type: SHT_DYNAMIC<br>
@@ -101,10 +86,7 @@<br>
 // CHECK-NEXT:   AddressAlignment: [[ALIGN:.*]]<br>
 // CHECK-NEXT:   EntrySize: 8<br>
 // CHECK-NEXT:   SectionData (<br>
-// CHECK-NEXT:     0000:<br>
-// CHECK-NEXT:     0010:<br>
-// CHECK-NEXT:     0020:<br>
-// CHECK-NEXT:   )<br>
+// CHECK:        )<br>
 // CHECK-NEXT: }<br>
<br>
 // CHECK:        Index: [[DYNSTR]]<br>
@@ -190,6 +172,7 @@<br>
 // CHECK-NEXT:   0x00000006 SYMTAB               [[DYNSYMADDR]]<br>
 // CHECK-NEXT:   0x00000005 STRTAB               [[DYNSTRADDR]]<br>
 // CHECK-NEXT:   0x0000000A STRSZ<br>
+// CHECK-NEXT:   0x00000004 HASH                 [[HASHADDR]]<br>
 // CHECK-NEXT:   0x0000001D RUNPATH              foo:bar<br>
 // CHECK-NEXT:   0x00000001 NEEDED               SharedLibrary ({{.*}}2.so)<br>
 // CHECK-NEXT:   0x00000000 NULL                 0x0<br>
@@ -221,6 +204,13 @@<br>
 // CHECK-NEXT:   Alignment: [[ALIGN]]<br>
 // CHECK-NEXT: }<br>
<br>
+// CHECK:      HashTable {<br>
+// CHECK-NEXT:   Num Buckets: 3<br>
+// CHECK-NEXT:   Num Chains: 3<br>
+// CHECK-NEXT:   Buckets: [2, 0, 1]<br>
+// CHECK-NEXT:   Chains: [0, 0, 0]<br>
+// CHECK-NEXT: }<br>
+<br>
 .global _start<br>
 _start:<br>
 .long bar<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>