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:
parent
c647dcfba0
commit
6b776ad985
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue