summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-02-28 05:53:47 +0000
committerRui Ueyama <ruiu@google.com>2017-02-28 05:53:47 +0000
commit6b776ad985e102cb206346c8ec6044fc12a32a0c (patch)
treebdda40cee496a0d5cd234c91a8214350cf243e7f
parentc647dcfba062256006ed2eb6a54193c4fb6e4622 (diff)
downloadbcm5719-llvm-6b776ad985e102cb206346c8ec6044fc12a32a0c.tar.gz
bcm5719-llvm-6b776ad985e102cb206346c8ec6044fc12a32a0c.zip
Refactor {Gnu,}HashTableSection classes.
In other places in LLD, we use write32<E> instead of Elf_Word. This patch uses the same technique in the hash table classes. The hash table classes needs improving as they have almost no comments. We at least need to describe the hash table structure and why we have to support two different on-disk hash tables for the same purpose. I'll do that later. llvm-svn: 296439
-rw-r--r--lld/ELF/SyntheticSections.cpp49
-rw-r--r--lld/ELF/SyntheticSections.h8
2 files changed, 31 insertions, 26 deletions
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 40a584d4f21..2e16d563226 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1461,7 +1461,7 @@ template <class ELFT>
unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) {
if (!NumHashed)
return 1;
- return NextPowerOf2((NumHashed - 1) / sizeof(Elf_Off));
+ return NextPowerOf2((NumHashed - 1) / sizeof(uintX_t));
}
template <class ELFT> void GnuHashTableSection<ELFT>::finalizeContents() {
@@ -1473,33 +1473,35 @@ template <class ELFT> void GnuHashTableSection<ELFT>::finalizeContents() {
this->OutSec->Entsize = this->Entsize;
this->OutSec->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex;
- this->Size = sizeof(Elf_Word) * 4 // Header
- + sizeof(Elf_Off) * MaskWords // Bloom Filter
- + sizeof(Elf_Word) * NBuckets // Hash Buckets
- + sizeof(Elf_Word) * NumHashed; // Hash Values
+ this->Size = sizeof(uint32_t) * 4 // Header
+ + sizeof(uintX_t) * MaskWords // Bloom Filter
+ + sizeof(uint32_t) * NBuckets // Hash Buckets
+ + sizeof(uint32_t) * NumHashed; // Hash Values
}
template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
- writeHeader(Buf);
+ Buf = writeHeader(Buf);
if (Symbols.empty())
return;
- writeBloomFilter(Buf);
+ Buf = writeBloomFilter(Buf);
writeHashTable(Buf);
}
template <class ELFT>
-void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) {
- auto *P = reinterpret_cast<Elf_Word *>(Buf);
- *P++ = NBuckets;
- *P++ = In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size();
- *P++ = MaskWords;
- *P++ = Shift2;
- Buf = reinterpret_cast<uint8_t *>(P);
+uint8_t *GnuHashTableSection<ELFT>::writeHeader(uint8_t *Buf) {
+ const endianness E = ELFT::TargetEndianness;
+ write32<E>(Buf, NBuckets);
+ write32<E>(Buf + 4, In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size());
+ write32<E>(Buf + 8, MaskWords);
+ write32<E>(Buf + 12, Shift2);
+ return Buf + 16;
}
template <class ELFT>
-void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) {
- unsigned C = sizeof(Elf_Off) * 8;
+uint8_t *GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *Buf) {
+ typedef typename ELFT::Off Elf_Off;
+
+ const unsigned C = sizeof(uintX_t) * 8;
auto *Masks = reinterpret_cast<Elf_Off *>(Buf);
for (const SymbolData &Sym : Symbols) {
@@ -1508,11 +1510,14 @@ void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) {
(uintX_t(1) << ((Sym.Hash >> Shift2) % C));
Masks[Pos] |= V;
}
- Buf += sizeof(Elf_Off) * MaskWords;
+ return Buf + sizeof(uintX_t) * MaskWords;
}
template <class ELFT>
void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) {
+ // A 32-bit integer type in the target endianness.
+ typedef typename ELFT::Word Elf_Word;
+
Elf_Word *Buckets = reinterpret_cast<Elf_Word *>(Buf);
Elf_Word *Values = Buckets + NBuckets;
@@ -1573,8 +1578,8 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) {
template <class ELFT>
HashTableSection<ELFT>::HashTableSection()
- : SyntheticSection(SHF_ALLOC, SHT_HASH, sizeof(Elf_Word), ".hash") {
- this->Entsize = sizeof(Elf_Word);
+ : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") {
+ this->Entsize = 4;
}
template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
@@ -1588,11 +1593,15 @@ template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
// FIXME: This is simplistic. We can try to optimize it, but implementing
// support for SHT_GNU_HASH is probably even more profitable.
NumEntries += In<ELFT>::DynSymTab->getNumSymbols();
- this->Size = NumEntries * sizeof(Elf_Word);
+ this->Size = NumEntries * 4;
}
template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ // A 32-bit integer type in the target endianness.
+ typedef typename ELFT::Word Elf_Word;
+
unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols();
+
auto *P = reinterpret_cast<Elf_Word *>(Buf);
*P++ = NumSymbols; // nbucket
*P++ = NumSymbols; // nchain
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 0aef47881f3..0174b619e5c 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -432,8 +432,6 @@ private:
// https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
template <class ELFT>
class GnuHashTableSection final : public SyntheticSection {
- typedef typename ELFT::Off Elf_Off;
- typedef typename ELFT::Word Elf_Word;
typedef typename ELFT::uint uintX_t;
public:
@@ -450,8 +448,8 @@ private:
static unsigned calcNBuckets(unsigned NumHashed);
static unsigned calcMaskWords(unsigned NumHashed);
- void writeHeader(uint8_t *&Buf);
- void writeBloomFilter(uint8_t *&Buf);
+ uint8_t *writeHeader(uint8_t *Buf);
+ uint8_t *writeBloomFilter(uint8_t *Buf);
void writeHashTable(uint8_t *Buf);
struct SymbolData {
@@ -469,8 +467,6 @@ private:
};
template <class ELFT> class HashTableSection final : public SyntheticSection {
- typedef typename ELFT::Word Elf_Word;
-
public:
HashTableSection();
void finalizeContents() override;
OpenPOWER on IntegriCloud