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