diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index c733dc5..a4b150c 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -138,6 +138,7 @@ static Sym *sysv_lookup(const char *s, uint32_t h, struct dso *dso) return 0; } +#define BWSZ (sizeof(size_t)*8) static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso) { Sym *sym; @@ -145,10 +146,15 @@ static Sym *gnu_lookup(const char *s, uint32_t h1, struct dso *dso) uint32_t *hashtab = dso->ghashtab; uint32_t nbuckets = hashtab[0]; uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4); - uint32_t h2; + size_t *maskwords = (size_t *)(hashtab + 4); + uint32_t h2 = h1 >> hashtab[3]; uint32_t *hashval; - uint32_t n = buckets[h1 % nbuckets]; + uint32_t n = (h1/BWSZ) & (hashtab[2]-1); + size_t bm = (1 << (h1%BWSZ)) | (1 << (h2%BWSZ)); + if ((maskwords[n] & bm) != bm) return 0; + + n = buckets[h1 % nbuckets]; if (!n) return 0; strings = dso->strings;