1/* Thread-local storage handling in the ELF dynamic linker. ARM version.
2 Copyright (C) 2006-2022 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 <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 ldr r0, [r0]
36 BX (lr)
37 eabi_fnend
38 cfi_endproc
39 .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
40
41 .hidden _dl_tlsdesc_undefweak
42 .global _dl_tlsdesc_undefweak
43 .type _dl_tlsdesc_undefweak,#function
44 cfi_startproc
45 eabi_fnstart
46 .align 2
47_dl_tlsdesc_undefweak:
48 GET_TLS (r1)
49 rsb r0, r0, #0
50 BX (lr)
51 cfi_endproc
52 eabi_fnend
53 .size _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
54
55#ifdef SHARED
56 .hidden _dl_tlsdesc_dynamic
57 .global _dl_tlsdesc_dynamic
58 .type _dl_tlsdesc_dynamic,#function
59
60
61/*
62 The assembly code that follows is a rendition of the following
63 C code, hand-optimized a little bit.
64
65ptrdiff_t
66_dl_tlsdesc_dynamic(struct tlsdesc *tdp)
67{
68 struct tlsdesc_dynamic_arg *td = tdp->argument.pointer;
69 dtv_t *dtv = (dtv_t *)THREAD_DTV();
70 if (__builtin_expect (td->gen_count <= dtv[0].counter
71 && dtv[td->tlsinfo.ti_module].pointer.val
72 != TLS_DTV_UNALLOCATED,
73 1))
74 return dtv[td->tlsinfo.ti_module].pointer.val +
75 td->tlsinfo.ti_offset - __builtin_thread_pointer();
76
77 return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
78}
79
80*/
81 cfi_startproc
82 eabi_fnstart
83 .align 2
84_dl_tlsdesc_dynamic:
85 /* Our calling convention is to clobber r0, r1 and the processor
86 flags. All others that are modified must be saved */
87 eabi_save ({r2,r3,r4,lr})
88 push {r2,r3,r4,lr}
89 cfi_adjust_cfa_offset (16)
90 cfi_rel_offset (r2,0)
91 cfi_rel_offset (r3,4)
92 cfi_rel_offset (r4,8)
93 cfi_rel_offset (lr,12)
94 ldr r1, [r0] /* td */
95 GET_TLS (lr)
96 mov r4, r0 /* r4 = tp */
97 ldr r0, [r0]
98 ldr r2, [r1, #8] /* gen_count */
99 ldr r3, [r0]
100 cmp r2, r3
101 bhi 1f
102 ldr r3, [r1]
103#ifndef ARM_NO_INDEX_REGISTER
104 ldr r2, [r0, r3, lsl #3]
105#else
106 add lr, r0, r3, lsl #3
107 ldr r2, [lr]
108#endif
109 cmn r2, #1
110 ittt ne
111 ldrne r3, [r1, #4]
112 addne r3, r2, r3
113 rsbne r0, r4, r3
114 bne 2f
1151: mov r0, r1
116 bl __tls_get_addr
117 rsb r0, r4, r0
1182:
119#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
120 || defined (ARM_ALWAYS_BX))
121 pop {r2,r3,r4, lr}
122 cfi_adjust_cfa_offset (-16)
123 cfi_restore (lr)
124 cfi_restore (r4)
125 cfi_restore (r3)
126 cfi_restore (r2)
127 bx lr
128#else
129 pop {r2,r3,r4, pc}
130#endif
131 eabi_fnend
132 cfi_endproc
133 .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
134#endif /* SHARED */
135

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