From a5207d3ef62c069aa8edf3c2b28ed8a21001dfed Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 21 Aug 2018 18:22:12 +0000 Subject: [PATCH] Revert r337978: Rework rtld's TLS Variant I implementation to match r326794 Michal Meloun reports that it breaks ctype (isspace()..) related functions on armv7 so back out while we diagnose the issue. Reported by: Michal Meloun --- libexec/rtld-elf/aarch64/rtld_machdep.h | 2 - libexec/rtld-elf/arm/rtld_machdep.h | 2 - libexec/rtld-elf/mips/rtld_machdep.h | 3 +- libexec/rtld-elf/powerpc/rtld_machdep.h | 3 +- libexec/rtld-elf/powerpc64/rtld_machdep.h | 3 +- libexec/rtld-elf/riscv/rtld_machdep.h | 3 +- libexec/rtld-elf/rtld.c | 77 +++++------------------ 7 files changed, 20 insertions(+), 73 deletions(-) diff --git a/libexec/rtld-elf/aarch64/rtld_machdep.h b/libexec/rtld-elf/aarch64/rtld_machdep.h index 9ff53d900aaa..eb72a61b6fe8 100644 --- a/libexec/rtld-elf/aarch64/rtld_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_machdep.h @@ -69,8 +69,6 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) \ - round(TLS_TCB_SIZE, align) - TLS_TCB_SIZE #define TLS_TCB_SIZE 16 typedef struct { diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h index 030c83cdc7f4..926971c41524 100644 --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -69,8 +69,6 @@ typedef struct { #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) \ - round(TLS_TCB_SIZE, align) - TLS_TCB_SIZE extern void *__tls_get_addr(tls_index *ti); diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index e20c32794530..0cfb665e7898 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -64,11 +64,10 @@ typedef struct { #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - TLS_TCB_SIZE + round(TLS_TCB_SIZE, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) 0 extern void *__tls_get_addr(tls_index *ti); diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h index c89ec4817401..584ccd977ec0 100644 --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -74,11 +74,10 @@ void _rtld_powerpc_pltcall(void); #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - TLS_TCB_SIZE + round(8, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) 0 typedef struct { unsigned long ti_module; diff --git a/libexec/rtld-elf/powerpc64/rtld_machdep.h b/libexec/rtld-elf/powerpc64/rtld_machdep.h index b0f71d312db0..cf42db426f4f 100644 --- a/libexec/rtld-elf/powerpc64/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc64/rtld_machdep.h @@ -66,11 +66,10 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - TLS_TCB_SIZE + round(16, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) 0 typedef struct { unsigned long ti_module; diff --git a/libexec/rtld-elf/riscv/rtld_machdep.h b/libexec/rtld-elf/riscv/rtld_machdep.h index 1737fa73ff8b..bb1f6868f1ac 100644 --- a/libexec/rtld-elf/riscv/rtld_machdep.h +++ b/libexec/rtld-elf/riscv/rtld_machdep.h @@ -89,11 +89,10 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - TLS_TCB_SIZE + round(16, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) -#define calculate_tls_post_size(align) 0 typedef struct { unsigned long ti_module; diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index dfd0388478f9..43240568b3e8 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -4692,88 +4692,48 @@ tls_get_addr_common(Elf_Addr **dtvp, int index, size_t offset) #if defined(__aarch64__) || defined(__arm__) || defined(__mips__) || \ defined(__powerpc__) || defined(__riscv) -/* - * Return pointer to allocated TLS block - */ -static void * -get_tls_block_ptr(void *tcb, size_t tcbsize) -{ - size_t extra_size, post_size, pre_size, tls_block_size; - size_t tls_init_align; - - tls_init_align = MAX(obj_main->tlsalign, 1); - - /* Compute fragments sizes. */ - extra_size = tcbsize - TLS_TCB_SIZE; - post_size = calculate_tls_post_size(tls_init_align); - tls_block_size = tcbsize + post_size; - pre_size = roundup2(tls_block_size, tls_init_align) - tls_block_size; - - return ((char *)tcb - pre_size - extra_size); -} - /* * Allocate Static TLS using the Variant I method. - * - * For details on the layout, see lib/libc/gen/tls.c. - * - * NB: rtld's tls_static_space variable includes TLS_TCB_SIZE and post_size as - * it is based on tls_last_offset, and TLS offsets here are really TCB - * offsets, whereas libc's tls_static_space is just the executable's static - * TLS segment. */ void * allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) { Obj_Entry *obj; - char *tls_block; - Elf_Addr *dtv, **tcb; + char *tcb; + Elf_Addr **tls; + Elf_Addr *dtv; Elf_Addr addr; int i; - size_t extra_size, maxalign, post_size, pre_size, tls_block_size; - size_t tls_init_align; if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) return (oldtcb); assert(tcbsize >= TLS_TCB_SIZE); - maxalign = MAX(tcbalign, tls_static_max_align); - tls_init_align = MAX(obj_main->tlsalign, 1); - - /* Compute fragmets sizes. */ - extra_size = tcbsize - TLS_TCB_SIZE; - post_size = calculate_tls_post_size(tls_init_align); - tls_block_size = tcbsize + post_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; - - /* Allocate whole TLS block */ - tls_block = malloc_aligned(tls_block_size, maxalign); - tcb = (Elf_Addr **)(tls_block + pre_size + extra_size); + tcb = xcalloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize); + tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); if (oldtcb != NULL) { - memcpy(tls_block, get_tls_block_ptr(oldtcb, tcbsize), - tls_static_space); - free_aligned(get_tls_block_ptr(oldtcb, tcbsize)); + memcpy(tls, oldtcb, tls_static_space); + free(oldtcb); /* Adjust the DTV. */ - dtv = tcb[0]; + dtv = tls[0]; for (i = 0; i < dtv[1]; i++) { if (dtv[i+2] >= (Elf_Addr)oldtcb && 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)tls; } } } else { dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); - tcb[0] = dtv; + tls[0] = dtv; dtv[0] = tls_dtv_generation; dtv[1] = tls_max_index; for (obj = globallist_curr(objs); obj != NULL; obj = globallist_next(obj)) { if (obj->tlsoffset > 0) { - addr = (Elf_Addr)tcb + obj->tlsoffset; + addr = (Elf_Addr)tls + obj->tlsoffset; if (obj->tlsinitsize > 0) memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); if (obj->tlssize > obj->tlsinitsize) @@ -4792,19 +4752,14 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign) { Elf_Addr *dtv; Elf_Addr tlsstart, tlsend; - size_t post_size; - size_t dtvsize, i, tls_init_align; + int dtvsize, i; assert(tcbsize >= TLS_TCB_SIZE); - tls_init_align = MAX(obj_main->tlsalign, 1); - /* Compute fragments sizes. */ - post_size = calculate_tls_post_size(tls_init_align); + tlsstart = (Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE; + tlsend = tlsstart + tls_static_space; - tlsstart = (Elf_Addr)tcb + TLS_TCB_SIZE + post_size; - tlsend = (Elf_Addr)tcb + tls_static_space; - - dtv = *(Elf_Addr **)tcb; + dtv = *(Elf_Addr **)tlsstart; dtvsize = dtv[1]; for (i = 0; i < dtvsize; i++) { if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] >= tlsend)) { @@ -4812,7 +4767,7 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign) } } free(dtv); - free_aligned(get_tls_block_ptr(tcb, tcbsize)); + free(tcb); } #endif