Blame sysdeps/s390/dl-tls.h

Packit Service 82fcde
/* Thread-local storage handling in the ELF dynamic linker.  s390 version.
Packit Service 82fcde
   Copyright (C) 2003-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Type used for the representation of TLS information in the GOT.  */
Packit Service 82fcde
typedef struct
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned long int ti_module;
Packit Service 82fcde
  unsigned long int ti_offset;
Packit Service 82fcde
} tls_index;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#ifdef SHARED
Packit Service 82fcde
Packit Service 82fcde
extern unsigned long __tls_get_offset (unsigned long got_offset);
Packit Service 82fcde
Packit Service 82fcde
# if IS_IN (rtld)
Packit Service 82fcde
Packit Service 82fcde
#  include <shlib-compat.h>
Packit Service 82fcde
Packit Service 82fcde
/* dl-tls.c declares __tls_get_addr as an exported symbol if it is not defined
Packit Service 82fcde
   as a macro.  It seems suitable to do that in the generic code because all
Packit Service 82fcde
   architectures other than s390 export __tls_get_addr.  The declaration causes
Packit Service 82fcde
   problems in s390 though, so we define __tls_get_addr here to avoid declaring
Packit Service 82fcde
   __tls_get_addr again.  */
Packit Service 82fcde
#  define __tls_get_addr __tls_get_addr
Packit Service 82fcde
Packit Service 82fcde
extern void *__tls_get_addr (tls_index *ti) attribute_hidden;
Packit Service 82fcde
/* Make a temporary alias of __tls_get_addr to remove the hidden
Packit Service 82fcde
   attribute.  Then export __tls_get_addr as __tls_get_addr_internal
Packit Service 82fcde
   for use from libc.  We do not want to export __tls_get_addr, but we
Packit Service 82fcde
   do need to use it from libc when looking up the address of a TLS
Packit Service 82fcde
   variable. We don't use __tls_get_offset because it requires r12 to
Packit Service 82fcde
   be setup and that might not always be true. Either way it's more
Packit Service 82fcde
   optimal to use __tls_get_addr directly (that's what
Packit Service 82fcde
   __tls_get_offset does anyways).  */
Packit Service 82fcde
strong_alias (__tls_get_addr, __tls_get_addr_internal_tmp);
Packit Service 82fcde
versioned_symbol (ld, __tls_get_addr_internal_tmp,
Packit Service 82fcde
		  __tls_get_addr_internal, GLIBC_PRIVATE);
Packit Service 82fcde
Packit Service 82fcde
/* The special thing about the s390 TLS ABI is that we do not have the
Packit Service 82fcde
   standard __tls_get_addr function but the __tls_get_offset function
Packit Service 82fcde
   which differs in two important aspects:
Packit Service 82fcde
   1) __tls_get_offset gets a got offset instead of a pointer to the
Packit Service 82fcde
      tls_index structure
Packit Service 82fcde
   2) __tls_get_offset returns the offset of the requested variable to
Packit Service 82fcde
      the thread descriptor instead of a pointer to the variable.
Packit Service 82fcde
 */
Packit Service 82fcde
#  ifdef __s390x__
Packit Service 82fcde
__asm__("\n\
Packit Service 82fcde
	.text\n\
Packit Service 82fcde
	.globl __tls_get_offset\n\
Packit Service 82fcde
	.type __tls_get_offset, @function\n\
Packit Service 82fcde
	.align 4\n\
Packit Service 82fcde
__tls_get_offset:\n\
Packit Service 82fcde
	la	%r2,0(%r2,%r12)\n\
Packit Service 82fcde
	jg	__tls_get_addr\n\
Packit Service 82fcde
");
Packit Service 82fcde
#  elif defined __s390__
Packit Service 82fcde
__asm__("\n\
Packit Service 82fcde
	.text\n\
Packit Service 82fcde
	.globl __tls_get_offset\n\
Packit Service 82fcde
	.type __tls_get_offset, @function\n\
Packit Service 82fcde
	.align 4\n\
Packit Service 82fcde
__tls_get_offset:\n\
Packit Service 82fcde
	basr	%r3,0\n\
Packit Service 82fcde
0:	la	%r2,0(%r2,%r12)\n\
Packit Service 82fcde
	l	%r4,1f-0b(%r3)\n\
Packit Service 82fcde
	b	0(%r4,%r3)\n\
Packit Service 82fcde
1:	.long	__tls_get_addr - 0b\n\
Packit Service 82fcde
");
Packit Service 82fcde
#  endif
Packit Service 82fcde
# else /* IS_IN (rtld) */
Packit Service 82fcde
extern void *__tls_get_addr_internal (tls_index *ti);
Packit Service 82fcde
# endif /* !IS_IN (rtld) */
Packit Service 82fcde
Packit Service 82fcde
# define GET_ADDR_OFFSET \
Packit Service 82fcde
  (ti->ti_offset - (unsigned long) __builtin_thread_pointer ())
Packit Service 82fcde
Packit Service 82fcde
/* Use the privately exported __tls_get_addr_internal instead of
Packit Service 82fcde
   __tls_get_offset in order to avoid the __tls_get_offset special
Packit Service 82fcde
   linkage requiring the GOT pointer to be set up in r12.  The
Packit Service 82fcde
   compiler will take care of setting up r12 only if itself issued the
Packit Service 82fcde
   __tls_get_offset call.  */
Packit Service 82fcde
# define __TLS_GET_ADDR(__ti)					\
Packit Service 82fcde
  ({ __tls_get_addr_internal (__ti)				\
Packit Service 82fcde
      + (unsigned long) __builtin_thread_pointer (); })
Packit Service 82fcde
Packit Service 82fcde
#endif