#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;
}