linux: Add FSCONFIG_CMD_CREATE_EXCL from Linux 6.6 to sys/mount.h
[glibc.git] / sysdeps / i386 / dl-tlsdesc.S
blob9522985ee78720981bf08dd09e8f1f58ada3674c
1 /* Thread-local storage handling in the ELF dynamic linker.  i386 version.
2    Copyright (C) 2004-2023 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/>.  */
19 #include <sysdep.h>
20 #include <tls.h>
21 #include "tlsdesc.h"
23         .text
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
27         threads.
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
37         cfi_startproc
38         .align 16
39 _dl_tlsdesc_return:
40         _CET_ENDBR
41         movl    4(%eax), %eax
42         ret
43         cfi_endproc
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
48         resolve to NULL.
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
59         cfi_startproc
60         .align 16
61 _dl_tlsdesc_undefweak:
62         _CET_ENDBR
63         movl    4(%eax), %eax
64         subl    %gs:0, %eax
65         ret
66         cfi_endproc
67         .size   _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
69 #ifdef SHARED
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.
85 ptrdiff_t
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),
94                         1))
95     return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset
96       - __thread_pointer;
98   return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
101         cfi_startproc
102         .align 16
103 _dl_tlsdesc_dynamic:
104         _CET_ENDBR
105         /* Like all TLS resolvers, preserve call-clobbered registers.
106            We need two scratch regs anyway.  */
107         subl    $28, %esp
108         cfi_adjust_cfa_offset (28)
109         movl    %ecx, 20(%esp)
110         movl    %edx, 24(%esp)
111         movl    TLSDESC_ARG(%eax), %eax
112         movl    %gs:DTV_OFFSET, %edx
113         movl    TLSDESC_GEN_COUNT(%eax), %ecx
114         cmpl    (%edx), %ecx
115         ja      .Lslow
116         movl    TLSDESC_MODID(%eax), %ecx
117         movl    (%edx,%ecx,8), %edx
118         cmpl    $-1, %edx
119         je      .Lslow
120         movl    TLSDESC_MODOFF(%eax), %eax
121         addl    %edx, %eax
122 .Lret:
123         movl    20(%esp), %ecx
124         subl    %gs:0, %eax
125         movl    24(%esp), %edx
126         addl    $28, %esp
127         cfi_adjust_cfa_offset (-28)
128         ret
129         .p2align 4,,7
130 .Lslow:
131         cfi_adjust_cfa_offset (28)
132         call    HIDDEN_JUMPTARGET (___tls_get_addr)
133         jmp     .Lret
134         cfi_endproc
135         .size   _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
136 #endif /* SHARED */