1 | /* PLT trampolines. ARM version. |
2 | Copyright (C) 2005-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 | /* ??? Needs more rearrangement for the LDM to handle thumb mode. */ |
20 | #define NO_THUMB |
21 | #include <sysdep.h> |
22 | #include <libc-symbols.h> |
23 | |
24 | .text |
25 | .globl _dl_runtime_resolve |
26 | .type _dl_runtime_resolve, #function |
27 | CFI_SECTIONS |
28 | cfi_startproc |
29 | .align 2 |
30 | _dl_runtime_resolve: |
31 | cfi_adjust_cfa_offset (4) |
32 | cfi_rel_offset (lr, 0) |
33 | |
34 | @ we get called with |
35 | @ stack[0] contains the return address from this call |
36 | @ ip contains &GOT[n+3] (pointer to function) |
37 | @ lr points to &GOT[2] |
38 | |
39 | @ Save arguments. We save r4 to realign the stack. |
40 | push {r0-r4} |
41 | cfi_adjust_cfa_offset (20) |
42 | cfi_rel_offset (r0, 0) |
43 | cfi_rel_offset (r1, 4) |
44 | cfi_rel_offset (r2, 8) |
45 | cfi_rel_offset (r3, 12) |
46 | |
47 | @ get pointer to linker struct |
48 | ldr r0, [lr, #-4] |
49 | |
50 | @ prepare to call _dl_fixup() |
51 | @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each |
52 | sub r1, ip, lr |
53 | sub r1, r1, #4 |
54 | add r1, r1, r1 |
55 | |
56 | @ call fixup routine |
57 | bl _dl_fixup |
58 | |
59 | @ save the return |
60 | mov ip, r0 |
61 | |
62 | @ get arguments and return address back. We restore r4 |
63 | @ only to realign the stack. |
64 | pop {r0-r4,lr} |
65 | cfi_adjust_cfa_offset (-24) |
66 | |
67 | @ jump to the newly found address |
68 | BX(ip) |
69 | |
70 | cfi_endproc |
71 | .size _dl_runtime_resolve, .-_dl_runtime_resolve |
72 | |
73 | #ifndef PROF |
74 | .globl _dl_runtime_profile |
75 | .type _dl_runtime_profile, #function |
76 | CFI_SECTIONS |
77 | cfi_startproc |
78 | .align 2 |
79 | _dl_runtime_profile: |
80 | cfi_adjust_cfa_offset (4) |
81 | cfi_rel_offset (lr, 0) |
82 | |
83 | @ we get called with |
84 | @ stack[0] contains the return address from this call |
85 | @ ip contains &GOT[n+3] (pointer to function) |
86 | @ lr points to &GOT[2] |
87 | |
88 | @ Stack layout: |
89 | @ 212 - saved lr |
90 | @ 208 - framesize returned from pltenter |
91 | @ 16 - La_arm_regs |
92 | @ 8 - Saved two arguments to _dl_profile_fixup |
93 | @ 4 - Saved result of _dl_profile_fixup |
94 | @ 0 - outgoing argument to _dl_profile_fixup |
95 | @ For now, we only save the general purpose registers. |
96 | |
97 | sub sp, sp, #196 |
98 | cfi_adjust_cfa_offset (196) |
99 | stmia sp, {r0-r3} |
100 | cfi_rel_offset (r0, 0) |
101 | cfi_rel_offset (r1, 4) |
102 | cfi_rel_offset (r2, 8) |
103 | cfi_rel_offset (r3, 12) |
104 | |
105 | sub sp, sp, #16 |
106 | cfi_adjust_cfa_offset (16) |
107 | |
108 | @ Save sp and lr. |
109 | add r0, sp, #216 |
110 | str r0, [sp, #32] |
111 | ldr r2, [sp, #212] |
112 | str r2, [sp, #36] |
113 | |
114 | @ get pointer to linker struct |
115 | ldr r0, [lr, #-4] |
116 | |
117 | @ prepare to call _dl_profile_fixup() |
118 | @ change &GOT[n+3] into 8*n NOTE: reloc are 8 bytes each |
119 | sub r1, ip, lr |
120 | sub r1, r1, #4 |
121 | add r1, r1, r1 |
122 | |
123 | @ Save these two arguments for pltexit. |
124 | add r3, sp, #8 |
125 | stmia r3!, {r0,r1} |
126 | |
127 | @ Set up extra args for _dl_profile_fixup. |
128 | @ r2 and r3 are already loaded. |
129 | add ip, sp, #208 |
130 | str ip, [sp, #0] |
131 | |
132 | @ call profiling fixup routine |
133 | bl _dl_profile_fixup |
134 | |
135 | @ The address to call is now in r0. |
136 | |
137 | @ Check whether we're wrapping this function. |
138 | ldr ip, [sp, #208] |
139 | cmp ip, #0 |
140 | bge 1f |
141 | cfi_remember_state |
142 | |
143 | @ save the return |
144 | mov ip, r0 |
145 | |
146 | @ get arguments and return address back |
147 | add sp, sp, #16 |
148 | cfi_adjust_cfa_offset (-16) |
149 | ldmia sp, {r0-r3,sp,lr} |
150 | cfi_adjust_cfa_offset (-200) |
151 | |
152 | @ jump to the newly found address |
153 | BX(ip) |
154 | |
155 | cfi_restore_state |
156 | 1: |
157 | @ The new frame size is in ip. |
158 | |
159 | @ New stack layout: |
160 | @ 268 - saved r7 |
161 | @ 264 - saved result of _dl_profile_fixup |
162 | @ 72 - La_arm_regs |
163 | @ 64 - Saved two arguments to _dl_profile_fixup |
164 | @ 0 - La_arm_retval |
165 | @ For now, we only save the general purpose registers. |
166 | |
167 | @ Build the new frame. |
168 | str r7, [sp, #212] |
169 | cfi_rel_offset (r7, 212) |
170 | sub r7, sp, #56 |
171 | cfi_def_cfa_register (r7) |
172 | cfi_adjust_cfa_offset (56) |
173 | sub sp, sp, ip |
174 | bic sp, sp, #7 |
175 | |
176 | @ Save the _dl_profile_fixup result around the call to memcpy. |
177 | str r0, [r7, #264] |
178 | |
179 | @ Copy the stack arguments. |
180 | mov r0, sp |
181 | add r1, r7, #272 |
182 | mov r2, ip |
183 | bl memcpy |
184 | |
185 | @ Call the function. |
186 | add ip, r7, #72 |
187 | ldmia ip, {r0-r3} |
188 | ldr ip, [r7, #264] |
189 | BLX(ip) |
190 | stmia r7, {r0-r3} |
191 | |
192 | @ Call pltexit. |
193 | add ip, r7, #64 |
194 | ldmia ip, {r0,r1} |
195 | add r2, r7, #72 |
196 | add r3, r7, #0 |
197 | bl _dl_audit_pltexit |
198 | |
199 | @ Return to caller. |
200 | ldmia r7, {r0-r3} |
201 | mov sp, r7 |
202 | cfi_def_cfa_register (sp) |
203 | ldr r7, [sp, #268] |
204 | ldr lr, [sp, #92] |
205 | add sp, sp, #272 |
206 | cfi_adjust_cfa_offset (-272) |
207 | BX(lr) |
208 | |
209 | cfi_endproc |
210 | .size _dl_runtime_profile, .-_dl_runtime_profile |
211 | #endif |
212 | .previous |
213 | |