1/* PLT trampolines. hppa version. 2 Copyright (C) 2005-2021 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 21/* This code gets called via the .plt stub, and is used in 22 dl-runtime.c to call the `_dl_fixup' function and then redirect 23 to the address it returns. `_dl_fixup' takes two arguments, however 24 `_dl_profile_fixup' takes a number of parameters for use with 25 library auditing (LA). 26 27 WARNING: This template is also used by gcc's __cffc, and expects 28 that the "bl" for _dl_runtime_resolve exist at a particular offset. 29 Do not change this template without changing gcc, while the prefix 30 "bl" should fix everything so gcc finds the right spot, it will 31 slow down __cffc when it attempts to call fixup to resolve function 32 descriptor references. Please refer to gcc/gcc/config/pa/fptr.c 33 34 Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp, r22 = fp. */ 35 36 /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ 37 .text 38 /* THIS CODE DOES NOT EXECUTE */ 39 bl _dl_fixup, %r2 40 .text 41 .global _dl_runtime_resolve 42 .type _dl_runtime_resolve,@function 43 cfi_startproc 44 .align 4 45_dl_runtime_resolve: 46 .PROC 47 .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 48 .ENTRY 49 /* SAVE_RP says we do */ 50 stw %rp, -20(%sp) 51 52 /* Save static link register */ 53 stw %r29,-16(%sp) 54 /* Save argument registers */ 55 stw %r26,-36(%sp) 56 stw %r25,-40(%sp) 57 stw %r24,-44(%sp) 58 stw %r23,-48(%sp) 59 60 /* Build a call frame, and save structure pointer. */ 61 copy %sp, %r1 /* Copy previous sp */ 62 /* Save function result address (on entry) */ 63 stwm %r28,128(%sp) 64 /* Fill in some frame info to follow ABI */ 65 stw %r1,-4(%sp) /* Previous sp */ 66 stw %r21,-32(%sp) /* PIC register value */ 67 68 /* Save input floating point registers. This must be done 69 in the new frame since the previous frame doesn't have 70 enough space */ 71 ldo -64(%sp),%r1 72 fstd,ma %fr4,-8(%r1) 73 fstd,ma %fr5,-8(%r1) 74 fstd,ma %fr6,-8(%r1) 75 76 /* Test PA_GP_RELOC bit. */ 77 bb,>= %r19,31,2f /* branch if not reloc offset */ 78 fstd,ma %fr7,-8(%r1) 79 80 /* Set up args to fixup func, needs only two arguments */ 81 ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ 82 copy %r19,%r25 /* (2) reloc offset */ 83 84 /* Call the real address resolver. */ 853: bl _dl_fixup,%rp 86 copy %r21,%r19 /* set fixup func ltp */ 87 88 /* While the linker will set a function pointer to NULL when it 89 encounters an undefined weak function, we need to dynamically 90 detect removed weak functions. The issue arises because a weak 91 __gmon_start__ function was added to shared executables to work 92 around issues in _init that are now resolved. The presence of 93 __gmon_start__ in every shared library breaks the linker 94 `--as-needed' option. This __gmon_start__ function does nothing 95 but removal is tricky. Depending on the binding, removal can 96 cause an application using it to fault. The call to _dl_fixup 97 returns NULL when a function isn't resolved. In order to help 98 with __gmon_start__ removal, we return directly to the caller 99 when _dl_fixup returns NULL. This check could be removed when 100 BZ 19170 is fixed. */ 101 comib,= 0,%r28,1f 102 103 /* Load up the returned func descriptor */ 104 copy %r28, %r22 105 copy %r29, %r19 106 107 /* Reload arguments fp args */ 108 ldo -64(%sp),%r1 109 fldd,ma -8(%r1),%fr4 110 fldd,ma -8(%r1),%fr5 111 fldd,ma -8(%r1),%fr6 112 fldd,ma -8(%r1),%fr7 113 114 /* Adjust sp, and restore function result address*/ 115 ldwm -128(%sp),%r28 116 117 /* Reload static link register */ 118 ldw -16(%sp),%r29 119 /* Reload general args */ 120 ldw -36(%sp),%r26 121 ldw -40(%sp),%r25 122 ldw -44(%sp),%r24 123 ldw -48(%sp),%r23 124 125 /* Jump to new function, but return to previous function */ 126 bv %r0(%r22) 127 ldw -20(%sp),%rp 128 1291: 130 /* Return to previous function */ 131 ldw -148(%sp),%rp 132 bv %r0(%rp) 133 ldo -128(%sp),%sp 134 1352: 136 /* Set up args for _dl_fix_reloc_arg. */ 137 copy %r22,%r26 /* (1) function pointer */ 138 depi 0,31,2,%r26 /* clear least significant bits */ 139 ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ 140 141 /* Save ltp and link map arg for _dl_fixup. */ 142 stw %r21,-56(%sp) /* ltp */ 143 stw %r25,-60(%sp) /* struct link map */ 144 145 /* Find reloc offset. */ 146 bl _dl_fix_reloc_arg,%rp 147 copy %r21,%r19 /* set func ltp */ 148 149 /* Set up args for _dl_fixup. */ 150 ldw -56(%sp),%r21 /* ltp */ 151 ldw -60(%sp),%r26 /* (1) struct link map */ 152 b 3b 153 copy %ret0,%r25 /* (2) reloc offset */ 154 .EXIT 155 .PROCEND 156 cfi_endproc 157 .size _dl_runtime_resolve, . - _dl_runtime_resolve 158 159 .text 160 .global _dl_runtime_profile 161 .type _dl_runtime_profile,@function 162 cfi_startproc 163 .align 4 164_dl_runtime_profile: 165 .PROC 166 .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 167 .ENTRY 168 169 /* SAVE_RP says we do */ 170 stw %rp, -20(%sp) 171 /* Save static link register */ 172 stw %r29,-16(%sp) 173 174 /* Build a call frame, and save structure pointer. */ 175 copy %sp, %r1 /* Copy previous sp */ 176 /* Save function result address (on entry) */ 177 stwm %r28,192(%sp) 178 /* Fill in some frame info to follow ABI */ 179 stw %r1,-4(%sp) /* Previous sp */ 180 stw %r21,-32(%sp) /* PIC register value */ 181 182 /* Create La_hppa_retval */ 183 /* -140, lrv_r28 184 -136, lrv_r29 185 -132, 4 byte pad 186 -128, lr_fr4 (8 bytes) */ 187 188 /* Create save space for _dl_profile_fixup arguments 189 -120, Saved reloc offset 190 -116, Saved struct link_map 191 -112, *framesizep */ 192 193 /* Create La_hppa_regs */ 194 /* 32-bit registers */ 195 stw %r26,-108(%sp) 196 stw %r25,-104(%sp) 197 stw %r24,-100(%sp) 198 stw %r23,-96(%sp) 199 /* -92, 4 byte pad */ 200 /* 64-bit floating point registers */ 201 ldo -88(%sp),%r1 202 fstd,ma %fr4,8(%r1) 203 fstd,ma %fr5,8(%r1) 204 fstd,ma %fr6,8(%r1) 205 fstd,ma %fr7,8(%r1) 206 207 /* Test PA_GP_RELOC bit. */ 208 bb,>= %r19,31,2f /* branch if not reloc offset */ 209 /* 32-bit stack pointer */ 210 stw %sp,-56(%sp) 211 212 /* Set up args to fixup func, needs five arguments */ 213 ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ 214 stw %r26,-116(%sp) /* Save struct link_map */ 215 copy %r19,%r25 /* (2) reloc offset */ 216 stw %r25,-120(%sp) /* Save reloc offset */ 217 copy %rp,%r24 /* (3) profile_fixup needs rp */ 218 ldo -56(%sp),%r23 /* (4) La_hppa_regs */ 219 ldo -112(%sp), %r1 220 stw %r1, -52(%sp) /* (5) long int *framesizep */ 221 222 /* Call the real address resolver. */ 2233: bl _dl_profile_fixup,%rp 224 copy %r21,%r19 /* set fixup func ltp */ 225 226 /* Load up the returned function descriptor */ 227 copy %r28, %r22 228 copy %r29, %r19 229 230 /* Restore gr/fr/sp/rp */ 231 ldw -108(%sp),%r26 232 ldw -104(%sp),%r25 233 ldw -100(%sp),%r24 234 ldw -96(%sp),%r23 235 /* -92, 4 byte pad, skip */ 236 ldo -88(%sp),%r1 237 fldd,ma 8(%r1),%fr4 238 fldd,ma 8(%r1),%fr5 239 fldd,ma 8(%r1),%fr6 240 fldd,ma 8(%r1),%fr7 241 242 /* Reload rp register -(192+20) without adjusting stack */ 243 ldw -212(%sp),%rp 244 245 /* Reload static link register -(192+16) without adjusting stack */ 246 ldw -208(%sp),%r29 247 248 /* *framesizep is >= 0 if we have to run pltexit */ 249 ldw -112(%sp),%r28 250 cmpb,>>=,N %r0,%r28,L(cpe) 251 252 /* Adjust sp, and restore function result address*/ 253 ldwm -192(%sp),%r28 254 /* Jump to new function, but return to previous function */ 255 bv %r0(%r22) 256 ldw -20(%sp),%rp 257 /* NO RETURN */ 258 259L(nf): 260 /* Call the returned function descriptor */ 261 bv %r0(%r22) 262 nop 263 b,n L(cont) 264 265L(cpe): 266 /* We are going to call the resolved function, but we have a 267 stack frame in the middle. We use the value of framesize to 268 guess how much extra frame we need, and how much frame to 269 copy forward. */ 270 271 /* Round to nearest multiple of 64 */ 272 addi 63, %r28, %r28 273 depi 0, 27, 6, %r28 274 275 /* Calcualte start of stack copy */ 276 ldo -192(%sp),%r2 277 278 /* Increate the stack by *framesizep */ 279 copy %sp, %r1 280 add %sp, %r28, %sp 281 /* Save stack pointer */ 282 stw %r1, -4(%sp) 283 284 /* Single byte copy of prevous stack onto newly allocated stack */ 2851: ldb %r28(%r2), %r1 286 add %r28, %sp, %r26 287 stb %r1, 0(%r26) 288 addi,< -1,%r28,%r28 289 b,n 1b 290 291 /* Retore r28 and r27 and r2 already points at -192(%sp) */ 292 ldw 0(%r2),%r28 293 ldw 84(%r2),%r26 294 295 /* Calculate address of L(cont) */ 296 b,l L(nf),%r2 297 depwi 0,31,2,%r2 298L(cont): 299 /* Undo fake stack */ 300 ldw -4(%sp),%r1 301 copy %r1, %sp 302 303 /* Arguments to _dl_audit_pltexit */ 304 ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ 305 ldw -120(%sp), %r25 /* (2) reloc offsets */ 306 ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ 307 ldo -124(%sp), %r23 /* (4) *La_hppa_retval */ 308 309 /* Fill *La_hppa_retval */ 310 stw %r28,-140(%sp) 311 stw %r29,-136(%sp) 312 ldo -128(%sp), %r1 313 fstd %fr4,0(%r1) 314 315 /* Call _dl_audit_pltexit */ 316 bl _dl_audit_pltexit,%rp 317 nop 318 319 /* Restore *La_hppa_retval */ 320 ldw -140(%sp), %r28 321 ldw -136(%sp), %r29 322 ldo -128(%sp), %r1 323 fldd 0(%r1), %fr4 324 325 /* Unwind the stack */ 326 ldo 192(%sp),%sp 327 /* Retore callers rp */ 328 ldw -20(%sp),%rp 329 /* Return */ 330 bv,n 0(%r2) 331 3322: 333 /* Set up args for _dl_fix_reloc_arg. */ 334 copy %r22,%r26 /* (1) function pointer */ 335 depi 0,31,2,%r26 /* clear least significant bits */ 336 ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ 337 338 /* Save ltp and link map arg for _dl_fixup. */ 339 stw %r21,-92(%sp) /* ltp */ 340 stw %r25,-116(%sp) /* struct link map */ 341 342 /* Find reloc offset. */ 343 bl _dl_fix_reloc_arg,%rp 344 copy %r21,%r19 /* set func ltp */ 345 346 /* Restore fixup ltp. */ 347 ldw -92(%sp),%r21 /* ltp */ 348 349 /* Set up args to fixup func, needs five arguments */ 350 ldw -116(%sp),%r26 /* (1) struct link map */ 351 copy %ret0,%r25 /* (2) reloc offset */ 352 stw %r25,-120(%sp) /* Save reloc offset */ 353 ldw -212(%sp),%r24 /* (3) profile_fixup needs rp */ 354 ldo -56(%sp),%r23 /* (4) La_hppa_regs */ 355 ldo -112(%sp), %r1 356 b 3b 357 stw %r1, -52(%sp) /* (5) long int *framesizep */ 358 .EXIT 359 .PROCEND 360 cfi_endproc 361 .size _dl_runtime_profile, . - _dl_runtime_profile 362