summaryrefslogtreecommitdiffstats
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
authorEugene Leviant <eleviant@accesssoftek.com>2016-11-18 06:44:18 +0000
committerEugene Leviant <eleviant@accesssoftek.com>2016-11-18 06:44:18 +0000
commitbe809a7125c3214ab067d0861aa2fe848ac40b9d (patch)
tree7f92a21a0e305da5a6efb5417f2102d49bc0351f /lld/ELF/OutputSections.cpp
parentf9980200aa1da6df925b03b4f5cecb252dd57bdd (diff)
downloadbcm5719-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.cpp152
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>;
OpenPOWER on IntegriCloud