static inline void compute_exported_hash(const struct elf_info *elf, enum ksymtab_type tp) { struct kernel_symbol *sym; struct kernel_symbol *start = elf->ksym_tables[tp].start; struct kernel_symbol *stop = elf->ksym_tables[tp].stop; for (sym = start; sym < stop; sym++) sym->hash_value = gnu_hash(GET_KSTRING(sym, elf->kstr_offset)); }
static int fill_hashtable(struct elf_htable *htable, struct kernel_symbol *start, struct kernel_symbol *stop, long s_offset) { struct kernel_symbol *ksym; uint32_t nb; unsigned long hvalue; int last_chain_slot; /* sanity check */ if ((htable->elf_buckets == NULL) || (htable->chains == NULL)) return -1; /* Initialize buckets and chains with -1 that means empty */ memset(htable->elf_buckets, -1, htable->nbucket * sizeof(uint32_t)); memset(htable->chains, -1, htable->nchain * sizeof(uint32_t)); nb = htable->nbucket; for (ksym = start, hvalue = 0; ksym < stop; ksym++, hvalue++) { const unsigned char *name = GET_KSTRING(ksym, s_offset); unsigned long h = gnu_hash(name); unsigned long idx = h % nb; uint32_t *slot = &htable->elf_buckets[idx]; /* * Store the index of the export symbol ksym in its * related __ksymtable in the hash table buckets for * using during lookup. * If the slot is alredy used ( != -1) then we have a collision * it needs to create an entry in the chain */ if (*slot == EMPTY_SLOT) *slot = hvalue; else { if (handle_collision(htable, *slot, hvalue) < 0) /* Something wrong happened */ return -1; } } /* * Update the chain lenght with the best value * so that we will cut unused entries beyond this upper limit * In the best case, when there are not collisions, htable->chains * will be 0 size... good ! */ /* Look for upper chains empty slot */ for (last_chain_slot = htable->nchain; --last_chain_slot >= 0 && htable->chains[last_chain_slot] == EMPTY_SLOT;); htable->nchain = last_chain_slot + 1; debugp("\t> Shortest chain lenght = %d\n", htable->nchain); return 0; }