diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:29:27 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:29:27 -0800 |
commit | 5be48c0aa50b576ea678d9298b5207c9e8854224 (patch) | |
tree | d37ee9e0c10b3abce0ff0f4f4f0a3d6e851be688 /hash.c | |
parent | d1ceeffdc951169c079c2d35f8b8cd26481dcc3a (diff) | |
download | elfcopy-5be48c0aa50b576ea678d9298b5207c9e8854224.tar.gz |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 76 |
1 files changed, 76 insertions, 0 deletions
@@ -0,0 +1,76 @@ +#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; +} |