Home | History | Annotate | Download | only in elfcopy
      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