Subject: Re: why ld.elf_so is slow starting mozilla
To: David Laight <david@l8s.co.uk>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-toolchain
Date: 10/03/2002 19:57:39
I reworked this a little...

Index: load.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/load.c,v
retrieving revision 1.19
diff -u -r1.19 load.c
--- load.c	2002/09/23 23:56:46	1.19
+++ load.c	2002/10/03 20:01:25
@@ -153,9 +153,16 @@
 		free(filepath);
 
 	++obj->refcount;
-	if ((mode & RTLD_GLOBAL) &&
-	    _rtld_objlist_find(&_rtld_list_global, obj) == NULL)
+	if (mode & RTLD_MAIN && !obj->mainref) {
+		obj->mainref = 1;
+		rdbg(("adding %p (%s) to _rtld_list_main", obj, obj->path));
+		_rtld_objlist_add(&_rtld_list_main, obj);
+	}
+	if (mode & RTLD_GLOBAL && !obj->globalref) {
+		obj->globalref = 1;
+		rdbg(("adding %p (%s) to _rtld_list_global", obj, obj->path));
 		_rtld_objlist_add(&_rtld_list_global, obj);
+	}
 	return obj;
 }
 
@@ -291,7 +298,7 @@
 	if (preload_path != NULL) {
 		cp = buf = xstrdup(preload_path);
 		while ((path = strsep(&cp, " :")) != NULL && status == 0) {
-			if (!_rtld_load_object(xstrdup(path), RTLD_GLOBAL))
+			if (!_rtld_load_object(xstrdup(path), RTLD_MAIN))
 				status = -1;
 			else
 				dbg((" preloaded \"%s\"", path));
Index: rtld.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/rtld.c,v
retrieving revision 1.83
diff -u -r1.83 rtld.c
--- rtld.c	2002/10/03 01:09:21	1.83
+++ rtld.c	2002/10/03 20:01:26
@@ -221,7 +221,6 @@
 	const char     *ld_bind_now;
 	const char    **argv;
 	long		argc;
-	Obj_Entry	*obj;
 	const char **real___progname;
 	const Obj_Entry **real___mainprog_obj;
 	char ***real_environ;
@@ -381,13 +380,16 @@
 	
 	_rtld_digest_dynamic(_rtld_objmain);
 
-	_rtld_linkmap_add(_rtld_objmain);
-	_rtld_linkmap_add(&_rtld_objself);
-
 	/* Link the main program into the list of objects. */
 	*_rtld_objtail = _rtld_objmain;
 	_rtld_objtail = &_rtld_objmain->next;
+
+	_rtld_linkmap_add(_rtld_objmain);
+	_rtld_linkmap_add(&_rtld_objself);
+
 	++_rtld_objmain->refcount;
+	_rtld_objmain->mainref = 1;
+	_rtld_objlist_add(&_rtld_list_main, _rtld_objmain);
 
 	/* Initialize a fake symbol for resolving undefined weak references. */
 	_rtld_sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
@@ -402,14 +404,9 @@
 		_rtld_die();
 
 	dbg(("loading needed objects"));
-	if (_rtld_load_needed_objects(_rtld_objmain, RTLD_GLOBAL) == -1)
+	if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)
 		_rtld_die();
 
-	for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
-		obj->main = 1;
-		_rtld_objlist_add(&_rtld_list_main, obj);
-	}
-
 	dbg(("relocating objects"));
 	if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
 		_rtld_die();
@@ -499,9 +496,14 @@
 {
 	const Needed_Entry *needed;
 
-	_rtld_objlist_add(&obj->dldags, root);
-	if (!obj->main)
+	if (!obj->mainref) {
+		if (_rtld_objlist_find(&obj->dldags, root))
+			return;
+		rdbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
+		    root->path));
+		_rtld_objlist_add(&obj->dldags, root);
 		_rtld_objlist_add(&root->dagmembers, obj);
+	}
 	for (needed = obj->needed; needed != NULL; needed = needed->next)
 		if (needed->obj != NULL)
 			_rtld_init_dag1(root, needed->obj);
