File indexing completed on 2024-05-12 05:43:30

0001 /*
0002     Copyright (C) 2015 Volker Krause <vkrause@kde.org>
0003 
0004     This program is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program.  If not, see <https://www.gnu.org/licenses/>.
0016 */
0017 
0018 #include "elfsysvhashsection.h"
0019 #include "elfsymboltablesection.h"
0020 
0021 #include <elf.h>
0022 #include <cassert>
0023 
0024 ElfSysvHashSection::ElfSysvHashSection(ElfFile* file, ElfSectionHeader* shdr):
0025     ElfHashSection(file, shdr)
0026 {
0027 }
0028 
0029 ElfSysvHashSection::~ElfSysvHashSection() = default;
0030 
0031 uint32_t ElfSysvHashSection::bucketCount() const
0032 {
0033     return *reinterpret_cast<const uint32_t*>(rawData());
0034 }
0035 
0036 uint32_t ElfSysvHashSection::bucket(uint32_t index) const
0037 {
0038     return *(reinterpret_cast<const uint32_t*>(rawData()) + 2 + index);
0039 }
0040 
0041 uint32_t ElfSysvHashSection::chainCount() const
0042 {
0043     return *(reinterpret_cast<const uint32_t*>(rawData()) + 1);
0044 }
0045 
0046 uint32_t ElfSysvHashSection::chain(uint32_t index) const
0047 {
0048     return *(reinterpret_cast<const uint32_t*>(rawData()) + 2 + bucketCount() + index);
0049 }
0050 
0051 uint32_t ElfSysvHashSection::hash(const char* name)
0052 {
0053     unsigned long h = 0, g;
0054     while (*name)
0055     {
0056         h = (h << 4) + *name++;
0057         if ((g = h & 0xf0000000))
0058             h ^= g >> 24;
0059         h &= ~g;
0060     }
0061     return h;
0062 }
0063 
0064 ElfSymbolTableEntry* ElfSysvHashSection::lookup(const char* name) const
0065 {
0066     const auto x = hash(name);
0067 
0068     const auto symTab = linkedSection<ElfSymbolTableSection>();
0069     assert(symTab);
0070     auto y = bucket(x % bucketCount());
0071     while (y != STN_UNDEF) {
0072         const auto entry = symTab->entry(y);
0073         if (strcmp(entry->name(), name) == 0)
0074             return entry;
0075         y = chain(y);
0076     }
0077 
0078     return nullptr;
0079 }
0080 
0081 QVector<uint32_t> ElfSysvHashSection::histogram() const
0082 {
0083     QVector<uint32_t> hist;
0084     for (uint i = 0; i < bucketCount(); ++i) {
0085         int count = 0;
0086 
0087         auto y = bucket(i);
0088         while (y != STN_UNDEF) {
0089             ++count;
0090             y = chain(y);
0091         }
0092 
0093         hist.resize(std::max(hist.size(), count + 1));
0094         hist[count]++;
0095     }
0096     return hist;
0097 }
0098 
0099 double ElfSysvHashSection::averagePrefixLength() const
0100 {
0101     int sum = 0;
0102     int count = 0;
0103 
0104     const auto symTab = linkedSection<ElfSymbolTableSection>();
0105     assert(symTab);
0106 
0107     for (uint i = 0; i < bucketCount(); ++i) {
0108         auto y1 = bucket(i);
0109         while (y1 != STN_UNDEF) {
0110             const auto entry1 = symTab->entry(y1);
0111             auto y2 = chain(y1);
0112             while (y2 != STN_UNDEF) {
0113                 const auto entry2 = symTab->entry(y2);
0114                 sum += commonPrefixLength(entry1->name(), entry2->name());
0115                 ++count;
0116                 y2 = chain(y2);
0117             }
0118 
0119             y1 = chain(y1);
0120         }
0121     }
0122 
0123     return count > 0 ? (double)sum / (double)count : 0.0;
0124 }