svn commit: r296727 - in stable/10/libexec/rtld-elf: . amd64 arm i386 powerpc powerpc64 sparc64

Konstantin Belousov kib at FreeBSD.org
Sat Mar 12 17:12:03 UTC 2016


Author: kib
Date: Sat Mar 12 17:12:00 2016
New Revision: 296727
URL: https://svnweb.freebsd.org/changeset/base/296727

Log:
  MFC r257811 (by markj):
  Include rtld itself when iterating over loaded ELF objects in
  dl_iterate_phdr(3).
  
  MFC r294373:
  Do not call callbacks for dl_iterate_phdr(3) with the rtld bind and
  phdr locks locked.
  
  MFC r294470 (by kan):
  Fix initlist_add_object invocation parameters.
  
  MFC r294936 (by kan):
  Do not unlock rtld_phdr_lock over callback invocations.

Modified:
  stable/10/libexec/rtld-elf/amd64/reloc.c
  stable/10/libexec/rtld-elf/arm/reloc.c
  stable/10/libexec/rtld-elf/debug.c
  stable/10/libexec/rtld-elf/i386/reloc.c
  stable/10/libexec/rtld-elf/powerpc/reloc.c
  stable/10/libexec/rtld-elf/powerpc64/reloc.c
  stable/10/libexec/rtld-elf/rtld.c
  stable/10/libexec/rtld-elf/rtld.h
  stable/10/libexec/rtld-elf/sparc64/reloc.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/libexec/rtld-elf/amd64/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/amd64/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/amd64/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -85,7 +85,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
 	    req.flags = SYMLOOK_EARLY;
 