@@ -532,7 +534,10 @@
 			_rtld_objlist_remove(&elm->obj->dldags, root);
 
 		/* Remove the DAG from the RTLD_GLOBAL list. */
-		_rtld_objlist_remove(&_rtld_list_global, root);
+		if (root->globalref) {
+			root->globalref = 0;
+			_rtld_objlist_remove(&_rtld_list_global, root);
+		}
 
 		/* Unmap all objects that are no longer referenced. */
 		linkp = &_rtld_objlist->next;
Index: rtld.h
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/rtld.h,v
retrieving revision 1.61
diff -u -r1.61 rtld.h
--- rtld.h	2002/10/03 01:09:21	1.61
+++ rtld.h	2002/10/03 20:01:26
@@ -115,6 +115,7 @@
 
 #define RTLD_MAGIC	0xd550b87a
 #define RTLD_VERSION	1
+#define	RTLD_MAIN	0x800
 
 typedef struct Struct_Obj_Entry {
 	Elf32_Word      magic;		/* Magic number (sanity check) */
@@ -183,7 +184,8 @@
 					 * "-Bsymbolic" */
 			printed:1,	/* True if ldd has printed it */
 			isdynamic:1,	/* True if this is a pure PIC object */
-			main:1;		/* True if on _rtld_list_main */
+			mainref:1,	/* True if on _rtld_list_main */
+			globalref:1;	/* True if on _rtld_list_global */
 
 	struct link_map linkmap;	/* for GDB */
 
@@ -258,7 +260,7 @@
 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,
-  Objlist *, const Obj_Entry **, bool);
+    const Objlist *, const Obj_Entry **, bool);
 
 /* map_object.c */
 Obj_Entry *_rtld_map_object __P((char *, int, const struct stat *));
Index: symbol.c
===================================================================
RCS file: /cvsroot/basesrc/libexec/ld.elf_so/symbol.c,v
retrieving revision 1.22
diff -u -r1.22 symbol.c
--- symbol.c	2002/09/24 20:27:07	1.22
+++ symbol.c	2002/10/03 20:01:26
@@ -74,7 +74,7 @@
 }
 
 const Elf_Sym *
-_rtld_symlook_list(const char *name, unsigned long hash, Objlist *objlist,
+_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
   const Obj_Entry **defobj_out, bool in_plt)
 {
 	const Elf_Sym *symp;
@@ -85,6 +85,7 @@
 	def = NULL;
 	defobj = NULL;
 	SIMPLEQ_FOREACH(elm, objlist, link) {
+		rdbg(("search object %p (%s)", elm->obj, elm->obj->path));
 		if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt))
 		    != NULL) {
 			if ((def == NULL) ||
@@ -127,6 +128,7 @@
 		assert(symnum < obj->nchains);
 		symp = obj->symtab + symnum;
 		strp = obj->strtab + symp->st_name;
+		rdbg(("check %s vs %s in %p", name, strp, obj));
 		if (name[1] == strp[1] && !strcmp(name, strp)) {
 			if (symp->st_shndx != SHN_UNDEF)
 				return symp;
@@ -192,6 +194,7 @@
 	
 	/* Search all objects loaded at program start up. */
 	if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+		rdbg(("search _rtld_list_main"));
 		symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, in_plt);
 		if (symp != NULL &&
 		    (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
@@ -204,6 +207,7 @@
 	SIMPLEQ_FOREACH(elm, &refobj->dldags, link) {
 		if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
 			break;
+		rdbg(("search DAG with root %p (%s)", elm->obj, elm->obj->path));
 		symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt);
 		if (symp != NULL &&
 		    (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
@@ -214,6 +218,7 @@
 	
 	/* Search all RTLD_GLOBAL objects. */
 	if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
+		rdbg(("search _rtld_list_global"));
 		symp = _rtld_symlook_list(name, hash, &_rtld_list_global, &obj, in_plt);
 		if (symp != NULL &&
 		    (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
@@ -234,8 +239,10 @@
 	
 	if (def != NULL)
 		*defobj_out = defobj;
-	else
+	else {
+		rdbg(("lookup failed"));
 		_rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)",
 		    refobj->path, in_plt ? "PLT " : "", name, symnum);
+	}
 	return def;
 }