Do not call callbacks for dl_iterate_phdr(3) with the rtld bind and

phdr locks locked.  This allows to call rtld services from the
callback, which is only reasonable for dlopen(path, RTLD_NOLOAD) to
test existence of the library in the image, and for dlsym().  The
later might still be not quite safe, due to the lazy resolution of
filters.

To allow dropping the locks around iteration in dl_iterate_phdr(3), we
insert markers to track current position between relocks.  The global
objects list is converted to tailq and all iterators skip markers,
globallist_next() and globallist_curr() helpers are added.

Reported and tested by:	davide
Reviewed by:	kan
Sponsored by:	The FreeBSD Foundation
MFC after:	3 weeks
This commit is contained in:
Konstantin Belousov 2016-01-20 07:21:33 +00:00
parent a63987426f
commit 9fee0541f2
11 changed files with 179 additions and 102 deletions

View File

@ -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;

View File

@ -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;

View File

@ -101,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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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;