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
This commit is contained in:
Rui Ueyama 2017-02-28 05:53:47 +00:00
parent c647dcfba0
commit 6b776ad985
2 changed files with 31 additions and 26 deletions

View File

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

View File

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