Sat Oct 4 09:37:12 2008 UTC ()
lib/39649: dlsym(3) does not follow dependencies
Pull across code from FreeBSD to do a search of the passed object and it's
NEEDED objects (dependencies).
Reviewed by gimpy.
(skrll)
diff -r1.121 -r1.122 src/libexec/ld.elf_so/rtld.c
diff -r1.78 -r1.79 src/libexec/ld.elf_so/rtld.h
diff -r1.46 -r1.47 src/libexec/ld.elf_so/symbol.c
--- src/libexec/ld.elf_so/rtld.c 2008/09/27 03:52:05 1.121
+++ src/libexec/ld.elf_so/rtld.c 2008/10/04 09:37:12 1.122
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.121 2008/09/27 03:52:05 macallan Exp $ */
+/* $NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.121 2008/09/27 03:52:05 macallan Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -889,12 +889,14 @@
def = _rtld_symlook_list(name, hash, &_rtld_list_main,
&defobj, false);
} else {
- /*
- * XXX - This isn't correct. The search should include
- * the whole DAG rooted at the given object.
- */
- def = _rtld_symlook_obj(name, hash, obj, false);
- defobj = obj;
+ Needed_Entry fake;
+
+ /* Search the object and all the libraries loaded by it. */
+ fake.next = NULL;
+ fake.obj = (Obj_Entry *)obj;
+ fake.name = 0;
+ def = _rtld_symlook_needed(name, hash, &fake, &defobj,
+ false);
}
break;
}
--- src/libexec/ld.elf_so/rtld.h 2008/06/03 19:32:32 1.78
+++ src/libexec/ld.elf_so/rtld.h 2008/10/04 09:37:12 1.79
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.78 2008/06/03 19:32:32 ad Exp $ */
+/* $NetBSD: rtld.h,v 1.79 2008/10/04 09:37:12 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -274,6 +274,8 @@
const Objlist *, const Obj_Entry **, bool);
const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
const Obj_Entry *, const Obj_Entry **, bool);
+const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
+ const Needed_Entry *, const Obj_Entry **, bool);
/* map_object.c */
Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
--- src/libexec/ld.elf_so/symbol.c 2008/07/24 04:39:25 1.46
+++ src/libexec/ld.elf_so/symbol.c 2008/10/04 09:37:12 1.47
@@ -1,4 +1,4 @@
-/* $NetBSD: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $ */
+/* $NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $");
+__RCSID("$NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll Exp $");
#endif /* not lint */
#include <err.h>
@@ -132,6 +132,56 @@
}
if (def != NULL)
*defobj_out = defobj;
+ return def;
+}
+
+/*
+ * Search the symbol table of a shared object and all objects needed by it for
+ * a symbol of the given name. Search order is breadth-first. Returns a pointer
+ * to the symbol, or NULL if no definition was found.
+ */
+const Elf_Sym *
+_rtld_symlook_needed(const char *name, unsigned long hash,
+ const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt)
+{
+ const Elf_Sym *def, *def_w;
+ const Needed_Entry *n;
+ const Obj_Entry *obj, *defobj, *defobj1;
+
+ def = def_w = NULL;
+ defobj = NULL;
+ for (n = needed; n != NULL; n = n->next) {
+ if ((obj = n->obj) == NULL ||
+ (def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
+ continue;
+ defobj = obj;
+ if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
+ *defobj_out = defobj;
+
+ return (def);
+ }
+ }
+ /*
+ * Either the symbol definition has not been found in directly needed
+ * objects, or the found symbol is weak.
+ */
+ for (n = needed; n != NULL; n = n->next) {
+ if ((obj = n->obj) == NULL)
+ continue;
+ def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1,
+ inplt);
+ if (def_w == NULL)
+ continue;
+ if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
+ def = def_w;
+ defobj = defobj1;
+ if (ELF_ST_BIND(def_w->st_info) != STB_WEAK)
+ break;
+ }
+ }
+ if (def != NULL)
+ *defobj_out = defobj;
+
return def;
}