Blame sysdeps/i386/dl-tlsdesc.S

Packit 6c4009
/* Thread-local storage handling in the ELF dynamic linker.  i386 version.
Packit 6c4009
   Copyright (C) 2004-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <tls.h>
Packit 6c4009
#include "tlsdesc.h"
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
Packit 6c4009
     /* This function is used to compute the TP offset for symbols in
Packit 6c4009
	Static TLS, i.e., whose TP offset is the same for all
Packit 6c4009
	threads.
Packit 6c4009
Packit 6c4009
	The incoming %eax points to the TLS descriptor, such that
Packit 6c4009
	0(%eax) points to _dl_tlsdesc_return itself, and 4(%eax) holds
Packit 6c4009
	the TP offset of the symbol corresponding to the object
Packit 6c4009
	denoted by the argument.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_return
Packit 6c4009
	.global	_dl_tlsdesc_return
Packit 6c4009
	.type	_dl_tlsdesc_return,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_return:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	movl	4(%eax), %eax
Packit 6c4009
	ret
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_return, .-_dl_tlsdesc_return
Packit 6c4009
Packit 6c4009
     /* This function is used for undefined weak TLS symbols, for
Packit 6c4009
	which the base address (i.e., disregarding any addend) should
Packit 6c4009
	resolve to NULL.
Packit 6c4009
Packit 6c4009
	%eax points to the TLS descriptor, such that 0(%eax) points to
Packit 6c4009
	_dl_tlsdesc_undefweak itself, and 4(%eax) holds the addend.
Packit 6c4009
	We return the addend minus the TP, such that, when the caller
Packit 6c4009
	adds TP, it gets the addend back.  If that's zero, as usual,
Packit 6c4009
	that's most likely a NULL pointer.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_undefweak
Packit 6c4009
	.global	_dl_tlsdesc_undefweak
Packit 6c4009
	.type	_dl_tlsdesc_undefweak,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_undefweak:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	movl	4(%eax), %eax
Packit 6c4009
	subl	%gs:0, %eax
Packit 6c4009
	ret
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
Packit 6c4009
Packit 6c4009
#ifdef SHARED
Packit 6c4009
	.hidden _dl_tlsdesc_dynamic
Packit 6c4009
	.global	_dl_tlsdesc_dynamic
Packit 6c4009
	.type	_dl_tlsdesc_dynamic,@function
Packit 6c4009
Packit 6c4009
     /* This function is used for symbols that need dynamic TLS.
Packit 6c4009
Packit 6c4009
	%eax points to the TLS descriptor, such that 0(%eax) points to
Packit 6c4009
	_dl_tlsdesc_dynamic itself, and 4(%eax) points to a struct
Packit 6c4009
	tlsdesc_dynamic_arg object.  It must return in %eax the offset
Packit 6c4009
	between the thread pointer and the object denoted by the
Packit 6c4009
	argument, without clobbering any registers.
Packit 6c4009
Packit 6c4009
	The assembly code that follows is a rendition of the following
Packit 6c4009
	C code, hand-optimized a little bit.
Packit 6c4009
Packit 6c4009
ptrdiff_t
Packit 6c4009
__attribute__ ((__regparm__ (1)))
Packit 6c4009
_dl_tlsdesc_dynamic (struct tlsdesc *tdp)
Packit 6c4009
{
Packit 6c4009
  struct tlsdesc_dynamic_arg *td = tdp->arg;
Packit 6c4009
  dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
Packit 6c4009
  if (__builtin_expect (td->gen_count <= dtv[0].counter
Packit 6c4009
			&& (dtv[td->tlsinfo.ti_module].pointer.val
Packit 6c4009
			    != TLS_DTV_UNALLOCATED),
Packit 6c4009
			1))
Packit 6c4009
    return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
Packit 6c4009
      - __thread_pointer;
Packit 6c4009
Packit 6c4009
  return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
Packit 6c4009
}
Packit 6c4009
*/
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_dynamic:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	/* Like all TLS resolvers, preserve call-clobbered registers.
Packit 6c4009
	   We need two scratch regs anyway.  */
