]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 2005-2019 Free Software Foundation, Inc. |
554066b8 MS |
2 | |
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 License as | |
7 | published by the Free Software Foundation; either version 2.1 of the | |
8 | 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 | |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
554066b8 MS |
18 | |
19 | #include <sysdep.h> | |
20 | #include <libc-symbols.h> | |
21 | ||
22 | #include "dl-link.h" | |
23 | ||
24 | #define ip0 x16 | |
389d1f1b | 25 | #define ip0l PTR_REG (16) |
554066b8 MS |
26 | #define ip1 x17 |
27 | #define lr x30 | |
28 | ||
389d1f1b SE |
29 | /* RELA relocatons are 3 pointers */ |
30 | #define RELA_SIZE (PTR_SIZE * 3) | |
31 | ||
554066b8 MS |
32 | .text |
33 | .globl _dl_runtime_resolve | |
34 | .type _dl_runtime_resolve, #function | |
35 | cfi_startproc | |
36 | .align 2 | |
37 | _dl_runtime_resolve: | |
38 | /* AArch64 we get called with: | |
39 | ip0 &PLTGOT[2] | |
40 | ip1 temp(dl resolver entry point) | |
41 | [sp, #8] lr | |
42 | [sp, #0] &PLTGOT[n] | |
43 | */ | |
44 | ||
45 | cfi_rel_offset (lr, 8) | |
46 | ||
47 | /* Save arguments. */ | |
9dbebe1a | 48 | stp x8, x9, [sp, #-(80+8*16)]! |
b513cbf7 | 49 | cfi_adjust_cfa_offset (80+8*16) |
554066b8 MS |
50 | cfi_rel_offset (x8, 0) |
51 | cfi_rel_offset (x9, 8) | |
52 | ||
53 | stp x6, x7, [sp, #16] | |
54 | cfi_rel_offset (x6, 16) | |
55 | cfi_rel_offset (x7, 24) | |
56 | ||
57 | stp x4, x5, [sp, #32] | |
58 | cfi_rel_offset (x4, 32) | |
59 | cfi_rel_offset (x5, 40) | |
60 | ||
61 | stp x2, x3, [sp, #48] | |
62 | cfi_rel_offset (x2, 48) | |
63 | cfi_rel_offset (x3, 56) | |
64 | ||
65 | stp x0, x1, [sp, #64] | |
66 | cfi_rel_offset (x0, 64) | |
67 | cfi_rel_offset (x1, 72) | |
68 | ||
9dbebe1a MS |
69 | stp q0, q1, [sp, #(80+0*16)] |
70 | cfi_rel_offset (q0, 80+0*16) | |
71 | cfi_rel_offset (q1, 80+1*16) | |
72 | ||
73 | stp q2, q3, [sp, #(80+2*16)] | |
74 | cfi_rel_offset (q0, 80+2*16) | |
75 | cfi_rel_offset (q1, 80+3*16) | |
76 | ||
77 | stp q4, q5, [sp, #(80+4*16)] | |
78 | cfi_rel_offset (q0, 80+4*16) | |
79 | cfi_rel_offset (q1, 80+5*16) | |
80 | ||
81 | stp q6, q7, [sp, #(80+6*16)] | |
82 | cfi_rel_offset (q0, 80+6*16) | |
83 | cfi_rel_offset (q1, 80+7*16) | |
84 | ||
554066b8 | 85 | /* Get pointer to linker struct. */ |
389d1f1b | 86 | ldr PTR_REG (0), [ip0, #-PTR_SIZE] |
554066b8 MS |
87 | |
88 | /* Prepare to call _dl_fixup(). */ | |
9dbebe1a | 89 | ldr x1, [sp, 80+8*16] /* Recover &PLTGOT[n] */ |
554066b8 MS |
90 | |
91 | sub x1, x1, ip0 | |
92 | add x1, x1, x1, lsl #1 | |
93 | lsl x1, x1, #3 | |
389d1f1b | 94 | sub x1, x1, #(RELA_SIZE<<3) |
554066b8 MS |
95 | lsr x1, x1, #3 |
96 | ||
97 | /* Call fixup routine. */ | |
98 | bl _dl_fixup | |
99 | ||
100 | /* Save the return. */ | |
101 | mov ip0, x0 | |
102 | ||
103 | /* Get arguments and return address back. */ | |
9dbebe1a MS |
104 | ldp q0, q1, [sp, #(80+0*16)] |
105 | ldp q2, q3, [sp, #(80+2*16)] | |
106 | ldp q4, q5, [sp, #(80+4*16)] | |
107 | ldp q6, q7, [sp, #(80+6*16)] | |
554066b8 MS |
108 | ldp x0, x1, [sp, #64] |
109 | ldp x2, x3, [sp, #48] | |
110 | ldp x4, x5, [sp, #32] | |
111 | ldp x6, x7, [sp, #16] | |
9dbebe1a MS |
112 | ldp x8, x9, [sp], #(80+8*16) |
113 | cfi_adjust_cfa_offset (-(80+8*16)) | |
554066b8 MS |
114 | |
115 | ldp ip1, lr, [sp], #16 | |
116 | cfi_adjust_cfa_offset (-16) | |
117 | ||
118 | /* Jump to the newly found address. */ | |
119 | br ip0 | |
120 | ||
121 | cfi_endproc | |
122 | .size _dl_runtime_resolve, .-_dl_runtime_resolve | |
123 | #ifndef PROF | |
124 | .globl _dl_runtime_profile | |
125 | .type _dl_runtime_profile, #function | |
126 | cfi_startproc | |
127 | .align 2 | |
128 | _dl_runtime_profile: | |
129 | /* AArch64 we get called with: | |
130 | ip0 &PLTGOT[2] | |
131 | ip1 temp(dl resolver entry point) | |
132 | [sp, #8] lr | |
133 | [sp, #0] &PLTGOT[n] | |
134 | ||
135 | Stack frame layout: | |
136 | [sp, #...] lr | |
137 | [sp, #...] &PLTGOT[n] | |
138 | [sp, #96] La_aarch64_regs | |
139 | [sp, #48] La_aarch64_retval | |
140 | [sp, #40] frame size return from pltenter | |
141 | [sp, #32] dl_profile_call saved x1 | |
142 | [sp, #24] dl_profile_call saved x0 | |
143 | [sp, #16] t1 | |
144 | [sp, #0] x29, lr <- x29 | |
145 | */ | |
146 | ||
147 | # define OFFSET_T1 16 | |
148 | # define OFFSET_SAVED_CALL_X0 OFFSET_T1 + 8 | |
149 | # define OFFSET_FS OFFSET_SAVED_CALL_X0 + 16 | |
150 | # define OFFSET_RV OFFSET_FS + 8 | |
151 | # define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV | |
152 | ||
153 | # define SF_SIZE OFFSET_RG + DL_SIZEOF_RG | |
154 | ||
155 | # define OFFSET_PLTGOTN SF_SIZE | |
156 | # define OFFSET_LR OFFSET_PLTGOTN + 8 | |
157 | ||
158 | /* Save arguments. */ | |
159 | sub sp, sp, #SF_SIZE | |
160 | cfi_adjust_cfa_offset (SF_SIZE) | |
161 | stp x29, x30, [SP, #0] | |
162 | mov x29, sp | |
163 | cfi_def_cfa_register (x29) | |
164 | cfi_rel_offset (x29, 0) | |
165 | cfi_rel_offset (lr, 8) | |
166 | ||
167 | stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0] | |
168 | cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0) | |
169 | cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8) | |
170 | stp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] | |
171 | cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0) | |
172 | cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8) | |
173 | stp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] | |
174 | cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0) | |
175 | cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8) | |
176 | stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] | |
177 | cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0) | |
178 | cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8) | |
179 | ||
180 | stp d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] | |
181 | cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0) | |
182 | cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8) | |
183 | stp d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1] | |
184 | cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0) | |
185 | cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8) | |
186 | stp d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] | |
187 | cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0) | |
188 | cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8) | |
189 | stp d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] | |
190 | cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0) | |
191 | cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8) | |
192 | ||
193 | add x0, x29, #SF_SIZE + 16 | |
194 | ldr x1, [x29, #OFFSET_LR] | |
195 | stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP] | |
196 | ||
197 | /* Get pointer to linker struct. */ | |
389d1f1b | 198 | ldr PTR_REG (0), [ip0, #-PTR_SIZE] |
554066b8 MS |
199 | |
200 | /* Prepare to call _dl_profile_fixup(). */ | |
201 | ldr x1, [x29, OFFSET_PLTGOTN] /* Recover &PLTGOT[n] */ | |
202 | ||
203 | sub x1, x1, ip0 | |
204 | add x1, x1, x1, lsl #1 | |
205 | lsl x1, x1, #3 | |
389d1f1b | 206 | sub x1, x1, #(RELA_SIZE<<3) |
554066b8 MS |
207 | lsr x1, x1, #3 |
208 | ||
209 | stp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] | |
210 | ||
211 | /* Set up extra args for _dl_profile_fixup */ | |
212 | ldr x2, [x29, #OFFSET_LR] /* load saved LR */ | |
213 | add x3, x29, #OFFSET_RG /* address of La_aarch64_reg */ | |
214 | add x4, x29, #OFFSET_FS /* address of framesize */ | |
215 | bl _dl_profile_fixup | |
216 | ||
389d1f1b SE |
217 | ldr ip0l, [x29, #OFFSET_FS] /* framesize == 0 */ |
218 | cmp ip0l, #0 | |
554066b8 MS |
219 | bge 1f |
220 | cfi_remember_state | |
221 | ||
222 | /* Save the return. */ | |
223 | mov ip0, x0 | |
224 | ||
225 | /* Get arguments and return address back. */ | |
226 | ldp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0] | |
227 | ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] | |
228 | ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] | |
229 | ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] | |
230 | ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] | |
231 | ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] | |
232 | ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] | |
233 | ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] | |
234 | ||
235 | cfi_def_cfa_register (sp) | |
236 | ldp x29, x30, [x29, #0] | |
237 | cfi_restore(x29) | |
238 | cfi_restore(x30) | |
239 | ||
240 | add sp, sp, SF_SIZE + 16 | |
241 | cfi_adjust_cfa_offset (- SF_SIZE - 16) | |
242 | ||
243 | /* Jump to the newly found address. */ | |
244 | br ip0 | |
245 | ||
246 | cfi_restore_state | |
247 | 1: | |
248 | /* The new frame size is in ip0. */ | |
249 | ||
389d1f1b | 250 | sub PTR_REG (1), PTR_REG (29), ip0l |
554066b8 MS |
251 | and sp, x1, #0xfffffffffffffff0 |
252 | ||
253 | str x0, [x29, #OFFSET_T1] | |
254 | ||
255 | mov x0, sp | |
256 | add x1, x29, #SF_SIZE + 16 | |
257 | mov x2, ip0 | |
258 | bl memcpy | |
259 | ||
260 | ldr ip0, [x29, #OFFSET_T1] | |
261 | ||
262 | /* Call the function. */ | |
263 | ldp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0] | |
264 | ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] | |
265 | ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] | |
266 | ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] | |
267 | ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] | |
268 | ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] | |
269 | ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] | |
270 | ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] | |
271 | blr ip0 | |
272 | stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] | |
273 | stp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] | |
274 | stp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] | |
275 | ||
276 | /* Setup call to pltexit */ | |
277 | ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] | |
278 | add x2, x29, #OFFSET_RG | |
279 | add x3, x29, #OFFSET_RV | |
280 | bl _dl_call_pltexit | |
281 | ||
282 | ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] | |
283 | ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] | |
284 | ldp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] | |
285 | /* LR from within La_aarch64_reg */ | |
286 | ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR] | |
287 | cfi_restore(lr) | |
288 | mov sp, x29 | |
289 | cfi_def_cfa_register (sp) | |
290 | ldr x29, [x29, #0] | |
291 | cfi_restore(x29) | |
292 | add sp, sp, SF_SIZE + 16 | |
293 | cfi_adjust_cfa_offset (- SF_SIZE - 16) | |
294 | ||
295 | br lr | |
296 | ||
297 | cfi_endproc | |
298 | .size _dl_runtime_profile, .-_dl_runtime_profile | |
299 | #endif | |
300 | .previous |