<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>