Packit 6c4009
	subl	$28, %esp
Packit 6c4009
	cfi_adjust_cfa_offset (28)
Packit 6c4009
	movl	%ecx, 20(%esp)
Packit 6c4009
	movl	%edx, 24(%esp)
Packit 6c4009
	movl	TLSDESC_ARG(%eax), %eax
Packit 6c4009
	movl	%gs:DTV_OFFSET, %edx
Packit 6c4009
	movl	TLSDESC_GEN_COUNT(%eax), %ecx
Packit 6c4009
	cmpl	(%edx), %ecx
Packit 6c4009
	ja	.Lslow
Packit 6c4009
	movl	TLSDESC_MODID(%eax), %ecx
Packit 6c4009
	movl	(%edx,%ecx,8), %edx
Packit 6c4009
	cmpl	$-1, %edx
Packit 6c4009
	je	.Lslow
Packit 6c4009
	movl	TLSDESC_MODOFF(%eax), %eax
Packit 6c4009
	addl	%edx, %eax
Packit 6c4009
.Lret:
Packit 6c4009
	movl	20(%esp), %ecx
Packit 6c4009
	subl	%gs:0, %eax
Packit 6c4009
	movl	24(%esp), %edx
Packit 6c4009
	addl	$28, %esp
Packit 6c4009
	cfi_adjust_cfa_offset (-28)
Packit 6c4009
	ret
Packit 6c4009
	.p2align 4,,7
Packit 6c4009
.Lslow:
Packit 6c4009
	cfi_adjust_cfa_offset (28)
Packit 6c4009
#ifdef NO_RTLD_HIDDEN
Packit 6c4009
	call	JUMPTARGET (___tls_get_addr)
Packit 6c4009
#else
Packit 6c4009
	call	HIDDEN_JUMPTARGET (___tls_get_addr)
