Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so Implement and integrate GNU Hashing function
details: https://anonhg.NetBSD.org/src/rev/dd192cca92d4
branches: trunk
changeset: 745331:dd192cca92d4
user: kamil <kamil%NetBSD.org@localhost>
date: Sat Feb 29 04:23:05 2020 +0000
description:
Implement and integrate GNU Hashing function
Define Elf_Hash struct that contains ELF/SYSV and GNU hash checksum.
Implement _rtld_gnu_hash() for DT_GNU_HASH.
Adapt existing code to compute all Elf_Hash types, instead of only
the ELF/SYSV one.
Rename _rtld_elf_hash() to _rtld_sysv_hash() to match the GNU toolchain
terminology.
_rtld_gnu_hash() uses Dan Bernstein's string hash function posted eons ago
on comp.lang.c.
diffstat:
libexec/ld.elf_so/reloc.c | 11 +++++++----
libexec/ld.elf_so/rtld.c | 30 ++++++++++++++++--------------
libexec/ld.elf_so/rtld.h | 18 ++++++++++++------
libexec/ld.elf_so/symbol.c | 39 ++++++++++++++++++++++++++++-----------
4 files changed, 63 insertions(+), 35 deletions(-)
diffs (truncated from 322 to 300 lines):
diff -r 0bf83e5a3eaf -r dd192cca92d4 libexec/ld.elf_so/reloc.c
--- a/libexec/ld.elf_so/reloc.c Sat Feb 29 04:21:42 2020 +0000
+++ b/libexec/ld.elf_so/reloc.c Sat Feb 29 04:23:05 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: reloc.c,v 1.114 2018/12/30 01:48:37 christos Exp $ */
+/* $NetBSD: reloc.c,v 1.115 2020/02/29 04:23:05 kamil Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.114 2018/12/30 01:48:37 christos Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.115 2020/02/29 04:23:05 kamil Exp $");
#endif /* not lint */
#include <err.h>
@@ -67,12 +67,15 @@
void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
const char *name = dstobj->strtab + dstsym->st_name;
- unsigned long hash = _rtld_elf_hash(name);
+ Elf_Hash hash;
size_t size = dstsym->st_size;
const void *srcaddr;
const Elf_Sym *srcsym = NULL;
Obj_Entry *srcobj;
+ hash.sysv = _rtld_sysv_hash(name);
+ hash.gnu = _rtld_gnu_hash(name);
+
if (__predict_false(size == 0)) {
#if defined(__powerpc__) && !defined(__LP64) /* PR port-macppc/47464 */
if (strcmp(name, "_SDA_BASE_") == 0
@@ -90,7 +93,7 @@
}
for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) {
- srcsym = _rtld_symlook_obj(name, hash, srcobj, 0,
+ srcsym = _rtld_symlook_obj(name, &hash, srcobj, 0,
_rtld_fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)));
if (srcsym != NULL)
break;
diff -r 0bf83e5a3eaf -r dd192cca92d4 libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c Sat Feb 29 04:21:42 2020 +0000
+++ b/libexec/ld.elf_so/rtld.c Sat Feb 29 04:23:05 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.201 2019/12/08 22:35:27 uwe Exp $ */
+/* $NetBSD: rtld.c,v 1.202 2020/02/29 04:23:05 kamil Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.201 2019/12/08 22:35:27 uwe Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.202 2020/02/29 04:23:05 kamil Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -1098,16 +1098,17 @@
void *
_rtld_objmain_sym(const char *name)
{
- unsigned long hash;
+ Elf_Hash hash;
const Elf_Sym *def;
const Obj_Entry *obj;
DoneList donelist;
- hash = _rtld_elf_hash(name);
+ hash.sysv = _rtld_sysv_hash(name);
+ hash.gnu = _rtld_gnu_hash(name);
obj = _rtld_objmain;
_rtld_donelist_init(&donelist);
- def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0,
+ def = _rtld_symlook_list(name, &hash, &_rtld_list_main, &obj, 0,
NULL, &donelist);
if (def != NULL)
@@ -1142,7 +1143,7 @@
do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr)
{
const Obj_Entry *obj;
- unsigned long hash;
+ Elf_Hash hash;
const Elf_Sym *def;
const Obj_Entry *defobj;
DoneList donelist;
@@ -1153,7 +1154,8 @@
lookup_mutex_enter();
- hash = _rtld_elf_hash(name);
+ hash.sysv = _rtld_sysv_hash(name);
+ hash.gnu = _rtld_gnu_hash(name);
def = NULL;
defobj = NULL;
@@ -1170,7 +1172,7 @@
switch ((intptr_t)handle) {
case (intptr_t)NULL: /* Just the caller's shared object. */
- def = _rtld_symlook_obj(name, hash, obj, flags, ventry);
+ def = _rtld_symlook_obj(name, &hash, obj, flags, ventry);
defobj = obj;
break;
@@ -1180,7 +1182,7 @@
case (intptr_t)RTLD_SELF: /* Caller included */
for (; obj; obj = obj->next) {
- if ((def = _rtld_symlook_obj(name, hash, obj,
+ if ((def = _rtld_symlook_obj(name, &hash, obj,
flags, ventry)) != NULL) {
defobj = obj;
break;
@@ -1194,7 +1196,7 @@
*/
if (!def || ELF_ST_BIND(def->st_info) == STB_WEAK) {
const Elf_Sym *symp = _rtld_symlook_obj(name,
- hash, &_rtld_objself, flags, ventry);
+ &hash, &_rtld_objself, flags, ventry);
if (symp != NULL) {
def = symp;
defobj = &_rtld_objself;
@@ -1203,7 +1205,7 @@
break;
case (intptr_t)RTLD_DEFAULT:
- def = _rtld_symlook_default(name, hash, obj, &defobj,
+ def = _rtld_symlook_default(name, &hash, obj, &defobj,
flags, ventry);
break;
@@ -1222,7 +1224,7 @@
if (obj->mainprog) {
/* Search main program and all libraries loaded by it */
- def = _rtld_symlook_list(name, hash, &_rtld_list_main,
+ def = _rtld_symlook_list(name, &hash, &_rtld_list_main,
&defobj, flags, ventry, &donelist);
} else {
Needed_Entry fake;
@@ -1234,7 +1236,7 @@
fake.name = 0;
_rtld_donelist_init(&depth);
- def = _rtld_symlook_needed(name, hash, &fake, &defobj,
+ def = _rtld_symlook_needed(name, &hash, &fake, &defobj,
flags, ventry, &donelist, &depth);
}
@@ -1301,7 +1303,7 @@
if (version != NULL) {
ver_entry.name = version;
ver_entry.file = NULL;
- ver_entry.hash = _rtld_elf_hash(version);
+ ver_entry.hash = _rtld_sysv_hash(version);
ver_entry.flags = 0;
ventry = &ver_entry;
}
diff -r 0bf83e5a3eaf -r dd192cca92d4 libexec/ld.elf_so/rtld.h
--- a/libexec/ld.elf_so/rtld.h Sat Feb 29 04:21:42 2020 +0000
+++ b/libexec/ld.elf_so/rtld.h Sat Feb 29 04:23:05 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.136 2018/12/30 01:48:37 christos Exp $ */
+/* $NetBSD: rtld.h,v 1.137 2020/02/29 04:23:05 kamil Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -76,6 +76,11 @@
assert((dlp)->objs != NULL), \
(dlp)->num_used = 0)
+
+typedef struct Struct_Elf_Hash {
+ unsigned long sysv;
+ unsigned long gnu;
+} Elf_Hash;
#endif /* _RTLD_SOURCE */
/*
@@ -410,19 +415,20 @@
Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
/* symbol.c */
-unsigned long _rtld_elf_hash(const char *);
-const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long,
+unsigned long _rtld_sysv_hash(const char *);
+unsigned long _rtld_gnu_hash(const char *);
+const Elf_Sym *_rtld_symlook_obj(const char *, Elf_Hash *,
const Obj_Entry *, u_int, const Ver_Entry *);
const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, u_int);
const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *,
const Obj_Entry **, bool);
-const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
+const Elf_Sym *_rtld_symlook_list(const char *, Elf_Hash *,
const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *);
-const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
+const Elf_Sym *_rtld_symlook_default(const char *, Elf_Hash *,
const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *);
-const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
+const Elf_Sym *_rtld_symlook_needed(const char *, Elf_Hash *,
const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *,
DoneList *, DoneList *);
diff -r 0bf83e5a3eaf -r dd192cca92d4 libexec/ld.elf_so/symbol.c
--- a/libexec/ld.elf_so/symbol.c Sat Feb 29 04:21:42 2020 +0000
+++ b/libexec/ld.elf_so/symbol.c Sat Feb 29 04:23:05 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: symbol.c,v 1.70 2020/02/29 04:21:42 kamil Exp $ */
+/* $NetBSD: symbol.c,v 1.71 2020/02/29 04:23:05 kamil Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.70 2020/02/29 04:21:42 kamil Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.71 2020/02/29 04:23:05 kamil Exp $");
#endif /* not lint */
#include <err.h>
@@ -85,7 +85,7 @@
* this. It is specified by the System V ABI.
*/
unsigned long
-_rtld_elf_hash(const char *name)
+_rtld_sysv_hash(const char *name)
{
const unsigned char *p = (const unsigned char *) name;
unsigned long h = 0;
@@ -103,8 +103,24 @@
return (h);
}
+/*
+ * Hash function for symbol table lookup. Don't even think about changing
+ * this. It is specified by the GNU toolchain ABI.
+ */
+unsigned long
+_rtld_gnu_hash(const char *name)
+{
+ const unsigned char *p = (const unsigned char *) name;
+ uint_fast32_t h = 5381;
+ unsigned char c;
+
+ for (c = *p; c != '\0'; c = *++p)
+ h = h * 33 + c;
+ return (unsigned long)h;
+}
+
const Elf_Sym *
-_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
+_rtld_symlook_list(const char *name, Elf_Hash *hash, const Objlist *objlist,
const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry,
DoneList *dlp)
{
@@ -142,7 +158,7 @@
* to the symbol, or NULL if no definition was found.
*/
const Elf_Sym *
-_rtld_symlook_needed(const char *name, unsigned long hash,
+_rtld_symlook_needed(const char *name, Elf_Hash *hash,
const Needed_Entry *needed, const Obj_Entry **defobj_out, u_int flags,
const Ver_Entry *ventry, DoneList *breadth, DoneList *depth)
{
@@ -315,14 +331,14 @@
* eliminates many recomputations of the hash value.
*/
const Elf_Sym *
-_rtld_symlook_obj(const char *name, unsigned long hash,
+_rtld_symlook_obj(const char *name, Elf_Hash *hash,
const Obj_Entry *obj, u_int flags, const Ver_Entry *ventry)
{
unsigned long symnum;
const Elf_Sym *vsymp = NULL;
int vcount = 0;
- for (symnum = obj->buckets[fast_remainder32(hash, obj->nbuckets,
+ for (symnum = obj->buckets[fast_remainder32(hash->sysv, obj->nbuckets,
obj->nbuckets_m, obj->nbuckets_s1, obj->nbuckets_s2)];
symnum != ELF_SYM_UNDEFINED;
symnum = obj->chains[symnum]) {
@@ -352,7 +368,7 @@
const Elf_Sym *def;
const Obj_Entry *defobj;
const char *name;
- unsigned long hash;
+ Elf_Hash hash;
ref = refobj->symtab + symnum;
name = refobj->strtab + ref->st_name;
Home |
Main Index |
Thread Index |
Old Index