Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* Thread-local storage handling in the ELF dynamic linker. x86_64 version. |
---|---|
2 | Copyright (C) 2004-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
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. |
9 | |
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. |
14 | |
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/>. */ |
18 | |
19 | #ifndef SECTION |
20 | # define SECTION(p) p |
21 | #endif |
22 | |
23 | #undef REGISTER_SAVE_AREA |
24 | #undef LOCAL_STORAGE_AREA |
25 | #undef BASE |
26 | |
27 | #include "dl-trampoline-state.h" |
28 | |
29 | .section SECTION(.text),"ax",@progbits |
30 | |
31 | .hidden _dl_tlsdesc_dynamic |
32 | .global _dl_tlsdesc_dynamic |
33 | .type _dl_tlsdesc_dynamic,@function |
34 | |
35 | /* %rax points to the TLS descriptor, such that 0(%rax) points to |
36 | _dl_tlsdesc_dynamic itself, and 8(%rax) points to a struct |
37 | tlsdesc_dynamic_arg object. It must return in %rax the offset |
38 | between the thread pointer and the object denoted by the |
39 | argument, without clobbering any registers. |
40 | |
41 | The assembly code that follows is a rendition of the following |
42 | C code, hand-optimized a little bit. |
43 | |
44 | ptrdiff_t |
45 | _dl_tlsdesc_dynamic (register struct tlsdesc *tdp asm ("%rax")) |
46 | { |
47 | struct tlsdesc_dynamic_arg *td = tdp->arg; |
48 | dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET); |
49 | if (__builtin_expect (td->gen_count <= dtv[0].counter |
50 | && (dtv[td->tlsinfo.ti_module].pointer.val |
51 | != TLS_DTV_UNALLOCATED), |
52 | 1)) |
53 | return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset |
54 | - __thread_pointer; |
55 | |
56 | return __tls_get_addr_internal (&td->tlsinfo) - __thread_pointer; |
57 | } |
58 | */ |
59 | cfi_startproc |
60 | .align 16 |
61 | _dl_tlsdesc_dynamic: |
62 | _CET_ENDBR |
63 | /* Preserve call-clobbered registers that we modify. |
64 | We need two scratch regs anyway. */ |
65 | movq %rsi, -16(%rsp) |
66 | mov %fs:DTV_OFFSET, %RSI_LP |
67 | movq %rdi, -8(%rsp) |
68 | movq TLSDESC_ARG(%rax), %rdi |
69 | movq (%rsi), %rax |
70 | cmpq %rax, TLSDESC_GEN_COUNT(%rdi) |
71 | ja 2f |
72 | movq TLSDESC_MODID(%rdi), %rax |
73 | salq $4, %rax |
74 | movq (%rax,%rsi), %rax |
75 | cmpq $-1, %rax |
76 | je 2f |
77 | addq TLSDESC_MODOFF(%rdi), %rax |
78 | 1: |
79 | movq -16(%rsp), %rsi |
80 | sub %fs:0, %RAX_LP |
81 | movq -8(%rsp), %rdi |
82 | ret |
83 | 2: |
84 | #if DL_RUNTIME_RESOLVE_REALIGN_STACK |
85 | movq %rbx, -24(%rsp) |
86 | mov %RSP_LP, %RBX_LP |
87 | cfi_def_cfa_register(%rbx) |
88 | and $-STATE_SAVE_ALIGNMENT, %RSP_LP |
89 | #endif |
90 | #ifdef REGISTER_SAVE_AREA |
91 | # if DL_RUNTIME_RESOLVE_REALIGN_STACK |
92 | /* STATE_SAVE_OFFSET has space for 8 integer registers. But we |
93 | need space for RCX, RDX, RSI, RDI, R8, R9, R10 and R11, plus |
94 | RBX above. */ |
95 | sub $(REGISTER_SAVE_AREA + STATE_SAVE_ALIGNMENT), %RSP_LP |
96 | # else |
97 | sub $REGISTER_SAVE_AREA, %RSP_LP |
98 | cfi_adjust_cfa_offset(REGISTER_SAVE_AREA) |
99 | # endif |
100 | #else |
101 | /* Allocate stack space of the required size to save the state. */ |
102 | sub _rtld_local_ro+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_FULL_SIZE_OFFSET(%rip), %RSP_LP |
103 | #endif |
104 | /* Besides rdi and rsi, saved above, save rcx, rdx, r8, r9, |
105 | r10 and r11. */ |
106 | movq %rcx, REGISTER_SAVE_RCX(%rsp) |
107 | movq %rdx, REGISTER_SAVE_RDX(%rsp) |
108 | movq %r8, REGISTER_SAVE_R8(%rsp) |
109 | movq %r9, REGISTER_SAVE_R9(%rsp) |
110 | movq %r10, REGISTER_SAVE_R10(%rsp) |
111 | movq %r11, REGISTER_SAVE_R11(%rsp) |
112 | #ifdef USE_FXSAVE |
113 | fxsave STATE_SAVE_OFFSET(%rsp) |
114 | #else |
115 | movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax |
116 | xorl %edx, %edx |
117 | /* Clear the XSAVE Header. */ |
118 | # ifdef USE_XSAVE |
119 | movq %rdx, (STATE_SAVE_OFFSET + 512)(%rsp) |
120 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8)(%rsp) |
121 | # endif |
122 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 2)(%rsp) |
123 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 3)(%rsp) |
124 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 4)(%rsp) |
125 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 5)(%rsp) |
126 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 6)(%rsp) |
127 | movq %rdx, (STATE_SAVE_OFFSET + 512 + 8 * 7)(%rsp) |
128 | # ifdef USE_XSAVE |
129 | xsave STATE_SAVE_OFFSET(%rsp) |
130 | # else |
131 | xsavec STATE_SAVE_OFFSET(%rsp) |
132 | # endif |
133 | #endif |
134 | /* %rdi already points to the tlsinfo data structure. */ |
135 | call HIDDEN_JUMPTARGET (__tls_get_addr) |
136 | # Get register content back. |
137 | #ifdef USE_FXSAVE |
138 | fxrstor STATE_SAVE_OFFSET(%rsp) |
139 | #else |
140 | /* Save and retore __tls_get_addr return value stored in RAX. */ |
141 | mov %RAX_LP, %RCX_LP |
142 | movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax |
143 | xorl %edx, %edx |
144 | xrstor STATE_SAVE_OFFSET(%rsp) |
145 | mov %RCX_LP, %RAX_LP |
146 | #endif |
147 | movq REGISTER_SAVE_R11(%rsp), %r11 |
148 | movq REGISTER_SAVE_R10(%rsp), %r10 |
149 | movq REGISTER_SAVE_R9(%rsp), %r9 |
150 | movq REGISTER_SAVE_R8(%rsp), %r8 |
151 | movq REGISTER_SAVE_RDX(%rsp), %rdx |
152 | movq REGISTER_SAVE_RCX(%rsp), %rcx |
153 | #if DL_RUNTIME_RESOLVE_REALIGN_STACK |
154 | mov %RBX_LP, %RSP_LP |
155 | cfi_def_cfa_register(%rsp) |
156 | movq -24(%rsp), %rbx |
157 | cfi_restore(%rbx) |
158 | #else |
159 | add $REGISTER_SAVE_AREA, %RSP_LP |
160 | cfi_adjust_cfa_offset(-REGISTER_SAVE_AREA) |
161 | #endif |
162 | jmp 1b |
163 | cfi_endproc |
164 | .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic |
165 | |
166 | #undef STATE_SAVE_ALIGNMENT |
167 |
Warning: That file was not part of the compilation database. It may have many parsing errors.