1 #include <common.h> 2 #include <debug.h> 3 #include <libelf.h> 4 #include <hash.h> 5 #include <string.h> 6 7 void setup_hash(Elf_Data *hash_data, 8 Elf32_Word nbuckets, 9 Elf32_Word nchains) 10 { 11 hash_data->d_size = 2; 12 hash_data->d_size += nbuckets; 13 hash_data->d_size += nchains; 14 hash_data->d_buf = CALLOC(hash_data->d_size, sizeof(Elf32_Word)); 15 hash_data->d_size *= sizeof(Elf32_Word); 16 ((Elf32_Word *)hash_data->d_buf)[0] = nbuckets; 17 ((Elf32_Word *)hash_data->d_buf)[1] = nchains; 18 } 19 20 void add_to_hash(Elf_Data *hash_data, 21 const char *symbol, 22 int symindex) 23 { 24 Elf32_Word *buckets = (Elf32_Word *)hash_data->d_buf; 25 Elf32_Word nbuckets = *buckets++; 26 Elf32_Word *chains = ++buckets + nbuckets; 27 Elf32_Word last_chain_index; 28 unsigned long bucket = elf_hash(symbol) % nbuckets; 29 30 ASSERT(symindex != STN_UNDEF); 31 32 if (buckets[bucket] == STN_UNDEF) { 33 INFO("Adding [%s] to hash at bucket [%ld] (first add)\n", 34 symbol, bucket); 35 buckets[bucket] = symindex; 36 } 37 else { 38 INFO("Collision on adding [%s] to hash at bucket [%ld]\n", 39 symbol, bucket); 40 last_chain_index = buckets[bucket]; 41 while (chains[last_chain_index] != STN_UNDEF) { 42 INFO("\ttrying at chain index [%d]...\n", last_chain_index); 43 last_chain_index = chains[last_chain_index]; 44 } 45 INFO("\tsuccess at chain index [%d]...\n", last_chain_index); 46 chains[last_chain_index] = symindex; 47 } 48 } 49 50 int hash_lookup(Elf *elf, 51 section_info_t *hash_info, 52 section_info_t *symtab_info, 53 const char *symname, 54 GElf_Sym *sym_mem) 55 { 56 Elf32_Word *hash_data = (Elf32_Word *)hash_info->data->d_buf; 57 Elf32_Word index; 58 Elf32_Word nbuckets = *hash_data++; 59 Elf32_Word *buckets = ++hash_data; 60 Elf32_Word *chains = hash_data + nbuckets; 61 62 GElf_Sym *sym; 63 64 index = buckets[elf_hash(symname) % nbuckets]; 65 while(index != STN_UNDEF) 66 { 67 sym = gelf_getsymshndx (symtab_info->data, NULL, index, sym_mem, NULL); 68 FAILIF_LIBELF(NULL == sym, gelf_getsymshndx); 69 if (!strcmp(symname, 70 elf_strptr(elf, symtab_info->hdr->sh_link, sym->st_name))) 71 break; 72 index = chains[index]; 73 } 74 75 return index; 76 } 77