| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2005-2016 Free Software Foundation, Inc. | 
|  | 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 | 
|  | 17 | <http://www.gnu.org/licenses/>.  */ | 
|  | 18 |  | 
|  | 19 | #include <sysdep.h> | 
|  | 20 | #include <libc-symbols.h> | 
|  | 21 |  | 
|  | 22 | #include "dl-link.h" | 
|  | 23 |  | 
|  | 24 | #define ip0 x16 | 
|  | 25 | #define ip1 x17 | 
|  | 26 | #define lr  x30 | 
|  | 27 |  | 
|  | 28 | .text | 
|  | 29 | .globl _dl_runtime_resolve | 
|  | 30 | .type _dl_runtime_resolve, #function | 
|  | 31 | cfi_startproc | 
|  | 32 | .align 2 | 
|  | 33 | _dl_runtime_resolve: | 
|  | 34 | /* AArch64 we get called with: | 
|  | 35 | ip0		&PLTGOT[2] | 
|  | 36 | ip1		temp(dl resolver entry point) | 
|  | 37 | [sp, #8]	lr | 
|  | 38 | [sp, #0]	&PLTGOT[n] | 
|  | 39 | */ | 
|  | 40 |  | 
|  | 41 | cfi_rel_offset (lr, 8) | 
|  | 42 |  | 
|  | 43 | /* Save arguments.  */ | 
|  | 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) | 
|  | 48 |  | 
|  | 49 | stp	x6, x7, [sp,  #16] | 
|  | 50 | cfi_rel_offset (x6, 16) | 
|  | 51 | cfi_rel_offset (x7, 24) | 
|  | 52 |  | 
|  | 53 | stp	x4, x5, [sp,  #32] | 
|  | 54 | cfi_rel_offset (x4, 32) | 
|  | 55 | cfi_rel_offset (x5, 40) | 
|  | 56 |  | 
|  | 57 | stp	x2, x3, [sp,  #48] | 
|  | 58 | cfi_rel_offset (x2, 48) | 
|  | 59 | cfi_rel_offset (x3, 56) | 
|  | 60 |  | 
|  | 61 | stp	x0, x1, [sp,  #64] | 
|  | 62 | cfi_rel_offset (x0, 64) | 
|  | 63 | cfi_rel_offset (x1, 72) | 
|  | 64 |  | 
|  | 65 | stp	q0, q1, [sp, #(80+0*16)] | 
|  | 66 | cfi_rel_offset (q0, 80+0*16) | 
|  | 67 | cfi_rel_offset (q1, 80+1*16) | 
|  | 68 |  | 
|  | 69 | stp	q2, q3, [sp, #(80+2*16)] | 
|  | 70 | cfi_rel_offset (q0, 80+2*16) | 
|  | 71 | cfi_rel_offset (q1, 80+3*16) | 
|  | 72 |  | 
|  | 73 | stp	q4, q5, [sp, #(80+4*16)] | 
|  | 74 | cfi_rel_offset (q0, 80+4*16) | 
|  | 75 | cfi_rel_offset (q1, 80+5*16) | 
|  | 76 |  | 
|  | 77 | stp	q6, q7, [sp, #(80+6*16)] | 
|  | 78 | cfi_rel_offset (q0, 80+6*16) | 
|  | 79 | cfi_rel_offset (q1, 80+7*16) | 
|  | 80 |  | 
|  | 81 | /* Get pointer to linker struct.  */ | 
|  | 82 | ldr	x0, [ip0, #-8] | 
|  | 83 |  | 
|  | 84 | /* Prepare to call _dl_fixup().  */ | 
|  | 85 | ldr	x1, [sp, 80+8*16]	/* Recover &PLTGOT[n] */ | 
|  | 86 |  | 
|  | 87 | sub     x1, x1, ip0 | 
|  | 88 | add     x1, x1, x1, lsl #1 | 
|  | 89 | lsl     x1, x1, #3 | 
|  | 90 | sub     x1, x1, #192 | 
|  | 91 | lsr     x1, x1, #3 | 
|  | 92 |  | 
|  | 93 | /* Call fixup routine.  */ | 
|  | 94 | bl	_dl_fixup | 
|  | 95 |  | 
|  | 96 | /* Save the return.  */ | 
|  | 97 | mov	ip0, x0 | 
|  | 98 |  | 
|  | 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)) | 
|  | 110 |  | 
|  | 111 | ldp	ip1, lr, [sp], #16 | 
|  | 112 | cfi_adjust_cfa_offset (-16) | 
|  | 113 |  | 
|  | 114 | /* Jump to the newly found address.  */ | 
|  | 115 | br	ip0 | 
|  | 116 |  | 
|  | 117 | cfi_endproc | 
|  | 118 | .size _dl_runtime_resolve, .-_dl_runtime_resolve | 
|  | 119 | #ifndef PROF | 
|  | 120 | .globl _dl_runtime_profile | 
|  | 121 | .type _dl_runtime_profile, #function | 
|  | 122 | cfi_startproc | 
|  | 123 | .align 2 | 
|  | 124 | _dl_runtime_profile: | 
|  | 125 | /* AArch64 we get called with: | 
|  | 126 | ip0		&PLTGOT[2] | 
|  | 127 | ip1		temp(dl resolver entry point) | 
|  | 128 | [sp, #8]	lr | 
|  | 129 | [sp, #0]	&PLTGOT[n] | 
|  | 130 |  | 
|  | 131 | Stack frame layout: | 
|  | 132 | [sp,   #...] lr | 
|  | 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 | 
|  | 139 | [sp,    #16] t1 | 
|  | 140 | [sp,     #0] x29, lr   <- x29 | 
|  | 141 | */ | 
|  | 142 |  | 
|  | 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 | 
|  | 148 |  | 
|  | 149 | # define SF_SIZE		OFFSET_RG + DL_SIZEOF_RG | 
|  | 150 |  | 
|  | 151 | # define OFFSET_PLTGOTN		SF_SIZE | 
|  | 152 | # define OFFSET_LR		OFFSET_PLTGOTN + 8 | 
|  | 153 |  | 
|  | 154 | /* Save arguments.  */ | 
|  | 155 | sub	sp, sp, #SF_SIZE | 
|  | 156 | cfi_adjust_cfa_offset (SF_SIZE) | 
|  | 157 | stp	x29, x30, [SP, #0] | 
|  | 158 | mov	x29, sp | 
|  | 159 | cfi_def_cfa_register (x29) | 
|  | 160 | cfi_rel_offset (x29, 0) | 
|  | 161 | cfi_rel_offset (lr, 8) | 
|  | 162 |  | 
|  | 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) | 
|  | 175 |  | 
|  | 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) | 
|  | 188 |  | 
|  | 189 | add     x0, x29, #SF_SIZE + 16 | 
|  | 190 | ldr	x1, [x29, #OFFSET_LR] | 
|  | 191 | stp	x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP] | 
|  | 192 |  | 
|  | 193 | /* Get pointer to linker struct.  */ | 
|  | 194 | ldr	x0, [ip0, #-8] | 
|  | 195 |  | 
|  | 196 | /* Prepare to call _dl_profile_fixup().  */ | 
|  | 197 | ldr	x1, [x29, OFFSET_PLTGOTN]	/* Recover &PLTGOT[n] */ | 
|  | 198 |  | 
|  | 199 | sub     x1, x1, ip0 | 
|  | 200 | add     x1, x1, x1, lsl #1 | 
|  | 201 | lsl     x1, x1, #3 | 
|  | 202 | sub     x1, x1, #192 | 
|  | 203 | lsr     x1, x1, #3 | 
|  | 204 |  | 
|  | 205 | stp	x0, x1, [x29, #OFFSET_SAVED_CALL_X0] | 
|  | 206 |  | 
|  | 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 */ | 
|  | 211 | bl	_dl_profile_fixup | 
|  | 212 |  | 
|  | 213 | ldr	ip0, [x29, #OFFSET_FS]		/* framesize == 0 */ | 
|  | 214 | cmp	ip0, #0 | 
|  | 215 | bge	1f | 
|  | 216 | cfi_remember_state | 
|  | 217 |  | 
|  | 218 | /* Save the return.  */ | 
|  | 219 | mov	ip0, x0 | 
|  | 220 |  | 
|  | 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] | 
|  | 230 |  | 
|  | 231 | cfi_def_cfa_register (sp) | 
|  | 232 | ldp	x29, x30, [x29, #0] | 
|  | 233 | cfi_restore(x29) | 
|  | 234 | cfi_restore(x30) | 
|  | 235 |  | 
|  | 236 | add	sp, sp, SF_SIZE + 16 | 
|  | 237 | cfi_adjust_cfa_offset (- SF_SIZE - 16) | 
|  | 238 |  | 
|  | 239 | /* Jump to the newly found address.  */ | 
|  | 240 | br	ip0 | 
|  | 241 |  | 
|  | 242 | cfi_restore_state | 
|  | 243 | 1: | 
|  | 244 | /* The new frame size is in ip0.  */ | 
|  | 245 |  | 
|  | 246 | sub	x1, x29, ip0 | 
|  | 247 | and	sp, x1, #0xfffffffffffffff0 | 
|  | 248 |  | 
|  | 249 | str	x0, [x29, #OFFSET_T1] | 
|  | 250 |  | 
|  | 251 | mov	x0, sp | 
|  | 252 | add	x1, x29, #SF_SIZE + 16 | 
|  | 253 | mov	x2, ip0 | 
|  | 254 | bl	memcpy | 
|  | 255 |  | 
|  | 256 | ldr	ip0, [x29, #OFFSET_T1] | 
|  | 257 |  | 
|  | 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] | 
|  | 267 | blr	ip0 | 
|  | 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] | 
|  | 271 |  | 
|  | 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 | 
|  | 276 | bl	_dl_call_pltexit | 
|  | 277 |  | 
|  | 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] | 
|  | 283 | cfi_restore(lr) | 
|  | 284 | mov	sp, x29 | 
|  | 285 | cfi_def_cfa_register (sp) | 
|  | 286 | ldr	x29, [x29, #0] | 
|  | 287 | cfi_restore(x29) | 
|  | 288 | add	sp, sp, SF_SIZE + 16 | 
|  | 289 | cfi_adjust_cfa_offset (- SF_SIZE - 16) | 
|  | 290 |  | 
|  | 291 | br	lr | 
|  | 292 |  | 
|  | 293 | cfi_endproc | 
|  | 294 | .size _dl_runtime_profile, .-_dl_runtime_profile | 
|  | 295 | #endif | 
|  | 296 | .previous |