1 /* Copyright (C) 2005-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
20 #include <libc-symbols.h>
29 .globl _dl_runtime_resolve
30 .type _dl_runtime_resolve, #function
34 /* AArch64 we get called with:
36 ip1 temp(dl resolver entry point)
41 cfi_rel_offset (lr, 8)
44 stp x8, x9, [sp, #-(80+8*16)]!
45 cfi_adjust_cfa_offset (80+8*16)
46 cfi_rel_offset (x8, 0)
47 cfi_rel_offset (x9, 8)
50 cfi_rel_offset (x6, 16)
51 cfi_rel_offset (x7, 24)
54 cfi_rel_offset (x4, 32)
55 cfi_rel_offset (x5, 40)
58 cfi_rel_offset (x2, 48)
59 cfi_rel_offset (x3, 56)
62 cfi_rel_offset (x0, 64)
63 cfi_rel_offset (x1, 72)
65 stp q0, q1, [sp, #(80+0*16)]
66 cfi_rel_offset (q0, 80+0*16)
67 cfi_rel_offset (q1, 80+1*16)
69 stp q2, q3, [sp, #(80+2*16)]
70 cfi_rel_offset (q0, 80+2*16)
71 cfi_rel_offset (q1, 80+3*16)
73 stp q4, q5, [sp, #(80+4*16)]
74 cfi_rel_offset (q0, 80+4*16)
75 cfi_rel_offset (q1, 80+5*16)
77 stp q6, q7, [sp, #(80+6*16)]
78 cfi_rel_offset (q0, 80+6*16)
79 cfi_rel_offset (q1, 80+7*16)
81 /* Get pointer to linker struct. */
84 /* Prepare to call _dl_fixup(). */
85 ldr x1, [sp, 80+8*16] /* Recover &PLTGOT[n] */
88 add x1, x1, x1, lsl #1
93 /* Call fixup routine. */
96 /* Save the return. */
99 /* Get arguments and return address back. */
100 ldp q0, q1, [sp, #(80+0*16)]
101 ldp q2, q3, [sp, #(80+2*16)]
102 ldp q4, q5, [sp, #(80+4*16)]
103 ldp q6, q7, [sp, #(80+6*16)]
104 ldp x0, x1, [sp, #64]
105 ldp x2, x3, [sp, #48]
106 ldp x4, x5, [sp, #32]
107 ldp x6, x7, [sp, #16]
108 ldp x8, x9, [sp], #(80+8*16)
109 cfi_adjust_cfa_offset (-(80+8*16))
111 ldp ip1, lr, [sp], #16
112 cfi_adjust_cfa_offset (-16)
114 /* Jump to the newly found address. */
118 .size _dl_runtime_resolve, .-_dl_runtime_resolve
120 .globl _dl_runtime_profile
121 .type _dl_runtime_profile, #function
125 /* AArch64 we get called with:
127 ip1 temp(dl resolver entry point)
133 [sp, #...] &PLTGOT[n]
134 [sp, #96] La_aarch64_regs
135 [sp, #48] La_aarch64_retval
136 [sp, #40] frame size return from pltenter
137 [sp, #32] dl_profile_call saved x1
138 [sp, #24] dl_profile_call saved x0
140 [sp, #0] x29, lr <- x29
143 # define OFFSET_T1 16
144 # define OFFSET_SAVED_CALL_X0 OFFSET_T1 + 8
145 # define OFFSET_FS OFFSET_SAVED_CALL_X0 + 16
146 # define OFFSET_RV OFFSET_FS + 8
147 # define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV
149 # define SF_SIZE OFFSET_RG + DL_SIZEOF_RG
151 # define OFFSET_PLTGOTN SF_SIZE
152 # define OFFSET_LR OFFSET_PLTGOTN + 8
154 /* Save arguments. */
156 cfi_adjust_cfa_offset (SF_SIZE)
157 stp x29, x30, [SP, #0]
159 cfi_def_cfa_register (x29)
160 cfi_rel_offset (x29, 0)
161 cfi_rel_offset (lr, 8)
163 stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
164 cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
165 cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
166 stp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
167 cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
168 cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
169 stp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
170 cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
171 cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
172 stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
173 cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
174 cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
176 stp d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
177 cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0)
178 cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8)
179 stp d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1]
180 cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0)
181 cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8)
182 stp d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
183 cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0)
184 cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8)
185 stp d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
186 cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0)
187 cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8)
189 add x0, x29, #SF_SIZE + 16
190 ldr x1, [x29, #OFFSET_LR]
191 stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP]
193 /* Get pointer to linker struct. */
196 /* Prepare to call _dl_profile_fixup(). */
197 ldr x1, [x29, OFFSET_PLTGOTN] /* Recover &PLTGOT[n] */
200 add x1, x1, x1, lsl #1
205 stp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
207 /* Set up extra args for _dl_profile_fixup */
208 ldr x2, [x29, #OFFSET_LR] /* load saved LR */
209 add x3, x29, #OFFSET_RG /* address of La_aarch64_reg */
210 add x4, x29, #OFFSET_FS /* address of framesize */
213 ldr ip0, [x29, #OFFSET_FS] /* framesize == 0 */
218 /* Save the return. */
221 /* Get arguments and return address back. */
222 ldp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
223 ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
224 ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
225 ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
226 ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
227 ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
228 ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
229 ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
231 cfi_def_cfa_register (sp)
232 ldp x29, x30, [x29, #0]
236 add sp, sp, SF_SIZE + 16
237 cfi_adjust_cfa_offset (- SF_SIZE - 16)
239 /* Jump to the newly found address. */
244 /* The new frame size is in ip0. */
247 and sp, x1, #0xfffffffffffffff0
249 str x0, [x29, #OFFSET_T1]
252 add x1, x29, #SF_SIZE + 16
256 ldr ip0, [x29, #OFFSET_T1]
258 /* Call the function. */
259 ldp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
260 ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
261 ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
262 ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
263 ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
264 ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
265 ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
266 ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
268 stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
269 stp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
270 stp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
272 /* Setup call to pltexit */
273 ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
274 add x2, x29, #OFFSET_RG
275 add x3, x29, #OFFSET_RV
278 ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
279 ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
280 ldp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
281 /* LR from within La_aarch64_reg */
282 ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
285 cfi_def_cfa_register (sp)
288 add sp, sp, SF_SIZE + 16
289 cfi_adjust_cfa_offset (- SF_SIZE - 16)
294 .size _dl_runtime_profile, .-_dl_runtime_profile