aboutsummaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorGlen Barber <gjb@FreeBSD.org>2016-01-20 09:50:54 +0000
committerGlen Barber <gjb@FreeBSD.org>2016-01-20 09:50:54 +0000
commit59d43d11fe3e3f490ad5fce4d0349e9eeaf8d765 (patch)
treeb62bad40f6761e8b139ebb94b63befbbbfc84604 /libexec
parenta11378bd93b579413444d7d4d2c102fa77580205 (diff)
parent7acd784290df33b5ff70f1f3f894ad64e9c25788 (diff)
downloadsrc-59d43d11fe3e3f490ad5fce4d0349e9eeaf8d765.tar.gz
src-59d43d11fe3e3f490ad5fce4d0349e9eeaf8d765.zip
MFH
Sponsored by: The FreeBSD Foundation
Notes
Notes: svn path=/projects/release-pkg/; revision=294408
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/aarch64/reloc.c4
-rw-r--r--libexec/rtld-elf/amd64/reloc.c3
-rw-r--r--libexec/rtld-elf/arm/reloc.c23
-rw-r--r--libexec/rtld-elf/debug.c3
-rw-r--r--libexec/rtld-elf/i386/reloc.c3
-rw-r--r--libexec/rtld-elf/paths.h2
-rw-r--r--libexec/rtld-elf/powerpc/reloc.c4
-rw-r--r--libexec/rtld-elf/powerpc64/reloc.c4
-rw-r--r--libexec/rtld-elf/riscv/reloc.c4
-rw-r--r--libexec/rtld-elf/rtld.c249
-rw-r--r--libexec/rtld-elf/rtld.h7
-rw-r--r--libexec/rtld-elf/sparc64/reloc.c4
12 files changed, 198 insertions, 112 deletions
diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c
index 7a9ce97e3ce9..de7ffd594821 100644
--- a/libexec/rtld-elf/aarch64/reloc.c
+++ b/libexec/rtld-elf/aarch64/reloc.c
@@ -99,8 +99,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;
diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c
index 989594469b48..80a3c35d6596 100644
--- a/libexec/rtld-elf/amd64/reloc.c
+++ b/libexec/rtld-elf/amd64/reloc.c
@@ -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;
diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c
index 6bdda735e713..5e21ca56cf44 100644
--- a/libexec/rtld-elf/arm/reloc.c
+++ b/libexec/rtld-elf/arm/reloc.c
@@ -3,6 +3,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
@@ -21,6 +22,7 @@ void
arm_abi_variant_hook(Elf_Auxinfo **aux_info)
{
Elf_Word ehdr;
+ struct stat sb;
/*
* If we're running an old kernel that doesn't provide any data fail
@@ -38,12 +40,19 @@ arm_abi_variant_hook(Elf_Auxinfo **aux_info)
return;
/*
+ * If there's no /usr/libsoft, then we don't have a system with both
+ * hard and soft float. In that case, hope for the best and just
+ * return. Such systems are required to have all soft or all hard
+ * float ABI binaries and libraries. This is, at best, a transition
+ * compatibility hack. Once we're fully hard-float, this should
+ * be removed.
+ */
+ if (stat("/usr/libsoft", &sb) != 0 || !S_ISDIR(sb.st_mode))
+ return;
+
+ /*
* This is a soft float ABI binary. We need to use the soft float
- * settings. For the moment, the standard library path includes the hard
- * float paths as well. When upgrading, we need to execute the wrong
- * kind of binary until we've installed the new binaries. We could go
- * off whether or not /libsoft exists, but the simplicity of having it
- * in the path wins.
+ * settings.
*/
ld_elf_hints_default = _PATH_SOFT_ELF_HINTS;
ld_path_libmap_conf = _PATH_SOFT_LIBMAP_CONF;
@@ -92,8 +101,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;
diff --git a/libexec/rtld-elf/debug.c b/libexec/rtld-elf/debug.c
index 8f8311c7793b..3c37b7f63e1c 100644
--- a/libexec/rtld-elf/debug.c
+++ b/libexec/rtld-elf/debug.c
@@ -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);
}
}
diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c
index 55b653713242..2d6021c97796 100644
--- a/libexec/rtld-elf/i386/reloc.c
+++ b/libexec/rtld-elf/i386/reloc.c
@@ -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;
diff --git a/libexec/rtld-elf/paths.h b/libexec/rtld-elf/paths.h
index abfeb3f3ce1a..7d9d372c293c 100644
--- a/libexec/rtld-elf/paths.h
+++ b/libexec/rtld-elf/paths.h
@@ -62,7 +62,7 @@
#define _PATH_SOFT_ELF_HINTS "/var/run/ld-elf-soft.so.hints"
#define _PATH_SOFT_LIBMAP_CONF "/etc/libmap-soft.conf"
#define _PATH_SOFT_RTLD "/libexec/ld-elf.so.1"
-#define SOFT_STANDARD_LIBRARY_PATH "/libsoft:/usr/libsoft:/lib:/usr/lib"
+#define SOFT_STANDARD_LIBRARY_PATH "/usr/libsoft"
#define LD_SOFT_ "LD_SOFT_"
extern char *ld_elf_hints_default;
diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c
index 1fe96764c56f..89a00894ca1d 100644
--- a/libexec/rtld-elf/powerpc/reloc.c
+++ b/libexec/rtld-elf/powerpc/reloc.c
@@ -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;
diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c
index c428d6b2a975..5cef3f8c59c7 100644
--- a/libexec/rtld-elf/powerpc64/reloc.c
+++ b/libexec/rtld-elf/powerpc64/reloc.c
@@ -90,8 +90,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;
diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c
index c43800a9407d..92c4276df08b 100644
--- a/libexec/rtld-elf/riscv/reloc.c
+++ b/libexec/rtld-elf/riscv/reloc.c
@@ -120,8 +120,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;
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index ad5d359452d4..06690ff22b1e 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -90,7 +90,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 variable for libraries to
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);
@@ -370,7 +369,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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;
@@ -435,7 +434,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
trust = !issetugid();
-/* md_abi_variant_hook(aux_info); */
+ md_abi_variant_hook(aux_info);
ld_bind_now = getenv(_LD("BIND_NOW"));
/*
@@ -569,8 +568,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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++;
@@ -585,7 +583,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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)
@@ -593,7 +591,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
/* 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;
@@ -651,7 +651,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
* 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]) : "");
@@ -660,7 +660,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
/* 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! */
@@ -690,7 +691,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
_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);
}
@@ -1410,9 +1413,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);
@@ -1823,6 +1827,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)
{
@@ -1905,7 +1935,7 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info)
}
/* 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));
@@ -1986,7 +2016,7 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list)
/* Process the current needed object. */
if (needed->obj != NULL)
- initlist_add_objects(needed->obj, &needed->obj->next, list);
+ initlist_add_objects(needed->obj, globallist_next(needed->obj), list);
}
/*
@@ -1999,16 +2029,18 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list)
* 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 && nobj != tail)
+ initlist_add_objects(nobj, tail, list);
/* Recursively process the needed objects. */
if (obj->needed != NULL)
@@ -2111,7 +2143,10 @@ load_needed_objects(Obj_Entry *first, int flags)
{
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);
}
@@ -2173,7 +2208,9 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
fd = -1;
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);
}
@@ -2218,9 +2255,12 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
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);
@@ -2288,8 +2328,7 @@ do_load_object(int fd, const char *name, char *path, struct stat *sbp,
}
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() */
@@ -2310,7 +2349,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))
@@ -2436,8 +2477,11 @@ objlist_call_init(Objlist *list, RtldLockState *lockstate)
* 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
@@ -2681,7 +2725,11 @@ relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj,
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)
@@ -2719,7 +2767,10 @@ resolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags,
{
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);
}
@@ -3033,7 +3084,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;
@@ -3047,7 +3098,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
}
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;
@@ -3060,8 +3111,9 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
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);
@@ -3088,7 +3140,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
*/
} else {
/* Make list of init functions to call. */
- initlist_add_objects(obj, &obj->next, &initlist);
+ initlist_add_objects(obj, globallist_next(obj), &initlist);
}
/*
* Process all no_delete or global objects here, given
@@ -3194,8 +3246,10 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
} 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 ||
@@ -3464,31 +3518,43 @@ rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
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;
-
- 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;
+ struct dl_phdr_info phdr_info;
+ Obj_Entry *obj, marker;
+ RtldLockState bind_lockstate, phdr_lockstate;
+ int error;
- }
- if (error == 0) {
- rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info);
- error = callback(&phdr_info, sizeof(phdr_info), param);
- }
+ 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);
+ lock_release(rtld_phdr_lock, &phdr_lockstate);
+
+ error = callback(&phdr_info, sizeof phdr_info, param);
+
+ wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
+ 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);
+ lock_release(rtld_phdr_lock, &phdr_lockstate);
+ error = callback(&phdr_info, sizeof(phdr_info), param);
+ }
+ return (error);
}
static void *
@@ -4208,11 +4274,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) {
@@ -4295,34 +4363,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);
-
- /* 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;
+ /*
+ * Pass over the DAG removing unreferenced objects from
+ * appropriate lists.
+ */
+ unlink_object(root);
+
+ /* 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
@@ -4455,7 +4519,8 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign)
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)
@@ -4554,15 +4619,16 @@ allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign)
*/
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;
- }
}
}
@@ -4611,7 +4677,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;
}
@@ -4690,7 +4758,8 @@ _rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign)
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);
}
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index 72a632e912e6..5fbfb271a3bf 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -139,7 +139,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;
@@ -264,6 +264,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 (%) */
@@ -276,6 +277,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. */
@@ -367,6 +370,8 @@ const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *,
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);
diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c
index 738a847d1d08..242fb8e4d948 100644
--- a/libexec/rtld-elf/sparc64/reloc.c
+++ b/libexec/rtld-elf/sparc64/reloc.c
@@ -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;