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 }