| /* PLT trampolines. hppa version. |
| Copyright (C) 2005-2014 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| The GNU C Library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include <sysdep.h> |
| |
| /* This code gets called via the .plt stub, and is used in |
| dl-runtime.c to call the `_dl_fixup' function and then redirect |
| to the address it returns. `_dl_fixup' takes two arguments, however |
| `_dl_profile_fixup' takes a number of parameters for use with |
| library auditing (LA). |
| |
| WARNING: This template is also used by gcc's __cffc, and expects |
| that the "bl" for _dl_runtime_resolve exist at a particular offset. |
| Do not change this template without changing gcc, while the prefix |
| "bl" should fix everything so gcc finds the right spot, it will |
| slow down __cffc when it attempts to call fixup to resolve function |
| descriptor references. Please refer to gcc/gcc/config/pa/fptr.c |
| |
| Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */ |
| |
| /* RELOCATION MARKER: bl to provide gcc's __cffc with fixup loc. */ |
| .text |
| /* THIS CODE DOES NOT EXECUTE */ |
| bl _dl_fixup, %r2 |
| .text |
| .global _dl_runtime_resolve |
| .type _dl_runtime_resolve,@function |
| cfi_startproc |
| .align 4 |
| _dl_runtime_resolve: |
| .PROC |
| .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3 |
| .ENTRY |
| /* SAVE_RP says we do */ |
| stw %rp, -20(%sp) |
| |
| /* Save static link register */ |
| stw %r29,-16(%sp) |
| /* Save argument registers */ |
| stw %r26,-36(%sp) |
| stw %r25,-40(%sp) |
| stw %r24,-44(%sp) |
| stw %r23,-48(%sp) |
| |
| /* Build a call frame, and save structure pointer. */ |
| copy %sp, %r1 /* Copy previous sp */ |
| /* Save function result address (on entry) */ |
| stwm %r28,128(%sp) |
| /* Fillin some frame info to follow ABI */ |
| stw %r1,-4(%sp) /* Previous sp */ |
| stw %r21,-32(%sp) /* PIC register value */ |
| |
| /* Save input floating point registers. This must be done |
| in the new frame since the previous frame doesn't have |
| enough space */ |
| ldo -56(%sp),%r1 |
| fstd,ma %fr4,-8(%r1) |
| fstd,ma %fr5,-8(%r1) |
| fstd,ma %fr6,-8(%r1) |
| fstd,ma %fr7,-8(%r1) |
| |
| /* Set up args to fixup func, needs only two arguments */ |
| ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
| copy %r19,%r25 /* (2) reloc offset */ |
| |
| /* Call the real address resolver. */ |
| bl _dl_fixup,%rp |
| copy %r21,%r19 /* set fixup func ltp */ |
| |
| /* Load up the returned func descriptor */ |
| copy %r28, %r22 |
| copy %r29, %r19 |
| |
| /* Reload arguments fp args */ |
| ldo -56(%sp),%r1 |
| fldd,ma -8(%r1),%fr4 |
| fldd,ma -8(%r1),%fr5 |
| fldd,ma -8(%r1),%fr6 |
| fldd,ma -8(%r1),%fr7 |
| |
| /* Adjust sp, and restore function result address*/ |
| ldwm -128(%sp),%r28 |
| |
| /* Reload static link register */ |
| ldw -16(%sp),%r29 |
| /* Reload general args */ |
| ldw -36(%sp),%r26 |
| ldw -40(%sp),%r25 |
| ldw -44(%sp),%r24 |
| ldw -48(%sp),%r23 |
| |
| /* Jump to new function, but return to previous function */ |
| bv %r0(%r22) |
| ldw -20(%sp),%rp |
| .EXIT |
| .PROCEND |
| cfi_endproc |
| .size _dl_runtime_resolve, . - _dl_runtime_resolve |
| |
| .text |
| .global _dl_runtime_profile |
| .type _dl_runtime_profile,@function |
| cfi_startproc |
| .align 4 |
| _dl_runtime_profile: |
| .PROC |
| .CALLINFO FRAME=192,CALLS,SAVE_RP,ENTRY_GR=3 |
| .ENTRY |
| |
| /* SAVE_RP says we do */ |
| stw %rp, -20(%sp) |
| /* Save static link register */ |
| stw %r29,-16(%sp) |
| |
| /* Build a call frame, and save structure pointer. */ |
| copy %sp, %r1 /* Copy previous sp */ |
| /* Save function result address (on entry) */ |
| stwm %r28,192(%sp) |
| /* Fillin some frame info to follow ABI */ |
| stw %r1,-4(%sp) /* Previous sp */ |
| stw %r21,-32(%sp) /* PIC register value */ |
| |
| /* Create La_hppa_retval */ |
| /* -140, lrv_r28 |
| -136, lrv_r29 |
| -132, 4 byte pad |
| -128, lr_fr4 (8 bytes) */ |
| |
| /* Create save space for _dl_profile_fixup arguments |
| -120, Saved reloc offset |
| -116, Saved struct link_map |
| -112, *framesizep */ |
| |
| /* Create La_hppa_regs */ |
| /* 32-bit registers */ |
| stw %r26,-108(%sp) |
| stw %r25,-104(%sp) |
| stw %r24,-100(%sp) |
| stw %r23,-96(%sp) |
| /* -92, 4 byte pad */ |
| /* 64-bit floating point registers */ |
| ldo -88(%sp),%r1 |
| fstd,ma %fr4,8(%r1) |
| fstd,ma %fr5,8(%r1) |
| fstd,ma %fr6,8(%r1) |
| fstd,ma %fr7,8(%r1) |
| /* 32-bit stack pointer and return register */ |
| stw %sp,-56(%sp) |
| stw %r2,-52(%sp) |
| |
| |
| /* Set up args to fixup func, needs five arguments */ |
| ldw 8+4(%r20),%r26 /* (1) got[1] == struct link_map */ |
| stw %r26,-116(%sp) /* Save struct link_map */ |
| copy %r19,%r25 /* (2) reloc offset */ |
| stw %r25,-120(%sp) /* Save reloc offset */ |
| copy %rp,%r24 /* (3) profile_fixup needs rp */ |
| ldo -56(%sp),%r23 /* (4) La_hppa_regs */ |
| ldo -112(%sp), %r1 |
| stw %r1, -52(%sp) /* (5) long int *framesizep */ |
| |
| /* Call the real address resolver. */ |
| bl _dl_profile_fixup,%rp |
| copy %r21,%r19 /* set fixup func ltp */ |
| |
| /* Load up the returned function descriptor */ |
| copy %r28, %r22 |
| copy %r29, %r19 |
| |
| /* Restore gr/fr/sp/rp */ |
| ldw -108(%sp),%r26 |
| ldw -104(%sp),%r25 |
| ldw -100(%sp),%r24 |
| ldw -96(%sp),%r23 |
| /* -92, 4 byte pad, skip */ |
| ldo -88(%sp),%r1 |
| fldd,ma 8(%r1),%fr4 |
| fldd,ma 8(%r1),%fr5 |
| fldd,ma 8(%r1),%fr6 |
| fldd,ma 8(%r1),%fr7 |
| ldw -52(%sp),%rp |
| |
| /* Reload static link register -(192+16) without adjusting stack */ |
| ldw -208(%sp),%r29 |
| |
| /* *framesizep is >= 0 if we have to run pltexit */ |
| ldw -112(%sp),%r28 |
| cmpb,>>=,N %r0,%r28,L(cpe) |
| |
| /* Adjust sp, and restore function result address*/ |
| ldwm -192(%sp),%r28 |
| /* Jump to new function, but return to previous function */ |
| bv %r0(%r22) |
| ldw -20(%sp),%rp |
| /* NO RETURN */ |
| |
| L(nf): |
| /* Call the returned function descriptor */ |
| bv %r0(%r22) |
| nop |
| b,n L(cont) |
| |
| L(cpe): |
| /* We are going to call the resolved function, but we have a |
| stack frame in the middle. We use the value of framesize to |
| guess how much extra frame we need, and how much frame to |
| copy forward. */ |
| |
| /* Round to nearest multiple of 64 */ |
| addi 63, %r28, %r28 |
| depi 0, 27, 6, %r28 |
| |
| /* Calcualte start of stack copy */ |
| ldo -192(%sp),%r2 |
| |
| /* Increate the stack by *framesizep */ |
| copy %sp, %r1 |
| add %sp, %r28, %sp |
| /* Save stack pointer */ |
| stw %r1, -4(%sp) |
| |
| /* Single byte copy of prevous stack onto newly allocated stack */ |
| 1: ldb %r28(%r2), %r1 |
| add %r28, %sp, %r26 |
| stb %r1, 0(%r26) |
| addi,< -1,%r28,%r28 |
| b,n 1b |
| |
| /* Retore r28 and r27 and r2 already points at -192(%sp) */ |
| ldw 0(%r2),%r28 |
| ldw 84(%r2),%r26 |
| |
| /* Calculate address of L(cont) */ |
| b,l L(nf),%r2 |
| depwi 0,31,2,%r2 |
| L(cont): |
| /* Undo fake stack */ |
| ldw -4(%sp),%r1 |
| copy %r1, %sp |
| |
| /* Arguments to _dl_call_pltexit */ |
| ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ |
| ldw -120(%sp), %r25 /* (2) reloc offsets */ |
| ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ |
| ldo -124(%sp), %r23 /* (4) *La_hppa_retval */ |
| |
| /* Fill *La_hppa_retval */ |
| stw %r28,-140(%sp) |
| stw %r29,-136(%sp) |
| ldo -128(%sp), %r1 |
| fstd %fr4,0(%r1) |
| |
| /* Call _dl_call_pltexit */ |
| bl _dl_call_pltexit,%rp |
| nop |
| |
| /* Restore *La_hppa_retval */ |
| ldw -140(%sp), %r28 |
| ldw -136(%sp), %r29 |
| ldo -128(%sp), %r1 |
| fldd 0(%r1), %fr4 |
| |
| /* Unwind the stack */ |
| ldo 192(%sp),%sp |
| /* Retore callers rp */ |
| ldw -20(%sp),%rp |
| /* Return */ |
| bv,n 0(%r2) |
| .EXIT |
| .PROCEND |
| cfi_endproc |
| .size _dl_runtime_profile, . - _dl_runtime_profile |
| |