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 | #include <sysdep.h> |
20 | #include <tls.h> |
21 | #include <cpu-features-offsets.h> |
22 | #include <features-offsets.h> |
23 | #include <isa-level.h> |
24 | #include "tlsdesc.h" |
25 | #include "dl-trampoline-save.h" |
26 | |
27 | /* Area on stack to save and restore registers used for parameter |
28 | passing when calling _dl_tlsdesc_dynamic. */ |
29 | #define REGISTER_SAVE_RCX 0 |
30 | #define REGISTER_SAVE_RDX (REGISTER_SAVE_RCX + 8) |
31 | #define REGISTER_SAVE_R8 (REGISTER_SAVE_RDX + 8) |
32 | #define REGISTER_SAVE_R9 (REGISTER_SAVE_R8 + 8) |
33 | #define REGISTER_SAVE_R10 (REGISTER_SAVE_R9 + 8) |
34 | #define REGISTER_SAVE_R11 (REGISTER_SAVE_R10 + 8) |
35 | |
36 | .text |
37 | |
38 | /* This function is used to compute the TP offset for symbols in |
39 | Static TLS, i.e., whose TP offset is the same for all |
40 | threads. |
41 | |
42 | The incoming %rax points to the TLS descriptor, such that |
43 | 0(%rax) points to _dl_tlsdesc_return itself, and 8(%rax) holds |
44 | the TP offset of the symbol corresponding to the object |
45 | denoted by the argument. */ |
46 | |
47 | .hidden _dl_tlsdesc_return |
48 | .global _dl_tlsdesc_return |
49 | .type _dl_tlsdesc_return,@function |
50 | cfi_startproc |
51 | .align 16 |
52 | _dl_tlsdesc_return: |
53 | _CET_ENDBR |
54 | movq 8(%rax), %rax |
55 | ret |
56 | cfi_endproc |
57 | .size _dl_tlsdesc_return, .-_dl_tlsdesc_return |
58 | |
59 | /* This function is used for undefined weak TLS symbols, for |
60 | which the base address (i.e., disregarding any addend) should |
61 | resolve to NULL. |
62 | |
63 | %rax points to the TLS descriptor, such that 0(%rax) points to |
64 | _dl_tlsdesc_undefweak itself, and 8(%rax) holds the addend. |
65 | We return the addend minus the TP, such that, when the caller |
66 | adds TP, it gets the addend back. If that's zero, as usual, |
67 | that's most likely a NULL pointer. */ |
68 | |
69 | .hidden _dl_tlsdesc_undefweak |
70 | .global _dl_tlsdesc_undefweak |
71 | .type _dl_tlsdesc_undefweak,@function |
72 | cfi_startproc |
73 | .align 16 |
74 | _dl_tlsdesc_undefweak: |
75 | _CET_ENDBR |
76 | movq 8(%rax), %rax |
77 | sub %fs:0, %RAX_LP |
78 | ret |
79 | cfi_endproc |
80 | .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak |
81 | |
82 | #ifdef SHARED |
83 | # if MINIMUM_X86_ISA_LEVEL < AVX_X86_ISA_LEVEL |
84 | # define USE_FXSAVE |
85 | # define STATE_SAVE_ALIGNMENT 16 |
86 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fxsave |
87 | # include "dl-tlsdesc-dynamic.h" |
88 | # undef _dl_tlsdesc_dynamic |
89 | # undef USE_FXSAVE |
90 | # endif |
91 | |
92 | # define USE_XSAVE |
93 | # define STATE_SAVE_ALIGNMENT 64 |
94 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsave |
95 | # include "dl-tlsdesc-dynamic.h" |
96 | # undef _dl_tlsdesc_dynamic |
97 | # undef USE_XSAVE |
98 | |
99 | # define USE_XSAVEC |
100 | # define STATE_SAVE_ALIGNMENT 64 |
101 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsavec |
102 | # include "dl-tlsdesc-dynamic.h" |
103 | # undef _dl_tlsdesc_dynamic |
104 | # undef USE_XSAVEC |
105 | #endif /* SHARED */ |
106 | |