diff options
| author | Eugene Leviant <eleviant@accesssoftek.com> | 2016-11-18 06:44:18 +0000 |
|---|---|---|
| committer | Eugene Leviant <eleviant@accesssoftek.com> | 2016-11-18 06:44:18 +0000 |
| commit | be809a7125c3214ab067d0861aa2fe848ac40b9d (patch) | |
| tree | 7f92a21a0e305da5a6efb5417f2102d49bc0351f /lld/ELF/OutputSections.cpp | |
| parent | f9980200aa1da6df925b03b4f5cecb252dd57bdd (diff) | |
| download | bcm5719-llvm-be809a7125c3214ab067d0861aa2fe848ac40b9d.tar.gz bcm5719-llvm-be809a7125c3214ab067d0861aa2fe848ac40b9d.zip | |
[ELF] Convert GnuHashTableSection to input section
Differential revision: https://reviews.llvm.org/D26792
llvm-svn: 287322
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index c98170dfc42..8270be0dc98 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -179,153 +179,6 @@ template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) { } } -static uint32_t hashGnu(StringRef Name) { - uint32_t H = 5381; - for (uint8_t C : Name) - H = (H << 5) + H + C; - return H; -} - -template <class ELFT> -GnuHashTableSection<ELFT>::GnuHashTableSection() - : OutputSectionBase(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) { - this->Entsize = ELFT::Is64Bits ? 0 : 4; - this->Addralign = sizeof(uintX_t); -} - -template <class ELFT> -unsigned GnuHashTableSection<ELFT>::calcNBuckets(unsigned NumHashed) { - if (!NumHashed) - return 0; - - // These values are prime numbers which are not greater than 2^(N-1) + 1. - // In result, for any particular NumHashed we return a prime number - // which is not greater than NumHashed. - static const unsigned Primes[] = { - 1, 1, 3, 3, 7, 13, 31, 61, 127, 251, - 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071}; - - return Primes[std::min<unsigned>(Log2_32_Ceil(NumHashed), - array_lengthof(Primes) - 1)]; -} - -// Bloom filter estimation: at least 8 bits for each hashed symbol. -// GNU Hash table requirement: it should be a power of 2, -// the minimum value is 1, even for an empty table. -// Expected results for a 32-bit target: -// calcMaskWords(0..4) = 1 -// calcMaskWords(5..8) = 2 -// calcMaskWords(9..16) = 4 -// For a 64-bit target: -// calcMaskWords(0..8) = 1 -// calcMaskWords(9..16) = 2 -// calcMaskWords(17..32) = 4 -template <class ELFT> -unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) { - if (!NumHashed) - return 1; - return NextPowerOf2((NumHashed - 1) / sizeof(Elf_Off)); -} - -template <class ELFT> void GnuHashTableSection<ELFT>::finalize() { - unsigned NumHashed = Symbols.size(); - NBuckets = calcNBuckets(NumHashed); - MaskWords = calcMaskWords(NumHashed); - // Second hash shift estimation: just predefined values. - Shift2 = ELFT::Is64Bits ? 6 : 5; - - this->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 -} - -template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) { - writeHeader(Buf); - if (Symbols.empty()) - return; - 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); -} - -template <class ELFT> -void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) { - unsigned C = sizeof(Elf_Off) * 8; - - auto *Masks = reinterpret_cast<Elf_Off *>(Buf); - for (const SymbolData &Sym : Symbols) { - size_t Pos = (Sym.Hash / C) & (MaskWords - 1); - uintX_t V = (uintX_t(1) << (Sym.Hash % C)) | - (uintX_t(1) << ((Sym.Hash >> Shift2) % C)); - Masks[Pos] |= V; - } - Buf += sizeof(Elf_Off) * MaskWords; -} - -template <class ELFT> -void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) { - Elf_Word *Buckets = reinterpret_cast<Elf_Word *>(Buf); - Elf_Word *Values = Buckets + NBuckets; - - int PrevBucket = -1; - int I = 0; - for (const SymbolData &Sym : Symbols) { - int Bucket = Sym.Hash % NBuckets; - assert(PrevBucket <= Bucket); - if (Bucket != PrevBucket) { - Buckets[Bucket] = Sym.Body->DynsymIndex; - PrevBucket = Bucket; - if (I > 0) - Values[I - 1] |= 1; - } - Values[I] = Sym.Hash & ~1; - ++I; - } - if (I > 0) - Values[I - 1] |= 1; -} - -// Add symbols to this symbol hash table. Note that this function -// destructively sort a given vector -- which is needed because -// GNU-style hash table places some sorting requirements. -template <class ELFT> -void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) { - // Ideally this will just be 'auto' but GCC 6.1 is not able - // to deduce it correctly. - std::vector<SymbolTableEntry>::iterator Mid = - std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { - return S.Symbol->isUndefined(); - }); - if (Mid == V.end()) - return; - for (auto I = Mid, E = V.end(); I != E; ++I) { - SymbolBody *B = I->Symbol; - size_t StrOff = I->StrTabOffset; - Symbols.push_back({B, StrOff, hashGnu(B->getName())}); - } - - unsigned NBuckets = calcNBuckets(Symbols.size()); - std::stable_sort(Symbols.begin(), Symbols.end(), - [&](const SymbolData &L, const SymbolData &R) { - return L.Hash % NBuckets < R.Hash % NBuckets; - }); - - V.erase(Mid, V.end()); - for (const SymbolData &Sym : Symbols) - V.push_back({Sym.Body, Sym.STName}); -} - // Returns the number of version definition entries. Because the first entry // is for the version definition itself, it is the number of versioned symbols // plus one. Note that we don't support multiple versions yet. @@ -1085,11 +938,6 @@ template class PltSection<ELF32BE>; template class PltSection<ELF64LE>; template class PltSection<ELF64BE>; -template class GnuHashTableSection<ELF32LE>; -template class GnuHashTableSection<ELF32BE>; -template class GnuHashTableSection<ELF64LE>; -template class GnuHashTableSection<ELF64BE>; - template class HashTableSection<ELF32LE>; template class HashTableSection<ELF32BE>; template class HashTableSection<ELF64LE>; |

