[lld] r247625 - Add content to the .hash section.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 15:08:55 PDT 2015
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);
+
+ 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
More information about the llvm-commits
mailing list