xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame^] | 1 | /* PLT trampolines. hppa version. |
| 2 | Copyright (C) 2005-2016 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 | <http://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. */ |
| 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 | /* Fillin 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 -56(%sp),%r1 |
| 72 | fstd,ma %fr4,-8(%r1) |
| 73 | fstd,ma %fr5,-8(%r1) |
| 74 | fstd,ma %fr6,-8(%r1) |
| 75 | fstd,ma %fr7,-8(%r1) |
| 76 | |
| 77 | /* Set up args to fixup func, needs only two arguments */ |
| 78 | ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
| 79 | copy %r19,%r25 /* (2) reloc offset */ |
| 80 | |
| 81 | /* Call the real address resolver. */ |
| 82 | bl _dl_fixup,%rp |
| 83 | copy %r21,%r19 /* set fixup func ltp */ |
| 84 | |
| 85 | /* Load up the returned func descriptor */ |
| 86 | copy %r28, %r22 |
| 87 | copy %r29, %r19 |
| 88 | |
| 89 | /* Reload arguments fp args */ |
| 90 | ldo -56(%sp),%r1 |
| 91 | fldd,ma -8(%r1),%fr4 |
| 92 | fldd,ma -8(%r1),%fr5 |
| 93 | fldd,ma -8(%r1),%fr6 |
| 94 | fldd,ma -8(%r1),%fr7 |
| 95 | |
| 96 | /* Adjust sp, and restore function result address*/ |
| 97 | ldwm -128(%sp),%r28 |
| 98 | |
| 99 | /* Reload static link register */ |
| 100 | ldw -16(%sp),%r29 |
| 101 | /* Reload general args */ |
| 102 | ldw -36(%sp),%r26 |
| 103 | ldw -40(%sp),%r25 |
| 104 | ldw -44(%sp),%r24 |
| 105 | ldw -48(%sp),%r23 |
| 106 | |
| 107 | /* Jump to new function, but return to previous function */ |
| 108 | bv %r0(%r22) |
| 109 | ldw -20(%sp),%rp |
| 110 | .EXIT |
| 111 | .PROCEND |
| 112 | cfi_endproc |
| 113 | .size _dl_runtime_resolve, . - _dl_runtime_resolve |
| 114 | |
| 115 | .text |
| 116 | .global _dl_runtime_profile |
| 117 | .type _dl_runtime_profile,@function |
| 118 | cfi_startproc |
| 119 | .align 4 |
| 120 | _dl_runtime_profile: |
| 121 | .PROC |
| 122 | .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 |
| 123 | .ENTRY |
| 124 | |
| 125 | /* SAVE_RP says we do */ |
| 126 | stw %rp, -20(%sp) |
| 127 | /* Save static link register */ |
| 128 | stw %r29,-16(%sp) |
| 129 | |
| 130 | /* Build a call frame, and save structure pointer. */ |
| 131 | copy %sp, %r1 /* Copy previous sp */ |
| 132 | /* Save function result address (on entry) */ |
| 133 | stwm %r28,192(%sp) |
| 134 | /* Fillin some frame info to follow ABI */ |
| 135 | stw %r1,-4(%sp) /* Previous sp */ |
| 136 | stw %r21,-32(%sp) /* PIC register value */ |
| 137 | |
| 138 | /* Create La_hppa_retval */ |
| 139 | /* -140, lrv_r28 |
| 140 | -136, lrv_r29 |
| 141 | -132, 4 byte pad |
| 142 | -128, lr_fr4 (8 bytes) */ |
| 143 | |
| 144 | /* Create save space for _dl_profile_fixup arguments |
| 145 | -120, Saved reloc offset |
| 146 | -116, Saved struct link_map |
| 147 | -112, *framesizep */ |
| 148 | |
| 149 | /* Create La_hppa_regs */ |
| 150 | /* 32-bit registers */ |
| 151 | stw %r26,-108(%sp) |
| 152 | stw %r25,-104(%sp) |
| 153 | stw %r24,-100(%sp) |
| 154 | stw %r23,-96(%sp) |
| 155 | /* -92, 4 byte pad */ |
| 156 | /* 64-bit floating point registers */ |
| 157 | ldo -88(%sp),%r1 |
| 158 | fstd,ma %fr4,8(%r1) |
| 159 | fstd,ma %fr5,8(%r1) |
| 160 | fstd,ma %fr6,8(%r1) |
| 161 | fstd,ma %fr7,8(%r1) |
| 162 | /* 32-bit stack pointer and return register */ |
| 163 | stw %sp,-56(%sp) |
| 164 | stw %r2,-52(%sp) |
| 165 | |
| 166 | |
| 167 | /* Set up args to fixup func, needs five arguments */ |
| 168 | ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
| 169 | stw %r26,-116(%sp) /* Save struct link_map */ |
| 170 | copy %r19,%r25 /* (2) reloc offset */ |
| 171 | stw %r25,-120(%sp) /* Save reloc offset */ |
| 172 | copy %rp,%r24 /* (3) profile_fixup needs rp */ |
| 173 | ldo -56(%sp),%r23 /* (4) La_hppa_regs */ |
| 174 | ldo -112(%sp), %r1 |
| 175 | stw %r1, -52(%sp) /* (5) long int *framesizep */ |
| 176 | |
| 177 | /* Call the real address resolver. */ |
| 178 | bl _dl_profile_fixup,%rp |
| 179 | copy %r21,%r19 /* set fixup func ltp */ |
| 180 | |
| 181 | /* Load up the returned function descriptor */ |
| 182 | copy %r28, %r22 |
| 183 | copy %r29, %r19 |
| 184 | |
| 185 | /* Restore gr/fr/sp/rp */ |
| 186 | ldw -108(%sp),%r26 |
| 187 | ldw -104(%sp),%r25 |
| 188 | ldw -100(%sp),%r24 |
| 189 | ldw -96(%sp),%r23 |
| 190 | /* -92, 4 byte pad, skip */ |
| 191 | ldo -88(%sp),%r1 |
| 192 | fldd,ma 8(%r1),%fr4 |
| 193 | fldd,ma 8(%r1),%fr5 |
| 194 | fldd,ma 8(%r1),%fr6 |
| 195 | fldd,ma 8(%r1),%fr7 |
| 196 | ldw -52(%sp),%rp |
| 197 | |
| 198 | /* Reload static link register -(192+16) without adjusting stack */ |
| 199 | ldw -208(%sp),%r29 |
| 200 | |
| 201 | /* *framesizep is >= 0 if we have to run pltexit */ |
| 202 | ldw -112(%sp),%r28 |
| 203 | cmpb,>>=,N %r0,%r28,L(cpe) |
| 204 | |
| 205 | /* Adjust sp, and restore function result address*/ |
| 206 | ldwm -192(%sp),%r28 |
| 207 | /* Jump to new function, but return to previous function */ |
| 208 | bv %r0(%r22) |
| 209 | ldw -20(%sp),%rp |
| 210 | /* NO RETURN */ |
| 211 | |
| 212 | L(nf): |
| 213 | /* Call the returned function descriptor */ |
| 214 | bv %r0(%r22) |
| 215 | nop |
| 216 | b,n L(cont) |
| 217 | |
| 218 | L(cpe): |
| 219 | /* We are going to call the resolved function, but we have a |
| 220 | stack frame in the middle. We use the value of framesize to |
| 221 | guess how much extra frame we need, and how much frame to |
| 222 | copy forward. */ |
| 223 | |
| 224 | /* Round to nearest multiple of 64 */ |
| 225 | addi 63, %r28, %r28 |
| 226 | depi 0, 27, 6, %r28 |
| 227 | |
| 228 | /* Calcualte start of stack copy */ |
| 229 | ldo -192(%sp),%r2 |
| 230 | |
| 231 | /* Increate the stack by *framesizep */ |
| 232 | copy %sp, %r1 |
| 233 | add %sp, %r28, %sp |
| 234 | /* Save stack pointer */ |
| 235 | stw %r1, -4(%sp) |
| 236 | |
| 237 | /* Single byte copy of prevous stack onto newly allocated stack */ |
| 238 | 1: ldb %r28(%r2), %r1 |
| 239 | add %r28, %sp, %r26 |
| 240 | stb %r1, 0(%r26) |
| 241 | addi,< -1,%r28,%r28 |
| 242 | b,n 1b |
| 243 | |
| 244 | /* Retore r28 and r27 and r2 already points at -192(%sp) */ |
| 245 | ldw 0(%r2),%r28 |
| 246 | ldw 84(%r2),%r26 |
| 247 | |
| 248 | /* Calculate address of L(cont) */ |
| 249 | b,l L(nf),%r2 |
| 250 | depwi 0,31,2,%r2 |
| 251 | L(cont): |
| 252 | /* Undo fake stack */ |
| 253 | ldw -4(%sp),%r1 |
| 254 | copy %r1, %sp |
| 255 | |
| 256 | /* Arguments to _dl_call_pltexit */ |
| 257 | ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ |
| 258 | ldw -120(%sp), %r25 /* (2) reloc offsets */ |
| 259 | ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ |
| 260 | ldo -124(%sp), %r23 /* (4) *La_hppa_retval */ |
| 261 | |
| 262 | /* Fill *La_hppa_retval */ |
| 263 | stw %r28,-140(%sp) |
| 264 | stw %r29,-136(%sp) |
| 265 | ldo -128(%sp), %r1 |
| 266 | fstd %fr4,0(%r1) |
| 267 | |
| 268 | /* Call _dl_call_pltexit */ |
| 269 | bl _dl_call_pltexit,%rp |
| 270 | nop |
| 271 | |
| 272 | /* Restore *La_hppa_retval */ |
| 273 | ldw -140(%sp), %r28 |
| 274 | ldw -136(%sp), %r29 |
| 275 | ldo -128(%sp), %r1 |
| 276 | fldd 0(%r1), %fr4 |
| 277 | |
| 278 | /* Unwind the stack */ |
| 279 | ldo 192(%sp),%sp |
| 280 | /* Retore callers rp */ |
| 281 | ldw -20(%sp),%rp |
| 282 | /* Return */ |
| 283 | bv,n 0(%r2) |
| 284 | .EXIT |
| 285 | .PROCEND |
| 286 | cfi_endproc |
| 287 | .size _dl_runtime_profile, . - _dl_runtime_profile |