Changeset View
Changeset View
Standalone View
Standalone View
libexec/rtld-elf/rtld.c
Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static const char *basename(const char *); | static const char *basename(const char *); | ||||
static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, | static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, | ||||
const Elf_Dyn **, const Elf_Dyn **); | const Elf_Dyn **, const Elf_Dyn **); | ||||
static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, | static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, | ||||
const Elf_Dyn *); | const Elf_Dyn *); | ||||
static void digest_dynamic(Obj_Entry *, int); | static void digest_dynamic(Obj_Entry *, int); | ||||
static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); | static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); | ||||
static void distribute_static_tls(Objlist *, RtldLockState *); | |||||
static Obj_Entry *dlcheck(void *); | static Obj_Entry *dlcheck(void *); | ||||
static int dlclose_locked(void *, RtldLockState *); | static int dlclose_locked(void *, RtldLockState *); | ||||
static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, | static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, | ||||
int lo_flags, int mode, RtldLockState *lockstate); | int lo_flags, int mode, RtldLockState *lockstate); | ||||
static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); | static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); | ||||
static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); | static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); | ||||
static bool donelist_check(DoneList *, const Obj_Entry *); | static bool donelist_check(DoneList *, const Obj_Entry *); | ||||
static void errmsg_restore(char *); | static void errmsg_restore(char *); | ||||
▲ Show 20 Lines • Show All 1,139 Lines • ▼ Show 20 Lines | case DT_FLAGS: | ||||
if (dynp->d_un.d_val & DF_ORIGIN) | if (dynp->d_un.d_val & DF_ORIGIN) | ||||
obj->z_origin = true; | obj->z_origin = true; | ||||
if (dynp->d_un.d_val & DF_SYMBOLIC) | if (dynp->d_un.d_val & DF_SYMBOLIC) | ||||
obj->symbolic = true; | obj->symbolic = true; | ||||
if (dynp->d_un.d_val & DF_TEXTREL) | if (dynp->d_un.d_val & DF_TEXTREL) | ||||
obj->textrel = true; | obj->textrel = true; | ||||
if (dynp->d_un.d_val & DF_BIND_NOW) | if (dynp->d_un.d_val & DF_BIND_NOW) | ||||
obj->bind_now = true; | obj->bind_now = true; | ||||
/*if (dynp->d_un.d_val & DF_STATIC_TLS) | if (dynp->d_un.d_val & DF_STATIC_TLS) | ||||
;*/ | obj->static_tls = true; | ||||
break; | break; | ||||
#ifdef __mips__ | #ifdef __mips__ | ||||
case DT_MIPS_LOCAL_GOTNO: | case DT_MIPS_LOCAL_GOTNO: | ||||
obj->local_gotno = dynp->d_un.d_val; | obj->local_gotno = dynp->d_un.d_val; | ||||
break; | break; | ||||
case DT_MIPS_SYMTABNO: | case DT_MIPS_SYMTABNO: | ||||
obj->symtabno = dynp->d_un.d_val; | obj->symtabno = dynp->d_un.d_val; | ||||
▲ Show 20 Lines • Show All 2,065 Lines • ▼ Show 20 Lines | obj = load_object(name, fd, refobj, lo_flags); | ||||
if (obj) { | if (obj) { | ||||
obj->dl_refcount++; | obj->dl_refcount++; | ||||
if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) | if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) | ||||
objlist_push_tail(&list_global, obj); | objlist_push_tail(&list_global, obj); | ||||
if (globallist_next(old_obj_tail) != NULL) { | if (globallist_next(old_obj_tail) != NULL) { | ||||
/* We loaded something new. */ | /* We loaded something new. */ | ||||
assert(globallist_next(old_obj_tail) == obj); | assert(globallist_next(old_obj_tail) == obj); | ||||
result = load_needed_objects(obj, | result = 0; | ||||
lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY)); | if ((lo_flags & RTLD_LO_EARLY) == 0 && obj->static_tls && | ||||
!allocate_tls_offset(obj)) { | |||||
_rtld_error("%s: No space available " | |||||
"for static Thread Local Storage", obj->path); | |||||
result = -1; | |||||
} | |||||
if (result != -1) | |||||
result = load_needed_objects(obj, lo_flags & (RTLD_LO_DLOPEN | | |||||
RTLD_LO_EARLY)); | |||||
init_dag(obj); | init_dag(obj); | ||||
ref_dag(obj); | ref_dag(obj); | ||||
if (result != -1) | if (result != -1) | ||||
result = rtld_verify_versions(&obj->dagmembers); | result = rtld_verify_versions(&obj->dagmembers); | ||||
if (result != -1 && ld_tracing) | if (result != -1 && ld_tracing) | ||||
goto trace; | goto trace; | ||||
if (result == -1 || relocate_object_dag(obj, | if (result == -1 || relocate_object_dag(obj, | ||||
(mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, | (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | obj->z_nodelete) && !obj->ref_nodel) { | ||||
obj->z_nodelete = obj->ref_nodel = true; | obj->z_nodelete = obj->ref_nodel = true; | ||||
} | } | ||||
} | } | ||||
LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, | LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, | ||||
name); | name); | ||||
GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); | GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); | ||||
if (!(lo_flags & RTLD_LO_EARLY)) { | if ((lo_flags & RTLD_LO_EARLY) == 0) { | ||||
map_stacks_exec(lockstate); | map_stacks_exec(lockstate); | ||||
if (obj != NULL) | |||||
distribute_static_tls(&initlist, lockstate); | |||||
} | } | ||||
if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == RTLD_NOW, | if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == RTLD_NOW, | ||||
(lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, | (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, | ||||
lockstate) == -1) { | lockstate) == -1) { | ||||
objlist_clear(&initlist); | objlist_clear(&initlist); | ||||
dlopen_cleanup(obj, lockstate); | dlopen_cleanup(obj, lockstate); | ||||
if (lockstate == &mlockstate) | if (lockstate == &mlockstate) | ||||
▲ Show 20 Lines • Show All 1,508 Lines • ▼ Show 20 Lines | allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) | ||||
free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); | free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); | ||||
} else { | } else { | ||||
for (obj = objs; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | for (obj = objs; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | ||||
if (obj->marker || obj->tlsoffset == 0) | if (obj->marker || obj->tlsoffset == 0) | ||||
continue; | continue; | ||||
addr = segbase - obj->tlsoffset; | addr = segbase - obj->tlsoffset; | ||||
memset((void*)(addr + obj->tlsinitsize), | memset((void*)(addr + obj->tlsinitsize), | ||||
0, obj->tlssize - obj->tlsinitsize); | 0, obj->tlssize - obj->tlsinitsize); | ||||
if (obj->tlsinit) | if (obj->tlsinit) { | ||||
memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); | memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); | ||||
obj->static_tls_copied = true; | |||||
} | |||||
dtv[obj->tlsindex + 1] = addr; | dtv[obj->tlsindex + 1] = addr; | ||||
} | } | ||||
} | } | ||||
return (void*) segbase; | return (void*) segbase; | ||||
} | } | ||||
void | void | ||||
▲ Show 20 Lines • Show All 442 Lines • ▼ Show 20 Lines | map_stacks_exec(RtldLockState *lockstate) | ||||
if ((max_stack_flags & PF_X) == 0 || (stack_prot & PROT_EXEC) != 0) | if ((max_stack_flags & PF_X) == 0 || (stack_prot & PROT_EXEC) != 0) | ||||
return; | return; | ||||
thr_map_stacks_exec = (void (*)(void))(uintptr_t) | thr_map_stacks_exec = (void (*)(void))(uintptr_t) | ||||
get_program_var_addr("__pthread_map_stacks_exec", lockstate); | get_program_var_addr("__pthread_map_stacks_exec", lockstate); | ||||
if (thr_map_stacks_exec != NULL) { | if (thr_map_stacks_exec != NULL) { | ||||
stack_prot |= PROT_EXEC; | stack_prot |= PROT_EXEC; | ||||
thr_map_stacks_exec(); | thr_map_stacks_exec(); | ||||
} | |||||
} | |||||
static void | |||||
distribute_static_tls(Objlist *list, RtldLockState *lockstate) | |||||
{ | |||||
Objlist_Entry *elm; | |||||
Obj_Entry *obj; | |||||
void (*distrib)(size_t, void *, size_t, size_t); | |||||
distrib = (void (*)(size_t, void *, size_t, size_t))(uintptr_t) | |||||
get_program_var_addr("__pthread_distribute_static_tls", lockstate); | |||||
if (distrib == NULL) | |||||
return; | |||||
STAILQ_FOREACH(elm, list, link) { | |||||
obj = elm->obj; | |||||
if (obj->marker || !obj->tls_done || obj->static_tls_copied) | |||||
continue; | |||||
distrib(obj->tlsoffset, obj->tlsinit, obj->tlsinitsize, | |||||
obj->tlssize); | |||||
obj->static_tls_copied = true; | |||||
} | } | ||||
} | } | ||||
void | void | ||||
symlook_init(SymLook *dst, const char *name) | symlook_init(SymLook *dst, const char *name) | ||||
{ | { | ||||
bzero(dst, sizeof(*dst)); | bzero(dst, sizeof(*dst)); | ||||
▲ Show 20 Lines • Show All 282 Lines • Show Last 20 Lines |