| 195 | } |
| 196 | |
| 197 | [[nodiscard]] |
| 198 | static bool findSymByName64(const ElfView::ElfInfo &info, const char *symbol, |
| 199 | const Elf64_Sym **ppsym, uint32_t *psymidx) { |
| 200 | if (info.gnu_hash != nullptr) { |
| 201 | if (findLocalSymByGnuHash64(info, symbol, ppsym, psymidx)) { |
| 202 | return true; |
| 203 | } |
| 204 | // search the symtab |
| 205 | const uint32_t *gnuhashtab = static_cast<const uint32_t *>(info.gnu_hash); |
| 206 | const uint32_t symoffset = gnuhashtab[1]; |
| 207 | const Elf64_Sym *symtab = static_cast<const Elf64_Sym *>(info.symtab); |
| 208 | for (uint32_t i = 0; i < symoffset; i++) { |
| 209 | const char *symname = info.symstr + symtab[i].st_name; |
| 210 | if (strcmp(symname, symbol) == 0) { |
| 211 | *psymidx = i; |
| 212 | *ppsym = &symtab[i]; |
| 213 | return true; |
| 214 | } |
| 215 | } |
| 216 | return false; |
| 217 | } else if (info.chain != nullptr) { |
| 218 | const Elf64_Sym *target = nullptr; |
| 219 | uint32_t hash = elf_sysv_hash(symbol); |
| 220 | uint32_t index = info.bucket[hash % info.nbucket]; |
| 221 | const auto *sym = static_cast<const Elf64_Sym *>(info.symtab); |
| 222 | if (!strcmp(info.symstr + sym[index].st_name, symbol)) { |
| 223 | target = sym + index; |
| 224 | } |
| 225 | if (!target) { |
| 226 | do { |
| 227 | index = info.chain[index]; |
| 228 | if (!strcmp(info.symstr + sym[index].st_name, symbol)) { |
| 229 | target = sym + index; |
| 230 | break; |
| 231 | } |
| 232 | } while (index != 0); |
| 233 | } |
| 234 | if (target) { |
| 235 | *ppsym = target; |
| 236 | *psymidx = int(index); |
| 237 | return true; |
| 238 | } |
| 239 | } |
| 240 | return false; |
| 241 | } |
| 242 | |
| 243 | std::vector<uint64_t> ElfView::getExtSymGotRelVirtAddr(const char *symbol) const { |
| 244 | if (symbol == nullptr) { |
no test coverage detected