1 /* Thread-local storage handling in the ELF dynamic linker. i386 version.
2 Copyright (C) 2004-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
25 /* This function is used to compute the TP offset for symbols in
26 Static TLS, i.e., whose TP offset is the same for all
29 The incoming %eax points to the TLS descriptor, such that
30 0(%eax) points to _dl_tlsdesc_return itself, and 4(%eax) holds
31 the TP offset of the symbol corresponding to the object
32 denoted by the argument. */
34 .hidden _dl_tlsdesc_return
35 .global _dl_tlsdesc_return
36 .type _dl_tlsdesc_return,@function
44 .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
46 /* This function is used for undefined weak TLS symbols, for
47 which the base address (i.e., disregarding any addend) should
50 %eax points to the TLS descriptor, such that 0(%eax) points to
51 _dl_tlsdesc_undefweak itself, and 4(%eax) holds the addend.
52 We return the addend minus the TP, such that, when the caller
53 adds TP, it gets the addend back. If that's zero, as usual,
54 that's most likely a NULL pointer. */
56 .hidden _dl_tlsdesc_undefweak
57 .global _dl_tlsdesc_undefweak
58 .type _dl_tlsdesc_undefweak,@function
61 _dl_tlsdesc_undefweak:
67 .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
70 .hidden _dl_tlsdesc_dynamic
71 .global _dl_tlsdesc_dynamic
72 .type _dl_tlsdesc_dynamic,@function
74 /* This function is used for symbols that need dynamic TLS.
76 %eax points to the TLS descriptor, such that 0(%eax) points to
77 _dl_tlsdesc_dynamic itself, and 4(%eax) points to a struct
78 tlsdesc_dynamic_arg object. It must return in %eax the offset
79 between the thread pointer and the object denoted by the
80 argument, without clobbering any registers.
82 The assembly code that follows is a rendition of the following
83 C code, hand-optimized a little bit.
86 __attribute__ ((__regparm__ (1)))
87 _dl_tlsdesc_dynamic (struct tlsdesc *tdp)
89 struct tlsdesc_dynamic_arg *td = tdp->arg;
90 dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
91 if (__builtin_expect (td->gen_count <= dtv[0].counter
92 && (dtv[td->tlsinfo.ti_module].pointer.val
93 != TLS_DTV_UNALLOCATED),
95 return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
98 return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
105 /* Like all TLS resolvers, preserve call-clobbered registers.
106 We need two scratch regs anyway. */
108 cfi_adjust_cfa_offset (28)
111 movl TLSDESC_ARG(%eax), %eax
112 movl %gs:DTV_OFFSET, %edx
113 movl TLSDESC_GEN_COUNT(%eax), %ecx
116 movl TLSDESC_MODID(%eax), %ecx
117 movl (%edx,%ecx,8), %edx
120 movl TLSDESC_MODOFF(%eax), %eax
127 cfi_adjust_cfa_offset (-28)
131 cfi_adjust_cfa_offset (28)
132 call HIDDEN_JUMPTARGET (___tls_get_addr)
135 .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic