From owner-svn-src-head@freebsd.org Fri Aug 17 16:19:49 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7F14010744DB; Fri, 17 Aug 2018 16:19:49 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 291FB86ADC; Fri, 17 Aug 2018 16:19:49 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E077D2BBF; Fri, 17 Aug 2018 16:19:48 +0000 (UTC) (envelope-from brooks@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w7HGJmDK015262; Fri, 17 Aug 2018 16:19:48 GMT (envelope-from brooks@FreeBSD.org) Received: (from brooks@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w7HGJlZe015255; Fri, 17 Aug 2018 16:19:47 GMT (envelope-from brooks@FreeBSD.org) Message-Id: <201808171619.w7HGJlZe015255@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: brooks set sender to brooks@FreeBSD.org using -f From: Brooks Davis Date: Fri, 17 Aug 2018 16:19:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r337978 - in head/libexec/rtld-elf: . aarch64 arm mips powerpc powerpc64 riscv X-SVN-Group: head X-SVN-Commit-Author: brooks X-SVN-Commit-Paths: in head/libexec/rtld-elf: . aarch64 arm mips powerpc powerpc64 riscv X-SVN-Commit-Revision: 337978 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Aug 2018 16:19:49 -0000 Author: brooks Date: Fri Aug 17 16:19:47 2018 New Revision: 337978 URL: https://svnweb.freebsd.org/changeset/base/337978 Log: Rework rtld's TLS Variant I implementation to match r326794 The above commit fixed handling overaligned TLS segments in libc's TLS Variant I implementation, but rtld provides its own implementation for dynamically-linked executables which lacks these fixes. Thus, port these changes to rtld. Submitted by: James Clarke Reviewed by: kbowling Testing byL kbowling (powerpc64), br (riscv), kevans (armv7) Obtained from: CheriBSD Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D16510 Modified: head/libexec/rtld-elf/aarch64/rtld_machdep.h head/libexec/rtld-elf/arm/rtld_machdep.h head/libexec/rtld-elf/mips/rtld_machdep.h head/libexec/rtld-elf/powerpc/rtld_machdep.h head/libexec/rtld-elf/powerpc64/rtld_machdep.h head/libexec/rtld-elf/riscv/rtld_machdep.h head/libexec/rtld-elf/rtld.c Modified: head/libexec/rtld-elf/aarch64/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/aarch64/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/aarch64/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -69,6 +69,8 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr targe #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 { Modified: head/libexec/rtld-elf/arm/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/arm/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/arm/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -69,6 +69,8 @@ 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); Modified: head/libexec/rtld-elf/mips/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/mips/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/mips/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -64,10 +64,11 @@ typedef struct { #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(TLS_TCB_SIZE, align) + TLS_TCB_SIZE #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); Modified: head/libexec/rtld-elf/powerpc/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/powerpc/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/powerpc/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -74,10 +74,11 @@ void _rtld_powerpc_pltcall(void); #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(8, align) + TLS_TCB_SIZE #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; Modified: head/libexec/rtld-elf/powerpc64/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/powerpc64/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/powerpc64/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -66,10 +66,11 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr targe #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(16, align) + TLS_TCB_SIZE #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; Modified: head/libexec/rtld-elf/riscv/rtld_machdep.h ============================================================================== --- head/libexec/rtld-elf/riscv/rtld_machdep.h Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/riscv/rtld_machdep.h Fri Aug 17 16:19:47 2018 (r337978) @@ -89,10 +89,11 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr targe #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(16, align) + TLS_TCB_SIZE #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; Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Fri Aug 17 16:07:06 2018 (r337977) +++ head/libexec/rtld-elf/rtld.c Fri Aug 17 16:19:47 2018 (r337978) @@ -4693,47 +4693,87 @@ tls_get_addr_common(Elf_Addr **dtvp, int index, size_t 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 *tcb; - Elf_Addr **tls; - Elf_Addr *dtv; + char *tls_block; + Elf_Addr *dtv, **tcb; 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); - tcb = xcalloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize); - tls = (Elf_Addr **)(tcb + 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); + if (oldtcb != NULL) { - memcpy(tls, oldtcb, tls_static_space); - free(oldtcb); + memcpy(tls_block, get_tls_block_ptr(oldtcb, tcbsize), + tls_static_space); + free_aligned(get_tls_block_ptr(oldtcb, tcbsize)); /* Adjust the DTV. */ - dtv = tls[0]; + dtv = tcb[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)tls; + dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tcb; } } } else { dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); - tls[0] = dtv; + tcb[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)tls + obj->tlsoffset; + addr = (Elf_Addr)tcb + obj->tlsoffset; if (obj->tlsinitsize > 0) memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); if (obj->tlssize > obj->tlsinitsize) @@ -4752,14 +4792,19 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign) { Elf_Addr *dtv; Elf_Addr tlsstart, tlsend; - int dtvsize, i; + size_t post_size; + size_t dtvsize, i, tls_init_align; assert(tcbsize >= TLS_TCB_SIZE); + tls_init_align = MAX(obj_main->tlsalign, 1); - tlsstart = (Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE; - tlsend = tlsstart + tls_static_space; + /* Compute fragments sizes. */ + post_size = calculate_tls_post_size(tls_init_align); - dtv = *(Elf_Addr **)tlsstart; + tlsstart = (Elf_Addr)tcb + TLS_TCB_SIZE + post_size; + tlsend = (Elf_Addr)tcb + tls_static_space; + + dtv = *(Elf_Addr **)tcb; dtvsize = dtv[1]; for (i = 0; i < dtvsize; i++) { if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] >= tlsend)) { @@ -4767,7 +4812,7 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign) } } free(dtv); - free(tcb); + free_aligned(get_tls_block_ptr(tcb, tcbsize)); } #endif