|
|
|
@ -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;
|
|
|
|
@ -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;
|
|
|
|
|
struct dl_phdr_info phdr_info;
|
|
|
|
|
Obj_Entry *obj, marker;
|
|
|
|
|
RtldLockState bind_lockstate, phdr_lockstate;
|
|
|
|
|
int error;
|
|
|
|
|
|
|
|
|
|
wlock_acquire(rtld_phdr_lock, &phdr_lockstate);
|
|
|
|
|
rlock_acquire(rtld_bind_lock, &bind_lockstate);
|
|
|
|
|
bzero(&marker, sizeof(marker));
|
|
|
|
|
marker.marker = true;
|
|
|
|
|
error = 0;
|
|
|
|
|
|
|
|
|
|
error = 0;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
error = callback(&phdr_info, sizeof phdr_info, param);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (error == 0) {
|
|
|
|
|
rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lock_release(rtld_bind_lock, &bind_lockstate);
|
|
|
|
|
lock_release(rtld_phdr_lock, &phdr_lockstate);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|