/* ** hash.c for libelfsh ** ** Started on Mon Feb 26 04:15:44 2001 mayhem ** Last update Sun Jun 29 11:47:35 2003 mayhem */ #include "libelfsh.h" /* Return a pointer on the symbol hash table and load it if needed */ void *elfsh_get_hashtable(elfshobj_t *file) { elfshsect_t *new; int nbr; if (file->secthash[ELFSH_SECTION_HASH] == NULL) { new = elfsh_get_section_by_type(file, SHT_HASH, NULL, NULL, &nbr, 0); if (!new) return (NULL); new->data = elfsh_load_section(file, new->shdr); if (!new->data) ELFSH_SETERROR("libelfsh: No Hash table .", NULL); file->secthash[ELFSH_SECTION_HASH] = new; } return (file->secthash[ELFSH_SECTION_HASH]); } /* Return the symbol value giving its name using the symbol hash table */ int elfsh_get_dynsymbol_by_hash(elfshobj_t *file, char *name) { Elf32_Sym *sym; char *sname; int hash; int nbucket; int nchain; int *chain; int *bucket; int index; if (file->secthash[ELFSH_SECTION_HASH] == NULL && elfsh_get_hashtable(file) == NULL) ELFSH_SETERROR("libelfsh: Cannot retreive hash table", 0); if (NULL == file->secthash[ELFSH_SECTION_DYNSYM] && NULL == elfsh_get_dynsymtab(file, NULL)) ELFSH_SETERROR("libelfsh: Cannot retreive dynamic symbol table", 0); hash = elfsh_get_symbol_hash(name); nbucket = *((int *) file->secthash[ELFSH_SECTION_HASH]->data); nchain = *((int *) file->secthash[ELFSH_SECTION_HASH]->data + 1); bucket = (int *) file->secthash[ELFSH_SECTION_HASH]->data + 2; chain = (int *) bucket + nbucket; index = bucket[hash % nbucket]; sym = file->secthash[ELFSH_SECTION_DYNSYM]->data; sname = elfsh_get_dynsymbol_name(file, sym + index); if (!strcmp(name, sname)) return (sym[index].st_value); /* ** The first fetched dynamic symbol isnt the one we are looking for ** so we loop on the entry . */ for (sym = file->secthash[ELFSH_SECTION_DYNSYM]->data; index < nchain; index++) { #if __DEBUG__ printf("[LIBELFSH] Hash LOOP on bucket [%u] \n", (u_int) index); #endif sname = elfsh_get_dynsymbol_name(file, &sym[chain[index]]); if (!strcmp(name, sname)) return (sym[chain[index]].st_value); } ELFSH_SETERROR("ELFlib: No Hash found for the symbol .", 0); } /* Get the hash for the symbol name . Adapted from the ELF TIS reference */ int elfsh_get_symbol_hash(char *name) { unsigned long h; unsigned long g; for (h = 0; *name; h &= ~g) { h = (h << 4) + *name++; if ((g = h & 0xF0000000)) h ^= g >> 24; } return (h); }