#include <common.h> #include <debug.h> #include <libelf.h> #include <hash.h> #include <string.h> void setup_hash(Elf_Data *hash_data, Elf32_Word nbuckets, Elf32_Word nchains) { hash_data->d_size = 2; hash_data->d_size += nbuckets; hash_data->d_size += nchains; hash_data->d_buf = CALLOC(hash_data->d_size, sizeof(Elf32_Word)); hash_data->d_size *= sizeof(Elf32_Word); ((Elf32_Word *)hash_data->d_buf)[0] = nbuckets; ((Elf32_Word *)hash_data->d_buf)[1] = nchains; } void add_to_hash(Elf_Data *hash_data, const char *symbol, int symindex) { Elf32_Word *buckets = (Elf32_Word *)hash_data->d_buf; Elf32_Word nbuckets = *buckets++; Elf32_Word *chains = ++buckets + nbuckets; Elf32_Word last_chain_index; unsigned long bucket = elf_hash(symbol) % nbuckets; ASSERT(symindex != STN_UNDEF); if (buckets[bucket] == STN_UNDEF) { INFO("Adding [%s] to hash at bucket [%ld] (first add)\n", symbol, bucket); buckets[bucket] = symindex; } else { INFO("Collision on adding [%s] to hash at bucket [%ld]\n", symbol, bucket); last_chain_index = buckets[bucket]; while (chains[last_chain_index] != STN_UNDEF) { INFO("\ttrying at chain index [%d]...\n", last_chain_index); last_chain_index = chains[last_chain_index]; } INFO("\tsuccess at chain index [%d]...\n", last_chain_index); chains[last_chain_index] = symindex; } } int hash_lookup(Elf *elf, section_info_t *hash_info, section_info_t *symtab_info, const char *symname, GElf_Sym *sym_mem) { Elf32_Word *hash_data = (Elf32_Word *)hash_info->data->d_buf; Elf32_Word index; Elf32_Word nbuckets = *hash_data++; Elf32_Word *buckets = ++hash_data; Elf32_Word *chains = hash_data + nbuckets; GElf_Sym *sym; index = buckets[elf_hash(symname) % nbuckets]; while(index != STN_UNDEF) { sym = gelf_getsymshndx (symtab_info->data, NULL, index, sym_mem, NULL); FAILIF_LIBELF(NULL == sym, gelf_getsymshndx); if (!strcmp(symname, elf_strptr(elf, symtab_info->hdr->sh_link, sym->st_name))) break; index = chains[index]; } return index; }