| 102 | } |
| 103 | |
| 104 | [[nodiscard]] |
| 105 | static bool findLocalSymByGnuHash32(const ElfView::ElfInfo &info, const char *symbol, |
| 106 | const Elf32_Sym **ppsym, uint32_t *psymidx) { |
| 107 | using bloom_el_t = uint32_t; |
| 108 | constexpr int ELFCLASS_BITS = 32; |
| 109 | const uint32_t *hashtab = static_cast<const uint32_t *>(info.gnu_hash); |
| 110 | const uint32_t symbol_hash = elf_gnu_hash(symbol); |
| 111 | const uint32_t nbuckets = hashtab[0]; |
| 112 | const uint32_t symoffset = hashtab[1]; |
| 113 | const uint32_t bloom_size = hashtab[2]; |
| 114 | const uint32_t bloom_shift = hashtab[3]; |
| 115 | const bloom_el_t *bloom = reinterpret_cast<const bloom_el_t *>(&hashtab[4]); |
| 116 | const uint32_t *buckets = reinterpret_cast<const uint32_t *>(&bloom[bloom_size]); |
| 117 | const uint32_t *chain = &buckets[nbuckets]; |
| 118 | bloom_el_t word = bloom[(symbol_hash / ELFCLASS_BITS) % bloom_size]; |
| 119 | bloom_el_t mask = (bloom_el_t) 1 << (symbol_hash % ELFCLASS_BITS) |
| 120 | | (bloom_el_t) 1 << ((symbol_hash >> bloom_shift) % ELFCLASS_BITS); |
| 121 | /* If at least one bit is not set, a symbol is surely missing. */ |
| 122 | if ((word & mask) != mask) { |
| 123 | return false; |
| 124 | } |
| 125 | uint32_t symix = buckets[symbol_hash % nbuckets]; |
| 126 | if (symix < symoffset) { |
| 127 | return false; |
| 128 | } |
| 129 | const auto *symtab = static_cast<const Elf32_Sym *>(info.symtab); |
| 130 | /* Loop through the chain. */ |
| 131 | while (true) { |
| 132 | const char *symname = info.symstr + symtab[symix].st_name; |
| 133 | const uint32_t hash = chain[symix - symoffset]; |
| 134 | if ((symbol_hash | 1) == (hash | 1) && strcmp(symbol, symname) == 0) { |
| 135 | const Elf32_Sym &sym = symtab[symix]; |
| 136 | // found. |
| 137 | *psymidx = symix; |
| 138 | *ppsym = &sym; |
| 139 | return true; |
| 140 | } |
| 141 | /* Chain ends with an element with the lowest bit set to 1. */ |
| 142 | if (hash & 1) { |
| 143 | break; |
| 144 | } |
| 145 | symix++; |
| 146 | } |
| 147 | // not found |
| 148 | return false; |
| 149 | } |
| 150 | |
| 151 | [[nodiscard]] |
| 152 | static bool findSymByName32(const ElfView::ElfInfo &info, const char *symbol, |
no test coverage detected