Alexandre Julliard : preloader: Properly use the ELF hash table when looking up a symbol.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jul 31 15:01:21 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 8aab67d23805b65956c589297ff1ff76f0e0aa8f
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=8aab67d23805b65956c589297ff1ff76f0e0aa8f

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jul 31 15:48:32 2006 +0200

preloader: Properly use the ELF hash table when looking up a symbol.

---

 loader/preloader.c |   37 ++++++++++++++++++++++++++++++-------
 1 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/loader/preloader.c b/loader/preloader.c
index 46e96a5..d372ed7 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -745,6 +745,19 @@ #endif
 }
 
 
+static unsigned int elf_hash( const char *name )
+{
+    unsigned int hi, hash = 0;
+    while (*name)
+    {
+        hash = (hash << 4) + (unsigned char)*name++;
+        hi = hash & 0xf0000000;
+        hash ^= hi;
+        hash ^= hi >> 24;
+    }
+    return hash;
+}
+
 /*
  * Find a symbol in the symbol table of the executable loaded
  */
@@ -753,8 +766,8 @@ static void *find_symbol( const ElfW(Phd
     const ElfW(Dyn) *dyn = NULL;
     const ElfW(Phdr) *ph;
     const ElfW(Sym) *symtab = NULL;
+    const Elf_Symndx *hashtab = NULL;
     const char *strings = NULL;
-    uint32_t i, symtabend = 0;
 
     /* check the values */
 #ifdef DUMP_SYMS
@@ -785,7 +798,7 @@ #endif
         if( dyn->d_tag == DT_SYMTAB )
             symtab = (const ElfW(Sym) *)dyn->d_un.d_ptr;
         if( dyn->d_tag == DT_HASH )
-            symtabend = *((const uint32_t *)dyn->d_un.d_ptr + 1);
+            hashtab = (const Elf_Symndx *)dyn->d_un.d_ptr;
 #ifdef DUMP_SYMS
         wld_printf("%x %x\n", dyn->d_tag, dyn->d_un.d_ptr );
 #endif
@@ -794,15 +807,25 @@ #endif
 
     if( (!symtab) || (!strings) ) return NULL;
 
-    for (i = 0; i < symtabend; i++)
+    if (hashtab)
     {
-        if( ( ELF32_ST_BIND(symtab[i].st_info) == STT_OBJECT ) &&
-            ( 0 == wld_strcmp( strings+symtab[i].st_name, var ) ) )
+        Elf_Symndx nbuckets = hashtab[0];
+        unsigned int hash = elf_hash(var) % nbuckets;
+        const Elf_Symndx *buckets = hashtab + 2;
+        const Elf_Symndx *chains = buckets + nbuckets;
+        Elf_Symndx idx = buckets[hash];
+
+        while (idx != STN_UNDEF)
         {
+            if( ( ELF32_ST_BIND(symtab[idx].st_info) == STT_OBJECT ) &&
+                !wld_strcmp( strings + symtab[idx].st_name, var ))
+            {
 #ifdef DUMP_SYMS
-            wld_printf("Found %s -> %x\n", strings+symtab[i].st_name, symtab[i].st_value );
+                wld_printf("Found %s -> %x\n", strings + symtab[idx].st_name, symtab[idx].st_value );
 #endif
-            return (void*)symtab[i].st_value;
+                return (void*)symtab[idx].st_value;
+            }
+            idx = chains[idx];
         }
     }
     return NULL;




More information about the wine-cvs mailing list