Changeset View
Changeset View
Standalone View
Standalone View
head/libexec/rtld-elf/rtld.c
Show First 20 Lines • Show All 1,495 Lines • ▼ Show 20 Lines | case PT_DYNAMIC: | ||||
break; | break; | ||||
case PT_TLS: | case PT_TLS: | ||||
obj->tlsindex = 1; | obj->tlsindex = 1; | ||||
obj->tlssize = ph->p_memsz; | obj->tlssize = ph->p_memsz; | ||||
obj->tlsalign = ph->p_align; | obj->tlsalign = ph->p_align; | ||||
obj->tlsinitsize = ph->p_filesz; | obj->tlsinitsize = ph->p_filesz; | ||||
obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); | obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); | ||||
obj->tlspoffset = ph->p_offset; | |||||
break; | break; | ||||
case PT_GNU_STACK: | case PT_GNU_STACK: | ||||
obj->stack_flags = ph->p_flags; | obj->stack_flags = ph->p_flags; | ||||
break; | break; | ||||
case PT_GNU_RELRO: | case PT_GNU_RELRO: | ||||
obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); | obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); | ||||
▲ Show 20 Lines • Show All 3,351 Lines • ▼ Show 20 Lines | |||||
allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) | allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) | ||||
{ | { | ||||
Obj_Entry *obj; | Obj_Entry *obj; | ||||
char *tls_block; | char *tls_block; | ||||
Elf_Addr *dtv, **tcb; | Elf_Addr *dtv, **tcb; | ||||
Elf_Addr addr; | Elf_Addr addr; | ||||
Elf_Addr i; | Elf_Addr i; | ||||
size_t extra_size, maxalign, post_size, pre_size, tls_block_size; | size_t extra_size, maxalign, post_size, pre_size, tls_block_size; | ||||
size_t tls_init_align; | size_t tls_init_align, tls_init_offset; | ||||
if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) | if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) | ||||
return (oldtcb); | return (oldtcb); | ||||
assert(tcbsize >= TLS_TCB_SIZE); | assert(tcbsize >= TLS_TCB_SIZE); | ||||
maxalign = MAX(tcbalign, tls_static_max_align); | maxalign = MAX(tcbalign, tls_static_max_align); | ||||
tls_init_align = MAX(obj_main->tlsalign, 1); | tls_init_align = MAX(obj_main->tlsalign, 1); | ||||
/* Compute fragmets sizes. */ | /* Compute fragmets sizes. */ | ||||
extra_size = tcbsize - TLS_TCB_SIZE; | extra_size = tcbsize - TLS_TCB_SIZE; | ||||
post_size = calculate_tls_post_size(tls_init_align); | post_size = calculate_tls_post_size(tls_init_align); | ||||
tls_block_size = tcbsize + post_size; | tls_block_size = tcbsize + post_size; | ||||
pre_size = roundup2(tls_block_size, tls_init_align) - tls_block_size; | pre_size = roundup2(tls_block_size, tls_init_align) - tls_block_size; | ||||
tls_block_size += pre_size + tls_static_space - TLS_TCB_SIZE - post_size; | tls_block_size += pre_size + tls_static_space - TLS_TCB_SIZE - post_size; | ||||
/* Allocate whole TLS block */ | /* Allocate whole TLS block */ | ||||
tls_block = malloc_aligned(tls_block_size, maxalign); | tls_block = malloc_aligned(tls_block_size, maxalign, 0); | ||||
tcb = (Elf_Addr **)(tls_block + pre_size + extra_size); | tcb = (Elf_Addr **)(tls_block + pre_size + extra_size); | ||||
if (oldtcb != NULL) { | if (oldtcb != NULL) { | ||||
memcpy(tls_block, get_tls_block_ptr(oldtcb, tcbsize), | memcpy(tls_block, get_tls_block_ptr(oldtcb, tcbsize), | ||||
tls_static_space); | tls_static_space); | ||||
free_aligned(get_tls_block_ptr(oldtcb, tcbsize)); | free_aligned(get_tls_block_ptr(oldtcb, tcbsize)); | ||||
/* Adjust the DTV. */ | /* Adjust the DTV. */ | ||||
dtv = tcb[0]; | dtv = tcb[0]; | ||||
for (i = 0; i < dtv[1]; i++) { | for (i = 0; i < dtv[1]; i++) { | ||||
if (dtv[i+2] >= (Elf_Addr)oldtcb && | if (dtv[i+2] >= (Elf_Addr)oldtcb && | ||||
dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) { | dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) { | ||||
dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tcb; | dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tcb; | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); | dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); | ||||
tcb[0] = dtv; | tcb[0] = dtv; | ||||
dtv[0] = tls_dtv_generation; | dtv[0] = tls_dtv_generation; | ||||
dtv[1] = tls_max_index; | dtv[1] = tls_max_index; | ||||
for (obj = globallist_curr(objs); obj != NULL; | for (obj = globallist_curr(objs); obj != NULL; | ||||
obj = globallist_next(obj)) { | obj = globallist_next(obj)) { | ||||
if (obj->tlsoffset > 0) { | if (obj->tlsoffset == 0) | ||||
continue; | |||||
tls_init_offset = obj->tlspoffset & (obj->tlsalign - 1); | |||||
addr = (Elf_Addr)tcb + obj->tlsoffset; | addr = (Elf_Addr)tcb + obj->tlsoffset; | ||||
if (obj->tlsinitsize > 0) | if (tls_init_offset > 0) | ||||
memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); | memset((void *)addr, 0, tls_init_offset); | ||||
if (obj->tlssize > obj->tlsinitsize) | if (obj->tlsinitsize > 0) { | ||||
memset((void*)(addr + obj->tlsinitsize), 0, | memcpy((void *)(addr + tls_init_offset), obj->tlsinit, | ||||
obj->tlssize - obj->tlsinitsize); | obj->tlsinitsize); | ||||
dtv[obj->tlsindex + 1] = addr; | |||||
} | } | ||||
if (obj->tlssize > obj->tlsinitsize) { | |||||
memset((void *)(addr + tls_init_offset + obj->tlsinitsize), | |||||
0, obj->tlssize - obj->tlsinitsize - tls_init_offset); | |||||
} | } | ||||
dtv[obj->tlsindex + 1] = addr; | |||||
} | } | ||||
} | |||||
return (tcb); | return (tcb); | ||||
} | } | ||||
void | void | ||||
free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) | free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) | ||||
{ | { | ||||
Elf_Addr *dtv; | Elf_Addr *dtv; | ||||
Show All 39 Lines | allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) | ||||
size_t i; | size_t i; | ||||
ralign = tcbalign; | ralign = tcbalign; | ||||
if (tls_static_max_align > ralign) | if (tls_static_max_align > ralign) | ||||
ralign = tls_static_max_align; | ralign = tls_static_max_align; | ||||
size = round(tls_static_space, ralign) + round(tcbsize, ralign); | size = round(tls_static_space, ralign) + round(tcbsize, ralign); | ||||
assert(tcbsize >= 2*sizeof(Elf_Addr)); | assert(tcbsize >= 2*sizeof(Elf_Addr)); | ||||
tls = malloc_aligned(size, ralign); | tls = malloc_aligned(size, ralign, 0 /* XXX */); | ||||
dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); | dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); | ||||
segbase = (Elf_Addr)(tls + round(tls_static_space, ralign)); | segbase = (Elf_Addr)(tls + round(tls_static_space, ralign)); | ||||
((Elf_Addr*)segbase)[0] = segbase; | ((Elf_Addr*)segbase)[0] = segbase; | ||||
((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; | ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; | ||||
dtv[0] = tls_dtv_generation; | dtv[0] = tls_dtv_generation; | ||||
dtv[1] = tls_max_index; | dtv[1] = tls_max_index; | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
/* | /* | ||||
* Allocate TLS block for module with given index. | * Allocate TLS block for module with given index. | ||||
*/ | */ | ||||
void * | void * | ||||
allocate_module_tls(int index) | allocate_module_tls(int index) | ||||
{ | { | ||||
Obj_Entry* obj; | Obj_Entry *obj; | ||||
char* p; | char *p; | ||||
TAILQ_FOREACH(obj, &obj_list, next) { | TAILQ_FOREACH(obj, &obj_list, next) { | ||||
if (obj->marker) | if (obj->marker) | ||||
continue; | continue; | ||||
if (obj->tlsindex == index) | if (obj->tlsindex == index) | ||||
break; | break; | ||||
} | } | ||||
if (!obj) { | if (obj == NULL) { | ||||
_rtld_error("Can't find module with TLS index %d", index); | _rtld_error("Can't find module with TLS index %d", index); | ||||
rtld_die(); | rtld_die(); | ||||
} | } | ||||
p = malloc_aligned(obj->tlssize, obj->tlsalign); | p = malloc_aligned(obj->tlssize, obj->tlsalign, obj->tlspoffset); | ||||
memcpy(p, obj->tlsinit, obj->tlsinitsize); | memcpy(p, obj->tlsinit, obj->tlsinitsize); | ||||
memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); | memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); | ||||
return (p); | |||||
return p; | |||||
} | } | ||||
bool | bool | ||||
allocate_tls_offset(Obj_Entry *obj) | allocate_tls_offset(Obj_Entry *obj) | ||||
{ | { | ||||
size_t off; | size_t off; | ||||
if (obj->tls_done) | if (obj->tls_done) | ||||
▲ Show 20 Lines • Show All 674 Lines • Show Last 20 Lines |