Subject: dlsym() is braindead
To: None <tech-userlevel@netbsd.org, tech-toolchain@netbsd.org,>
From: Charles M. Hannum <mycroft@netbsd.org>
List: tech-userlevel
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--