1 | /* Thread-local storage handling in the ELF dynamic linker. i386 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 "tlsdesc.h" |
24 | |
25 | #ifndef DL_STACK_ALIGNMENT |
26 | /* Due to GCC bug: |
27 | |
28 | https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 |
29 | |
30 | __tls_get_addr may be called with 4-byte stack alignment. Although |
31 | this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume |
32 | that stack will be always aligned at 16 bytes. */ |
33 | # define DL_STACK_ALIGNMENT 4 |
34 | #endif |
35 | |
36 | /* True if _dl_tlsdesc_dynamic should align stack for STATE_SAVE or align |
37 | stack to MINIMUM_ALIGNMENT bytes before calling ___tls_get_addr. */ |
38 | #define DL_RUNTIME_RESOLVE_REALIGN_STACK \ |
39 | (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ |
40 | || MINIMUM_ALIGNMENT > DL_STACK_ALIGNMENT) |
41 | |
42 | .text |
43 | |
44 | /* This function is used to compute the TP offset for symbols in |
45 | Static TLS, i.e., whose TP offset is the same for all |
46 | threads. |
47 | |
48 | The incoming %eax points to the TLS descriptor, such that |
49 | 0(%eax) points to _dl_tlsdesc_return itself, and 4(%eax) holds |
50 | the TP offset of the symbol corresponding to the object |
51 | denoted by the argument. */ |
52 | |
53 | .hidden _dl_tlsdesc_return |
54 | .global _dl_tlsdesc_return |
55 | .type _dl_tlsdesc_return,@function |
56 | cfi_startproc |
57 | .align 16 |
58 | _dl_tlsdesc_return: |
59 | movl 4(%eax), %eax |
60 | ret |
61 | cfi_endproc |
62 | .size _dl_tlsdesc_return, .-_dl_tlsdesc_return |
63 | |
64 | /* This function is used for undefined weak TLS symbols, for |
65 | which the base address (i.e., disregarding any addend) should |
66 | resolve to NULL. |
67 | |
68 | %eax points to the TLS descriptor, such that 0(%eax) points to |
69 | _dl_tlsdesc_undefweak itself, and 4(%eax) holds the addend. |
70 | We return the addend minus the TP, such that, when the caller |
71 | adds TP, it gets the addend back. If that's zero, as usual, |
72 | that's most likely a NULL pointer. */ |
73 | |
74 | .hidden _dl_tlsdesc_undefweak |
75 | .global _dl_tlsdesc_undefweak |
76 | .type _dl_tlsdesc_undefweak,@function |
77 | cfi_startproc |
78 | .align 16 |
79 | _dl_tlsdesc_undefweak: |
80 | movl 4(%eax), %eax |
81 | subl %gs:0, %eax |
82 | ret |
83 | cfi_endproc |
84 | .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak |
85 | |
86 | #ifdef SHARED |
87 | # define USE_FNSAVE |
88 | # define MINIMUM_ALIGNMENT 4 |
89 | # define STATE_SAVE_ALIGNMENT 4 |
90 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fnsave |
91 | # include "dl-tlsdesc-dynamic.h" |
92 | # undef _dl_tlsdesc_dynamic |
93 | # undef MINIMUM_ALIGNMENT |
94 | # undef USE_FNSAVE |
95 | |
96 | # define MINIMUM_ALIGNMENT 16 |
97 | |
98 | # define USE_FXSAVE |
99 | # define STATE_SAVE_ALIGNMENT 16 |
100 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_fxsave |
101 | # include "dl-tlsdesc-dynamic.h" |
102 | # undef _dl_tlsdesc_dynamic |
103 | # undef USE_FXSAVE |
104 | |
105 | # define USE_XSAVE |
106 | # define STATE_SAVE_ALIGNMENT 64 |
107 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsave |
108 | # include "dl-tlsdesc-dynamic.h" |
109 | # undef _dl_tlsdesc_dynamic |
110 | # undef USE_XSAVE |
111 | |
112 | # define USE_XSAVEC |
113 | # define STATE_SAVE_ALIGNMENT 64 |
114 | # define _dl_tlsdesc_dynamic _dl_tlsdesc_dynamic_xsavec |
115 | # include "dl-tlsdesc-dynamic.h" |
116 | # undef _dl_tlsdesc_dynamic |
117 | # undef USE_XSAVEC |
118 | #endif /* SHARED */ |
119 | |