Subject: dlsym() is braindead
To: None <tech-userlevel@netbsd.org, tech-toolchain@netbsd.org,>
From: Charles M. Hannum <mycroft@netbsd.org>
List: tech-toolchain
Date: 04/15/2003 17:24:40
--=-GLYu01rOTy5URqw36PP2
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
dlsym() is known to be bogus -- in many cases it doesn't follow the
object DAG and fails to find symbols. The comments even allude to this.
I've taken a whack at fixing it. Does someone want to verify that the
semantics are correct? Klaus?
--=-GLYu01rOTy5URqw36PP2
Content-Disposition: attachment; filename=dlsym.diff
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; name=dlsym.diff; charset=646
Index: rtld.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.c,v
retrieving revision 1.90
diff -u -r1.90 rtld.c
--- rtld.c 2002/12/14 15:37:57 1.90
+++ rtld.c 2003/04/15 17:14:24
@@ -367,8 +367,6 @@
_rtld_objmain->pathlen =3D strlen(_rtld_objmain->path);
}
=20
- _rtld_objmain->mainprog =3D true;
-=09
/*
* Get the actual dynamic linker pathname from the executable if
* possible. (It should always be possible.) That ensures that
@@ -673,19 +671,10 @@
const char *name;
{
const Obj_Entry *obj;
- unsigned long hash;
const Elf_Sym *def;
const Obj_Entry *defobj;
-=09
- hash =3D _rtld_elf_hash(name);
- def =3D NULL;
- defobj =3D NULL;
=09
- if (handle =3D=3D NULL
-#if 0
- || handle =3D=3D RTLD_NEXT
-#endif
- ) {
+ if (handle =3D=3D NULL) {
void *retaddr;
=20
retaddr =3D __builtin_return_address(0); /* __GNUC__ only */
@@ -693,33 +682,14 @@
_rtld_error("Cannot determine caller's shared object");
return NULL;
}
- if (handle =3D=3D NULL) { /* Just the caller's shared object. */
- def =3D _rtld_symlook_obj(name, hash, obj, false);
- defobj =3D obj;
- } else { /* All the shared objects after the caller's */
- while ((obj =3D obj->next) !=3D NULL) {
- if ((def =3D _rtld_symlook_obj(name, hash, obj, false)) !=3D NULL) {
- defobj =3D obj;
- break;
- }
- }
- }
} else {
- if ((obj =3D _rtld_dlcheck(handle)) =3D=3D NULL)
+ if ((obj =3D _rtld_dlcheck(handle)) =3D=3D NULL) {
+ _rtld_error("Handle not found");
return NULL;
- =09
- if (obj->mainprog) {
- /* Search main program and all libraries loaded by it. */
- def =3D _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 =3D _rtld_symlook_obj(name, hash, obj, false);
- defobj =3D obj;
}
}
+ =09
+ def =3D _rtld_find_symname(name, obj, &defobj, false);
=09
if (def !=3D NULL) {
#ifdef __HAVE_FUNCTION_DESCRIPTORS
@@ -728,10 +698,10 @@
def, 0);
#endif /* __HAVE_FUNCTION_DESCRIPTORS */
return defobj->relocbase + def->st_value;
+ } else {
+ _rtld_error("Undefined symbol \"%s\"", name);
+ return NULL;
}
-=09
- _rtld_error("Undefined symbol \"%s\"", name);
- return NULL;
}
=20
int
Index: rtld.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.h,v
retrieving revision 1.65
diff -u -r1.65 rtld.h
--- rtld.h 2002/12/05 04:56:57 1.65
+++ rtld.h 2003/04/15 17:14:24
@@ -176,8 +176,7 @@
int (*dlclose) __P((void *));
int (*dladdr) __P((const void *, Dl_info *));
=20
- u_int32_t mainprog:1, /* True if this is the main program */
- rtld:1, /* True if this is the dynamic linker */
+ u_int32_t rtld:1, /* True if this is the dynamic linker */
textrel:1, /* True if there are relocations to
* text seg */
symbolic:1, /* True if generated with
@@ -256,6 +255,8 @@
unsigned long _rtld_elf_hash __P((const char *));
const Elf_Sym *_rtld_symlook_obj __P((const char *, unsigned long,
const Obj_Entry *, bool));
+const Elf_Sym *_rtld_find_symname __P((const char *, const Obj_Entry *,
+ const Obj_Entry **, bool));
const Elf_Sym *_rtld_find_symdef __P((unsigned long, const Obj_Entry *,
const Obj_Entry **, bool));
const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
Index: symbol.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/libexec/ld.elf_so/symbol.c,v
retrieving revision 1.25
diff -u -r1.25 symbol.c
--- symbol.c 2002/10/05 11:59:04 1.25
+++ symbol.c 2003/04/15 17:14:24
@@ -83,11 +83,9 @@
{
const Elf_Sym *symp;
const Elf_Sym *def;
- const Obj_Entry *defobj;
const Objlist_Entry *elm;
=09
def =3D NULL;
- defobj =3D NULL;
SIMPLEQ_FOREACH(elm, objlist, link) {
rdbg(("search object %p (%s)", elm->obj, elm->obj->path));
if ((symp =3D _rtld_symlook_obj(name, hash, elm->obj, in_plt))
@@ -95,14 +93,12 @@
if ((def =3D=3D NULL) ||
(ELF_ST_BIND(symp->st_info) !=3D STB_WEAK)) {
def =3D symp;
- defobj =3D elm->obj;
+ *defobj_out =3D elm->obj;
if (ELF_ST_BIND(def->st_info) !=3D STB_WEAK)
break;
}
}
}
- if (def !=3D NULL)
- *defobj_out =3D defobj;
return def;
}
=20
@@ -166,33 +162,26 @@
* defining object via the reference parameter DEFOBJ_OUT.
*/
const Elf_Sym *
-_rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
- unsigned long symnum;
+_rtld_find_symname(name, refobj, defobj_out, in_plt)
+ const char *name;
const Obj_Entry *refobj;
const Obj_Entry **defobj_out;
bool in_plt;
{
- const Elf_Sym *ref;
const Elf_Sym *def;
const Elf_Sym *symp;
const Obj_Entry *obj;
- const Obj_Entry *defobj;
const Objlist_Entry *elm;
- const char *name;
unsigned long hash;
=20
- ref =3D refobj->symtab + symnum;
- name =3D refobj->strtab + ref->st_name;
-
hash =3D _rtld_elf_hash(name);
def =3D NULL;
- defobj =3D NULL;
=09
if (refobj->symbolic) { /* Look first in the referencing object */
symp =3D _rtld_symlook_obj(name, hash, refobj, in_plt);
if (symp !=3D NULL) {
def =3D symp;
- defobj =3D refobj;
+ *defobj_out =3D refobj;
}
}
=09
@@ -203,7 +192,7 @@
if (symp !=3D NULL &&
(def =3D=3D NULL || ELF_ST_BIND(symp->st_info) !=3D STB_WEAK)) {
def =3D symp;
- defobj =3D obj;
+ *defobj_out =3D obj;
}
}
=09
@@ -216,7 +205,7 @@
if (symp !=3D NULL &&
(def =3D=3D NULL || ELF_ST_BIND(symp->st_info) !=3D STB_WEAK)) {
def =3D symp;
- defobj =3D obj;
+ *defobj_out =3D obj;
}
}
=09
@@ -227,26 +216,41 @@
if (symp !=3D NULL &&
(def =3D=3D NULL || ELF_ST_BIND(symp->st_info) !=3D STB_WEAK)) {
def =3D symp;
- defobj =3D obj;
+ *defobj_out =3D obj;
}
}
=09
- /*
- * If we found no definition and the reference is weak, treat the
- * symbol as having the value zero.
- */
- if (def =3D=3D NULL && ELF_ST_BIND(ref->st_info) =3D=3D STB_WEAK) {
- rdbg((" returning _rtld_sym_zero@_rtld_objmain"));
- def =3D &_rtld_sym_zero;
- defobj =3D _rtld_objmain;
- }
-=09
- if (def !=3D NULL)
- *defobj_out =3D defobj;
- else {
- rdbg(("lookup failed"));
- _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum =3D %ld)",
- refobj->path, in_plt ? "PLT " : "", name, symnum);
- }
return def;
+}
+
+const Elf_Sym *
+_rtld_find_symdef(symnum, refobj, defobj_out, in_plt)
+ unsigned long symnum;
+ const Obj_Entry *refobj;
+ const Obj_Entry **defobj_out;
+ bool in_plt;
+{
+ const Elf_Sym *ref, *def;
+ const char *name;
+
+ ref =3D refobj->symtab + symnum;
+ name =3D refobj->strtab + ref->st_name;
+
+ def =3D _rtld_find_symname(name, refobj, defobj_out, in_plt);
+ if (def =3D=3D NULL) {
+ if (ELF_ST_BIND(ref->st_info) =3D=3D STB_WEAK) {
+ /*
+ * If we found no definition and the reference is weak,
+ * treat the symbol as having the value zero.
+ */
+ rdbg((" returning _rtld_sym_zero@_rtld_objmain"));
+ def =3D &_rtld_sym_zero;
+ *defobj_out =3D _rtld_objmain;
+ } else {
+ rdbg(("lookup failed"));
+ _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum =3D %ld)",
+ refobj->path, in_plt ? "PLT " : "", name, symnum);
+ }
+ }
+ return (def);
}
--=-GLYu01rOTy5URqw36PP2--