-	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
+	    for (srcobj = globallist_next(dstobj); srcobj != NULL;
+	      srcobj = globallist_next(srcobj)) {
 		res = symlook_obj(&req, srcobj);
 		if (res == 0) {
 		    srcsym = req.sym_out;

Modified: stable/10/libexec/rtld-elf/arm/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/arm/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/arm/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -56,8 +56,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 			    ELF_R_SYM(rel->r_info));
 			req.flags = SYMLOOK_EARLY;
 
-			for (srcobj = dstobj->next;  srcobj != NULL; 
-			     srcobj = srcobj->next) {
+			for (srcobj = globallist_next(dstobj); srcobj != NULL;
+			    srcobj = globallist_next(srcobj)) {
 				res = symlook_obj(&req, srcobj);
 				if (res == 0) {
 					srcsym = req.sym_out;

Modified: stable/10/libexec/rtld-elf/debug.c
==============================================================================
--- stable/10/libexec/rtld-elf/debug.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/debug.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -62,7 +62,8 @@ dump_relocations (Obj_Entry *obj0)
 {
     Obj_Entry *obj;
 
-    for (obj = obj0; obj != NULL; obj = obj->next) {
+    for (obj = globallist_curr(obj0); obj != NULL;
+      obj = globallist_next(obj)) {
         dump_obj_relocations(obj);
     }
 }

Modified: stable/10/libexec/rtld-elf/i386/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/i386/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/i386/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -86,7 +86,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info));
 	    req.flags = SYMLOOK_EARLY;
 
-	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
+	    for (srcobj = globallist_next(dstobj);  srcobj != NULL;
+	      srcobj = globallist_next(srcobj)) {
 		res = symlook_obj(&req, srcobj);
 		if (res == 0) {
 		    srcsym = req.sym_out;

Modified: stable/10/libexec/rtld-elf/powerpc/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/powerpc/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/powerpc/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -94,8 +94,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 		req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
 		req.flags = SYMLOOK_EARLY;
 
-		for (srcobj = dstobj->next;  srcobj != NULL;
-		     srcobj = srcobj->next) {
+		for (srcobj = globallist_next(dstobj); srcobj != NULL;
+		     srcobj = globallist_next(srcobj)) {
 			res = symlook_obj(&req, srcobj);
 			if (res == 0) {
 				srcsym = req.sym_out;

Modified: stable/10/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/powerpc64/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/powerpc64/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -88,8 +88,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 		req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
 		req.flags = SYMLOOK_EARLY;
 
-		for (srcobj = dstobj->next;  srcobj != NULL;
-		     srcobj = srcobj->next) {
+		for (srcobj = globallist_next(dstobj); srcobj != NULL;
+		     srcobj = globallist_next(srcobj)) {
 			res = symlook_obj(&req, srcobj);
 			if (res == 0) {
 				srcsym = req.sym_out;

Modified: stable/10/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/10/libexec/rtld-elf/rtld.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/rtld.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -95,7 +95,7 @@ static void init_dag(Obj_Entry *);
 static void init_pagesizes(Elf_Auxinfo **aux_info);
 static void init_rtld(caddr_t, Elf_Auxinfo **);
 static void initlist_add_neededs(Needed_Entry *, Objlist *);
-static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *);
+static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *);
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
 static void load_filtees(Obj_Entry *, int flags, RtldLockState *);
@@ -180,12 +180,11 @@ static char *ld_preload;	/* Environment 
 static char *ld_elf_hints_path;	/* Environment variable for alternative hints path */
 static char *ld_tracing;	/* Called from ldd to print libs */
 static char *ld_utrace;		/* Use utrace() to log events. */
-static Obj_Entry *obj_list;	/* Head of linked list of shared objects */
-static Obj_Entry **obj_tail;	/* Link field of last object in list */
+static struct obj_entry_q obj_list;	/* Queue of all loaded objects */
 static Obj_Entry *obj_main;	/* The main program shared object */
 static Obj_Entry obj_rtld;	/* The dynamic linker shared object */
 static unsigned int obj_count;	/* Number of objects in obj_list */
-static unsigned int obj_loads;	/* Number of objects in obj_list */
+static unsigned int obj_loads;	/* Number of loads of objects (gen count) */
 
 static Objlist list_global =	/* Objects dlopened with RTLD_GLOBAL */
   STAILQ_HEAD_INITIALIZER(list_global);
@@ -343,7 +342,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     const char *argv0;
     Objlist_Entry *entry;
     Obj_Entry *obj;
-    Obj_Entry **preload_tail;
+    Obj_Entry *preload_tail;
     Obj_Entry *last_interposer;
     Objlist initlist;
     RtldLockState lockstate;
@@ -538,8 +537,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     linkmap_add(&obj_rtld);
 
     /* Link the main program into the list of objects. */
-    *obj_tail = obj_main;
-    obj_tail = &obj_main->next;
+    TAILQ_INSERT_HEAD(&obj_list, obj_main, next);
     obj_count++;
     obj_loads++;
 
@@ -554,7 +552,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     dbg("loading LD_PRELOAD libraries");
     if (load_preload_objects() == -1)
 	rtld_die();
-    preload_tail = obj_tail;
+    preload_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q));
 
     dbg("loading needed objects");
     if (load_needed_objects(obj_main, 0) == -1)
@@ -562,7 +560,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
 
     /* Make a list of all objects loaded at startup. */
     last_interposer = obj_main;
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (obj->z_interpose && obj != obj_main) {
 	    objlist_put_after(&list_main, last_interposer, obj);
 	    last_interposer = obj;
@@ -620,7 +620,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
      * might be the subject for relocations.
      */
     dbg("initializing initial thread local storage");
-    allocate_initial_tls(obj_list);
+    allocate_initial_tls(globallist_curr(TAILQ_FIRST(&obj_list)));
 
     dbg("initializing key program variables");
     set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : "");
@@ -629,7 +629,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
 
     /* Make a list of init functions to call. */
     objlist_init(&initlist);
-    initlist_add_objects(obj_list, preload_tail, &initlist);
+    initlist_add_objects(globallist_curr(TAILQ_FIRST(&obj_list)),
+      preload_tail, &initlist);
 
     r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */
 
@@ -659,7 +660,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     _r_debug_postinit(&obj_main->linkmap);
     objlist_clear(&initlist);
     dbg("loading filtees");
-    for (obj = obj_list->next; obj != NULL; obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (ld_loadfltr || obj->z_loadfltr)
 	    load_filtees(obj, 0, &lockstate);
     }
@@ -1373,9 +1376,10 @@ dlcheck(void *handle)
 {
     Obj_Entry *obj;
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
 	if (obj == (Obj_Entry *) handle)
 	    break;
+    }
 
     if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) {
 	_rtld_error("Invalid shared object handle %p", handle);
@@ -1779,6 +1783,32 @@ init_dag(Obj_Entry *root)
     root->dag_inited = true;
 }
 
+Obj_Entry *
+globallist_curr(const Obj_Entry *obj)
+{
+
+	for (;;) {
+		if (obj == NULL)
+			return (NULL);
+		if (!obj->marker)
+			return (__DECONST(Obj_Entry *, obj));
+		obj = TAILQ_PREV(obj, obj_entry_q, next);
+	}
+}
+
+Obj_Entry *
+globallist_next(const Obj_Entry *obj)
+{
+
+	for (;;) {
+		obj = TAILQ_NEXT(obj, next);
+		if (obj == NULL)
+			return (NULL);
+		if (!obj->marker)
+			return (__DECONST(Obj_Entry *, obj));
+	}
+}
+
 static void
 process_z(Obj_Entry *root)
 {
@@ -1861,7 +1891,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo *
     }
 
     /* Initialize the object list. */
-    obj_tail = &obj_list;
+    TAILQ_INIT(&obj_list);
 
     /* Now that non-local variables can be accesses, copy out obj_rtld. */
     memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld));
@@ -1942,7 +1972,7 @@ initlist_add_neededs(Needed_Entry *neede
 
     /* Process the current needed object. */
     if (needed->obj != NULL)
-	initlist_add_objects(needed->obj, &needed->obj->next, list);
+	initlist_add_objects(needed->obj, needed->obj, list);
 }
 
 /*
@@ -1955,16 +1985,18 @@ initlist_add_neededs(Needed_Entry *neede
  * held when this function is called.
  */
 static void
-initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list)
+initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list)
 {
+    Obj_Entry *nobj;
 
     if (obj->init_scanned || obj->init_done)
 	return;
     obj->init_scanned = true;
 
     /* Recursively process the successor objects. */
-    if (&obj->next != tail)
-	initlist_add_objects(obj->next, tail, list);
+    nobj = globallist_next(obj);
+    if (nobj != NULL && obj != tail)
+	initlist_add_objects(nobj, tail, list);
 
     /* Recursively process the needed objects. */
     if (obj->needed != NULL)
@@ -2067,7 +2099,10 @@ load_needed_objects(Obj_Entry *first, in
 {
     Obj_Entry *obj;
 
-    for (obj = first;  obj != NULL;  obj = obj->next) {
+    obj = first;
+    TAILQ_FOREACH_FROM(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (process_needed(obj, obj->needed, flags) == -1)
 	    return (-1);
     }
@@ -2128,7 +2163,9 @@ load_object(const char *name, int fd_u, 
     char *path;
 
     if (name != NULL) {
-	for (obj = obj_list->next;  obj != NULL;  obj = obj->next) {
+	TAILQ_FOREACH(obj, &obj_list, next) {
+	    if (obj->marker)
+		continue;
 	    if (object_match_name(obj, name))
 		return (obj);
 	}
@@ -2169,9 +2206,12 @@ load_object(const char *name, int fd_u, 
 	free(path);
 	return NULL;
     }
-    for (obj = obj_list->next;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (obj->ino == sb.st_ino && obj->dev == sb.st_dev)
 	    break;
+    }
     if (obj != NULL && name != NULL) {
 	object_add_name(obj, name);
 	free(path);
@@ -2239,8 +2279,7 @@ do_load_object(int fd, const char *name,
     }
 
     obj->dlopened = (flags & RTLD_LO_DLOPEN) != 0;
-    *obj_tail = obj;
-    obj_tail = &obj->next;
+    TAILQ_INSERT_TAIL(&obj_list, obj, next);
     obj_count++;
     obj_loads++;
     linkmap_add(obj);	/* for GDB & dlinfo() */
@@ -2261,7 +2300,9 @@ obj_from_addr(const void *addr)
 {
     Obj_Entry *obj;
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (addr < (void *) obj->mapbase)
 	    continue;
 	if (addr < (void *) (obj->mapbase + obj->mapsize))
@@ -2387,8 +2428,11 @@ objlist_call_init(Objlist *list, RtldLoc
      * possibly initialized earlier if any of vectors called below
      * cause the change by using dlopen.
      */
-    for (obj = obj_list;  obj != NULL;  obj = obj->next)
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	obj->init_scanned = false;
+    }
 
     /*
      * Preserve the current error message since an init function might
@@ -2632,7 +2676,11 @@ relocate_objects(Obj_Entry *first, bool 
 	Obj_Entry *obj;
 	int error;
 
-	for (error = 0, obj = first;  obj != NULL;  obj = obj->next) {
+	error = 0;
+	obj = first;
+	TAILQ_FOREACH_FROM(obj, &obj_list, next) {
+		if (obj->marker)
+			continue;
 		error = relocate_object(obj, bind_now, rtldobj, flags,
 		    lockstate);
 		if (error == -1)
@@ -2670,7 +2718,10 @@ resolve_objects_ifunc(Obj_Entry *first, 
 {
 	Obj_Entry *obj;
 
-	for (obj = first;  obj != NULL;  obj = obj->next) {
+	obj = first;
+	TAILQ_FOREACH_FROM(obj, &obj_list, next) {
+		if (obj->marker)
+			continue;
 		if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1)
 			return (-1);
 	}
@@ -2921,7 +2972,7 @@ static Obj_Entry *
 dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
     int mode, RtldLockState *lockstate)
 {
-    Obj_Entry **old_obj_tail;
+    Obj_Entry *old_obj_tail;
     Obj_Entry *obj;
     Objlist initlist;
     RtldLockState mlockstate;
@@ -2935,7 +2986,7 @@ dlopen_object(const char *name, int fd, 
     }
     GDB_STATE(RT_ADD,NULL);
 
-    old_obj_tail = obj_tail;
+    old_obj_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q));
     obj = NULL;
     if (name == NULL && fd == -1) {
 	obj = obj_main;
@@ -2948,8 +2999,9 @@ dlopen_object(const char *name, int fd, 
 	obj->dl_refcount++;
 	if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL)
 	    objlist_push_tail(&list_global, obj);
-	if (*old_obj_tail != NULL) {		/* We loaded something new. */
-	    assert(*old_obj_tail == obj);
+	if (globallist_next(old_obj_tail) != NULL) {
+	    /* We loaded something new. */
+	    assert(globallist_next(old_obj_tail) == obj);
 	    result = load_needed_objects(obj,
 		lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY));
 	    init_dag(obj);
@@ -2976,7 +3028,7 @@ dlopen_object(const char *name, int fd, 
 		 */
 	    } else {
 		/* Make list of init functions to call. */
-		initlist_add_objects(obj, &obj->next, &initlist);
+		initlist_add_objects(obj, obj, &initlist);
 	    }
 	    /*
 	     * Process all no_delete or global objects here, given
@@ -3084,8 +3136,10 @@ do_dlsym(void *handle, const char *name,
 	} else if (handle == RTLD_NEXT || /* Objects after caller's */
 		   handle == RTLD_SELF) { /* ... caller included */
 	    if (handle == RTLD_NEXT)
-		obj = obj->next;
-	    for (; obj != NULL; obj = obj->next) {
+		obj = globallist_next(obj);
+	    TAILQ_FOREACH_FROM(obj, &obj_list, next) {
+		if (obj->marker)
+		    continue;
 		res = symlook_obj(&req, obj);
 		if (res == 0) {
 		    if (def == NULL ||
@@ -3361,26 +3415,41 @@ rtld_fill_dl_phdr_info(const Obj_Entry *
 int
 dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
 {
-    struct dl_phdr_info phdr_info;
-    const Obj_Entry *obj;
-    RtldLockState bind_lockstate, phdr_lockstate;
-    int error;
-
-    wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
-    rlock_acquire(rtld_bind_lock, &bind_lockstate);
-
-    error = 0;
+	struct dl_phdr_info phdr_info;
+	Obj_Entry *obj, marker;
+	RtldLockState bind_lockstate, phdr_lockstate;
+	int error;
 
-    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
-	rtld_fill_dl_phdr_info(obj, &phdr_info);
-	if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0)
-		break;
+	bzero(&marker, sizeof(marker));
+	marker.marker = true;
+	error = 0;
 
-    }
-    lock_release(rtld_bind_lock, &bind_lockstate);
-    lock_release(rtld_phdr_lock, &phdr_lockstate);
+	wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
+	rlock_acquire(rtld_bind_lock, &bind_lockstate);
+	for (obj = globallist_curr(TAILQ_FIRST(&obj_list)); obj != NULL;) {
+		TAILQ_INSERT_AFTER(&obj_list, obj, &marker, next);
+		rtld_fill_dl_phdr_info(obj, &phdr_info);
+		lock_release(rtld_bind_lock, &bind_lockstate);
+
+		error = callback(&phdr_info, sizeof phdr_info, param);
+
+		rlock_acquire(rtld_bind_lock, &bind_lockstate);
+		obj = globallist_next(&marker);
+		TAILQ_REMOVE(&obj_list, &marker, next);
+		if (error != 0) {
+			lock_release(rtld_bind_lock, &bind_lockstate);
+			lock_release(rtld_phdr_lock, &phdr_lockstate);
+			return (error);
+		}
+	}
 
-    return (error);
+	if (error == 0) {
+		rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info);
+		lock_release(rtld_bind_lock, &bind_lockstate);
+		error = callback(&phdr_info, sizeof(phdr_info), param);
+	}
+	lock_release(rtld_phdr_lock, &phdr_lockstate);
+	return (error);
 }
 
 static void *
@@ -4100,11 +4169,13 @@ trace_loaded_objects(Obj_Entry *obj)
 
     list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL");
 
-    for (; obj; obj = obj->next) {
+    TAILQ_FOREACH_FROM(obj, &obj_list, next) {
 	Needed_Entry		*needed;
 	char			*name, *path;
 	bool			is_lib;
 
+	if (obj->marker)
+	    continue;
 	if (list_containers && obj->needed != NULL)
 	    rtld_printf("%s:\n", obj->path);
 	for (needed = obj->needed; needed; needed = needed->next) {
@@ -4187,34 +4258,30 @@ trace_loaded_objects(Obj_Entry *obj)
 static void
 unload_object(Obj_Entry *root)
 {
-    Obj_Entry *obj;
-    Obj_Entry **linkp;
+	Obj_Entry *obj, *obj1;
 
-    assert(root->refcount == 0);
+	assert(root->refcount == 0);
 
-    /*
-     * Pass over the DAG removing unreferenced objects from
-     * appropriate lists.
-     */
-    unlink_object(root);
+	/*
+	 * Pass over the DAG removing unreferenced objects from
+	 * appropriate lists.
+	 */
+	unlink_object(root);
 
-    /* Unmap all objects that are no longer referenced. */
-    linkp = &obj_list->next;
-    while ((obj = *linkp) != NULL) {
-	if (obj->refcount == 0) {
-	    LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0,
-		obj->path);
-	    dbg("unloading \"%s\"", obj->path);
-	    unload_filtees(root);
-	    munmap(obj->mapbase, obj->mapsize);
-	    linkmap_delete(obj);
-	    *linkp = obj->next;
-	    obj_count--;
-	    obj_free(obj);
-	} else
-	    linkp = &obj->next;
-    }
-    obj_tail = linkp;
+	/* Unmap all objects that are no longer referenced. */
+	TAILQ_FOREACH_SAFE(obj, &obj_list, next, obj1) {
+		if (obj->marker || obj->refcount != 0)
+			continue;
+		LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase,
+		    obj->mapsize, 0, obj->path);
+		dbg("unloading \"%s\"", obj->path);
+		unload_filtees(root);
+		munmap(obj->mapbase, obj->mapsize);
+		linkmap_delete(obj);
+		TAILQ_REMOVE(&obj_list, obj, next);
+		obj_count--;
+		obj_free(obj);
+	}
 }
 
 static void
@@ -4346,7 +4413,8 @@ allocate_tls(Obj_Entry *objs, void *oldt
 	dtv[0] = tls_dtv_generation;
 	dtv[1] = tls_max_index;
 
-	for (obj = objs; obj; obj = obj->next) {
+	for (obj = globallist_curr(objs); obj != NULL;
+	  obj = globallist_next(obj)) {
 	    if (obj->tlsoffset > 0) {
 		addr = (Elf_Addr)tls + obj->tlsoffset;
 		if (obj->tlsinitsize > 0)
@@ -4445,15 +4513,16 @@ allocate_tls(Obj_Entry *objs, void *oldt
 	 */
 	free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr));
     } else {
-	for (obj = objs; obj; obj = obj->next) {
-	    if (obj->tlsoffset) {
+	obj = objs;
+	TAILQ_FOREACH_FROM(obj, &obj_list, next) {
+		if (obj->marker || obj->tlsoffset == 0)
+			continue;
 		addr = segbase - obj->tlsoffset;
 		memset((void*) (addr + obj->tlsinitsize),
 		       0, obj->tlssize - obj->tlsinitsize);
 		if (obj->tlsinit)
 		    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
 		dtv[obj->tlsindex + 1] = addr;
-	    }
 	}
     }
 
@@ -4502,7 +4571,9 @@ allocate_module_tls(int index)
     Obj_Entry* obj;
     char* p;
 
-    for (obj = obj_list; obj; obj = obj->next) {
+    TAILQ_FOREACH(obj, &obj_list, next) {
+	if (obj->marker)
+	    continue;
 	if (obj->tlsindex == index)
 	    break;
     }
@@ -4581,7 +4652,8 @@ _rtld_allocate_tls(void *oldtls, size_t 
     RtldLockState lockstate;
 
     wlock_acquire(rtld_bind_lock, &lockstate);
-    ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign);
+    ret = allocate_tls(globallist_curr(TAILQ_FIRST(&obj_list)), oldtls,
+      tcbsize, tcbalign);
     lock_release(rtld_bind_lock, &lockstate);
     return (ret);
 }

Modified: stable/10/libexec/rtld-elf/rtld.h
==============================================================================
--- stable/10/libexec/rtld-elf/rtld.h	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/rtld.h	Sat Mar 12 17:12:00 2016	(r296727)
@@ -155,7 +155,7 @@ typedef struct Struct_Obj_Entry {
     Elf_Size magic;		/* Magic number (sanity check) */
     Elf_Size version;		/* Version number of struct format */
 
-    struct Struct_Obj_Entry *next;
+    TAILQ_ENTRY(Struct_Obj_Entry) next;
     char *path;			/* Pathname of underlying file (%) */
     char *origin_path;		/* Directory path of origin file */
     int refcount;
@@ -277,6 +277,7 @@ typedef struct Struct_Obj_Entry {
     bool valid_hash_sysv : 1;	/* A valid System V hash hash tag is available */
     bool valid_hash_gnu : 1;	/* A valid GNU hash tag is available */
     bool dlopened : 1;		/* dlopen()-ed (vs. load statically) */
+    bool marker : 1;		/* marker on the global obj list */
 
     struct link_map linkmap;	/* For GDB and dlinfo() */
     Objlist dldags;		/* Object belongs to these dlopened DAGs (%) */
@@ -289,6 +290,8 @@ typedef struct Struct_Obj_Entry {
 #define RTLD_MAGIC	0xd550b87a
 #define RTLD_VERSION	1
 
+TAILQ_HEAD(obj_entry_q, Struct_Obj_Entry);
+
 #define RTLD_STATIC_TLS_EXTRA	128
 
 /* Flags to be passed into symlook_ family of functions. */
@@ -380,6 +383,8 @@ const Elf_Sym *find_symdef(unsigned long
 void init_pltgot(Obj_Entry *);
 void lockdflt_init(void);
 void digest_notes(Obj_Entry *, Elf_Addr, Elf_Addr);
+Obj_Entry *globallist_curr(const Obj_Entry *obj);
+Obj_Entry *globallist_next(const Obj_Entry *obj);
 void obj_free(Obj_Entry *);
 Obj_Entry *obj_new(void);
 void _rtld_bind_start(void);

Modified: stable/10/libexec/rtld-elf/sparc64/reloc.c
==============================================================================
--- stable/10/libexec/rtld-elf/sparc64/reloc.c	Sat Mar 12 17:06:45 2016	(r296726)
+++ stable/10/libexec/rtld-elf/sparc64/reloc.c	Sat Mar 12 17:12:00 2016	(r296727)
@@ -266,8 +266,8 @@ do_copy_relocations(Obj_Entry *dstobj)
 			    ELF_R_SYM(rela->r_info));
 			req.flags = SYMLOOK_EARLY;
 
-			for (srcobj = dstobj->next; srcobj != NULL;
-			    srcobj = srcobj->next) {
+			for (srcobj = globallist_next(dstobj); srcobj != NULL;
+			    srcobj = globallist_next(srcobj)) {
 				res = symlook_obj(&req, srcobj);
 				if (res == 0) {
 					srcsym = req.sym_out;


More information about the svn-src-all mailing list