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

source code of glibc/sysdeps/i386/dl-tlsdesc.S