Packit 6c4009
#endif
Packit 6c4009
	jmp	.Lret
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
Packit 6c4009
#endif /* SHARED */
Packit 6c4009
Packit 6c4009
     /* This function is a wrapper for a lazy resolver for TLS_DESC
Packit 6c4009
	REL relocations that reference the *ABS* segment in their own
Packit 6c4009
	link maps.  %ebx points to the caller's GOT.  %eax points to a
Packit 6c4009
	TLS descriptor, such that 0(%eax) holds the address of the
Packit 6c4009
	resolver wrapper itself (unless some other thread beat us to
Packit 6c4009
	it) and 4(%eax) holds the addend in the relocation.
Packit 6c4009
Packit 6c4009
	When the actual resolver returns, it will have adjusted the
Packit 6c4009
	TLS descriptor such that we can tail-call it for it to return
Packit 6c4009
	the TP offset of the symbol.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_resolve_abs_plus_addend
Packit 6c4009
	.global	_dl_tlsdesc_resolve_abs_plus_addend
Packit 6c4009
	.type	_dl_tlsdesc_resolve_abs_plus_addend,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_resolve_abs_plus_addend:
Packit 6c4009
0:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	pushl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	movl	$1f - 0b, %ecx
Packit 6c4009
	movl	4(%ebx), %edx
Packit 6c4009
	call	_dl_tlsdesc_resolve_abs_plus_addend_fixup
Packit 6c4009
1:
Packit 6c4009
	popl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	jmp	*(%eax)
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_resolve_abs_plus_addend, .-_dl_tlsdesc_resolve_abs_plus_addend
Packit 6c4009
Packit 6c4009
     /* This function is a wrapper for a lazy resolver for TLS_DESC
Packit 6c4009
	REL relocations that had zero addends.  %ebx points to the
Packit 6c4009
	caller's GOT.  %eax points to a TLS descriptor, such that
Packit 6c4009
	0(%eax) holds the address of the resolver wrapper itself
Packit 6c4009
	(unless some other thread beat us to it) and 4(%eax) holds a
Packit 6c4009
	pointer to the relocation.
Packit 6c4009
Packit 6c4009
	When the actual resolver returns, it will have adjusted the
Packit 6c4009
	TLS descriptor such that we can tail-call it for it to return
Packit 6c4009
	the TP offset of the symbol.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_resolve_rel
Packit 6c4009
	.global	_dl_tlsdesc_resolve_rel
Packit 6c4009
	.type	_dl_tlsdesc_resolve_rel,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_resolve_rel:
Packit 6c4009
0:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	pushl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	movl	$1f - 0b, %ecx
Packit 6c4009
	movl	4(%ebx), %edx
Packit 6c4009
	call	_dl_tlsdesc_resolve_rel_fixup
Packit 6c4009
1:
Packit 6c4009
	popl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	jmp	*(%eax)
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_resolve_rel, .-_dl_tlsdesc_resolve_rel
Packit 6c4009
Packit 6c4009
     /* This function is a wrapper for a lazy resolver for TLS_DESC
Packit 6c4009
	RELA relocations.  %ebx points to the caller's GOT.  %eax
Packit 6c4009
	points to a TLS descriptor, such that 0(%eax) holds the
Packit 6c4009
	address of the resolver wrapper itself (unless some other
Packit 6c4009
	thread beat us to it) and 4(%eax) holds a pointer to the
Packit 6c4009
	relocation.
Packit 6c4009
Packit 6c4009
	When the actual resolver returns, it will have adjusted the
Packit 6c4009
	TLS descriptor such that we can tail-call it for it to return
Packit 6c4009
	the TP offset of the symbol.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_resolve_rela
Packit 6c4009
	.global	_dl_tlsdesc_resolve_rela
Packit 6c4009
	.type	_dl_tlsdesc_resolve_rela,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_resolve_rela:
Packit 6c4009
0:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	pushl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	movl	$1f - 0b, %ecx
Packit 6c4009
	movl	4(%ebx), %edx
Packit 6c4009
	call	_dl_tlsdesc_resolve_rela_fixup
Packit 6c4009
1:
Packit 6c4009
	popl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	jmp	*(%eax)
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela
Packit 6c4009
Packit 6c4009
     /* This function is a placeholder for lazy resolving of TLS
Packit 6c4009
	relocations.  Once some thread starts resolving a TLS
Packit 6c4009
	relocation, it sets up the TLS descriptor to use this
Packit 6c4009
	resolver, such that other threads that would attempt to
Packit 6c4009
	resolve it concurrently may skip the call to the original lazy
Packit 6c4009
	resolver and go straight to a condition wait.
Packit 6c4009
Packit 6c4009
	When the actual resolver returns, it will have adjusted the
Packit 6c4009
	TLS descriptor such that we can tail-call it for it to return
Packit 6c4009
	the TP offset of the symbol.  */
Packit 6c4009
Packit 6c4009
	.hidden _dl_tlsdesc_resolve_hold
Packit 6c4009
	.global	_dl_tlsdesc_resolve_hold
Packit 6c4009
	.type	_dl_tlsdesc_resolve_hold,@function
Packit 6c4009
	cfi_startproc
Packit 6c4009
	.align 16
Packit 6c4009
_dl_tlsdesc_resolve_hold:
Packit 6c4009
0:
Packit 6c4009
	_CET_ENDBR
Packit 6c4009
	pushl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	pushl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (4)
Packit 6c4009
	movl	$1f - 0b, %ecx
Packit 6c4009
	movl	4(%ebx), %edx
Packit 6c4009
	call	_dl_tlsdesc_resolve_hold_fixup
Packit 6c4009
1:
Packit 6c4009
	popl	%edx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%ecx
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	popl	%eax
Packit 6c4009
	cfi_adjust_cfa_offset (-4)
Packit 6c4009
	jmp	*(%eax)
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	_dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold