Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Aug 2018 18:00:21 +0200
From:      Michal Meloun <melounmichal@gmail.com>
To:        Brooks Davis <brooks@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r337978 - in head/libexec/rtld-elf: . aarch64 arm mips powerpc powerpc64 riscv
Message-ID:  <29d939de-108e-c7c4-b4b6-4a7772dca2eb@freebsd.org>
In-Reply-To: <201808171619.w7HGJlZe015255@repo.freebsd.org>
References:  <201808171619.w7HGJlZe015255@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help


On 17.08.2018 18:19, Brooks Davis wrote:
> 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
> 
This commit breaks TLS handling for (at least) armv7. Can you please
revert it until I will be able to identify where is problem?
In my case, the libc _ThreadRuneLocale symbol is not zero on program start.

Thanks,
Michal


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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?29d939de-108e-c7c4-b4b6-4a7772dca2eb>