blob: 0429b0106c38c24a6b8dfb98c2f7afd0e6205554 [file] [log] [blame]
xf.libdd93d52023-05-12 07:10:14 -07001/* Thread-local storage handling in the ELF dynamic linker. ARM version.
2 Copyright (C) 2006-2016 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 <http://www.gnu.org/licenses/>. */
18
19#include <sysdep.h>
20#include <arm-features.h>
21#include <tls.h>
22#include "tlsdesc.h"
23
24 .text
25 @ emit debug information with cfi
26 @ use arm-specific pseudos for unwinding itself
27 CFI_SECTIONS
28 .hidden _dl_tlsdesc_return
29 .global _dl_tlsdesc_return
30 .type _dl_tlsdesc_return,#function
31 cfi_startproc
32 eabi_fnstart
33 .align 2
34_dl_tlsdesc_return:
35 sfi_breg r0, \
36 ldr r0, [\B]
37 BX (lr)
38 eabi_fnend
39 cfi_endproc
40 .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
41
42 .hidden _dl_tlsdesc_undefweak
43 .global _dl_tlsdesc_undefweak
44 .type _dl_tlsdesc_undefweak,#function
45 cfi_startproc
46 eabi_fnstart
47 .align 2
48_dl_tlsdesc_undefweak:
49 GET_TLS (r1)
50 rsb r0, r0, #0
51 BX (lr)
52 cfi_endproc
53 eabi_fnend
54 .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
55
56#ifdef SHARED
57 .hidden _dl_tlsdesc_dynamic
58 .global _dl_tlsdesc_dynamic
59 .type _dl_tlsdesc_dynamic,#function
60
61
62/*
63 The assembly code that follows is a rendition of the following
64 C code, hand-optimized a little bit.
65
66ptrdiff_t
67_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
68{
69 struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
70 dtv_t *dtv = (dtv_t *)THREAD_DTV();
71 if (__builtin_expect (td->gen_count <= dtv[0].counter
72 && dtv[td->tlsinfo.ti_module].pointer.val
73 != TLS_DTV_UNALLOCATED,
74 1))
75 return dtv[td->tlsinfo.ti_module].pointer.val +
76 td->tlsinfo.ti_offset - __builtin_thread_pointer();
77
78 return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
79}
80
81*/
82 cfi_startproc
83 eabi_fnstart
84 .align 2
85_dl_tlsdesc_dynamic:
86 /* Our calling convention is to clobber r0, r1 and the processor
87 flags. All others that are modified must be saved */
88 eabi_save ({r2,r3,r4,lr})
89 push {r2,r3,r4,lr}
90 cfi_adjust_cfa_offset (16)
91 cfi_rel_offset (r2,0)
92 cfi_rel_offset (r3,4)
93 cfi_rel_offset (r4,8)
94 cfi_rel_offset (lr,12)
95 sfi_breg r0, \
96 ldr r1, [\B] /* td */
97 GET_TLS (lr)
98 mov r4, r0 /* r4 = tp */
99 sfi_breg r0, \
100 ldr r0, [\B]
101 sfi_breg r1, \
102 ldr r2, [\B, #8] /* gen_count */
103 sfi_breg r0, \
104 ldr r3, [\B]
105 cmp r2, r3
106 bhi 1f
107 sfi_breg r1, \
108 ldr r3, [\B]
109#ifndef ARM_NO_INDEX_REGISTER
110 ldr r2, [r0, r3, lsl #3]
111#else
112 add lr, r0, r3, lsl #3
113 sfi_breg lr, \
114 ldr r2, [\B]
115#endif
116 cmn r2, #1
117 ittt ne
118 sfi_breg r1, \
119 ldrne r3, [r1, #4]
120 addne r3, r2, r3
121 rsbne r0, r4, r3
122 bne 2f
1231: mov r0, r1
124 bl __tls_get_addr
125 rsb r0, r4, r0
1262:
127#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
128 || defined (ARM_ALWAYS_BX))
129 pop {r2,r3,r4, lr}
130 cfi_adjust_cfa_offset (-16)
131 cfi_restore (lr)
132 cfi_restore (r4)
133 cfi_restore (r3)
134 cfi_restore (r2)
135 bx lr
136#else
137 pop {r2,r3,r4, pc}
138#endif
139 eabi_fnend
140 cfi_endproc
141 .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
142#endif /* SHARED */
143
144/* lazy resolved for tls descriptors. */
145 .hidden _dl_tlsdesc_lazy_resolver
146 .global _dl_tlsdesc_lazy_resolver
147 .type _dl_tlsdesc_lazy_resolver,#function
148 cfi_startproc
149 eabi_fnstart
150 .align 2
151_dl_tlsdesc_lazy_resolver:
152 /* r0 points at the tlsdesc,
153 r1 points at the GOT
154 r2 was pushed by the trampoline and used as a temp,
155 we need to pop it here.
156 We push the remaining call-clobbered registers here, and also
157 R1 -- to keep the stack correctly aligned. */
158 /* Tell the unwinder that r2 has already been pushed. */
159 eabi_save ({r2})
160 cfi_adjust_cfa_offset (4)
161 cfi_rel_offset (r2, 0)
162 eabi_save ({r0,r1,r3,ip,lr})
163 push {r0, r1, r3, ip, lr}
164 cfi_adjust_cfa_offset (20)
165 cfi_rel_offset (r0, 0)
166 cfi_rel_offset (r1, 4)
167 cfi_rel_offset (r3, 8)
168 cfi_rel_offset (ip, 12)
169 cfi_rel_offset (lr, 16)
170 bl _dl_tlsdesc_lazy_resolver_fixup
171 pop {r0, r1, r3, ip, lr}
172 cfi_adjust_cfa_offset (-20)
173 cfi_restore (lr)
174 cfi_restore (ip)
175 cfi_restore (r3)
176 cfi_restore (r1)
177 cfi_restore (r0)
178 pop {r2}
179 cfi_adjust_cfa_offset (-4)
180 cfi_restore (r2)
181 sfi_breg r0, \
182 ldr r1, [\B, #4]
183 BX (r1)
184 eabi_fnend
185 cfi_endproc
186 .size _dl_tlsdesc_lazy_resolver, .-_dl_tlsdesc_lazy_resolver
187
188/* Holder for lazy tls descriptors being resolve in another thread.
189
190 Our calling convention is to clobber r0, r1 and the processor
191 flags. All others that are modified must be saved */
192 .hidden _dl_tlsdesc_resolve_hold
193 .global _dl_tlsdesc_resolve_hold
194 .type _dl_tlsdesc_resolve_hold,#function
195 cfi_startproc
196 eabi_fnstart
197 .align 2
198_dl_tlsdesc_resolve_hold:
199 /* r0 is saved so its original value can be used after the call and
200 r1 is saved only to keep the stack aligned. (r0 points to the tls
201 descriptor, it is passed to _dl_tlsdesc_resolve_hold_fixup which
202 is a void function that may clobber r0, later r0 is used to load
203 the new resolver.) */
204 eabi_save ({r0,r1,r2,r3,ip,lr})
205 push {r0, r1, r2, r3, ip, lr}
206 cfi_adjust_cfa_offset (24)
207 cfi_rel_offset (r0, 0)
208 cfi_rel_offset (r1, 4)
209 cfi_rel_offset (r2, 8)
210 cfi_rel_offset (r3, 12)
211 cfi_rel_offset (ip, 16)
212 cfi_rel_offset (lr, 20)
213 adr r1, _dl_tlsdesc_resolve_hold
214 bl _dl_tlsdesc_resolve_hold_fixup
215 pop {r0, r1, r2, r3, ip, lr}
216 cfi_adjust_cfa_offset (-24)
217 cfi_restore (lr)
218 cfi_restore (ip)
219 cfi_restore (r3)
220 cfi_restore (r2)
221 cfi_restore (r1)
222 cfi_restore (r0)
223 sfi_breg r0, \
224 ldr r1, [\B, #4]
225 BX (r1)
226 eabi_fnend
227 cfi_endproc
228 .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold