/* PLT trampolines. hppa version. Copyright (C) 2005-2023 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 . */ #include /* 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, r22 = fp. */ /* 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) /* Fill in 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 -64(%sp),%r1 fstd,ma %fr4,-8(%r1) fstd,ma %fr5,-8(%r1) fstd,ma %fr6,-8(%r1) /* Test PA_GP_RELOC bit. */ bb,>= %r19,31,2f /* branch if not reloc offset */ 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. */ 3: bl _dl_fixup,%rp copy %r21,%r19 /* set fixup func ltp */ /* While the linker will set a function pointer to NULL when it encounters an undefined weak function, we need to dynamically detect removed weak functions. The issue arises because a weak __gmon_start__ function was added to shared executables to work around issues in _init that are now resolved. The presence of __gmon_start__ in every shared library breaks the linker `--as-needed' option. This __gmon_start__ function does nothing but removal is tricky. Depending on the binding, removal can cause an application using it to fault. The call to _dl_fixup returns NULL when a function isn't resolved. In order to help with __gmon_start__ removal, we return directly to the caller when _dl_fixup returns NULL. This check could be removed when BZ 19170 is fixed. */ comib,= 0,%r28,1f /* Load up the returned func descriptor */ copy %r28, %r22 copy %r29, %r19 /* Reload arguments fp args */ ldo -64(%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 1: /* Return to previous function */ ldw -148(%sp),%rp bv %r0(%rp) ldo -128(%sp),%sp 2: /* Set up args for _dl_fix_reloc_arg. */ copy %r22,%r26 /* (1) function pointer */ depi 0,31,2,%r26 /* clear least significant bits */ ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ /* Save ltp and link map arg for _dl_fixup. */ stw %r21,-56(%sp) /* ltp */ stw %r25,-60(%sp) /* struct link map */ /* Find reloc offset. */ bl _dl_fix_reloc_arg,%rp copy %r21,%r19 /* set func ltp */ /* Set up args for _dl_fixup. */ ldw -56(%sp),%r21 /* ltp */ ldw -60(%sp),%r26 /* (1) struct link map */ b 3b copy %ret0,%r25 /* (2) reloc offset */ .EXIT .PROCEND cfi_endproc .size _dl_runtime_resolve, . - _dl_runtime_resolve #ifdef SHARED .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) /* Fill in 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) /* Test PA_GP_RELOC bit. */ bb,>= %r19,31,2f /* branch if not reloc offset */ /* 32-bit stack pointer */ stw %sp,-56(%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. */ 3: 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 /* Reload rp register -(192+20) without adjusting stack */ ldw -212(%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 /* Calculate 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 previous 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 /* Restore 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_audit_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_audit_pltexit */ bl _dl_audit_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 /* Restore callers rp */ ldw -20(%sp),%rp /* Return */ bv,n 0(%r2) 2: /* Set up args for _dl_fix_reloc_arg. */ copy %r22,%r26 /* (1) function pointer */ depi 0,31,2,%r26 /* clear least significant bits */ ldw 8+4(%r20),%r25 /* (2) got[1] == struct link_map */ /* Save ltp and link map arg for _dl_fixup. */ stw %r21,-92(%sp) /* ltp */ stw %r25,-116(%sp) /* struct link map */ /* Find reloc offset. */ bl _dl_fix_reloc_arg,%rp copy %r21,%r19 /* set func ltp */ /* Restore fixup ltp. */ ldw -92(%sp),%r21 /* ltp */ /* Set up args to fixup func, needs five arguments */ ldw -116(%sp),%r26 /* (1) struct link map */ copy %ret0,%r25 /* (2) reloc offset */ stw %r25,-120(%sp) /* Save reloc offset */ ldw -212(%sp),%r24 /* (3) profile_fixup needs rp */ ldo -56(%sp),%r23 /* (4) La_hppa_regs */ ldo -112(%sp), %r1 b 3b stw %r1, -52(%sp) /* (5) long int *framesizep */ .EXIT .PROCEND cfi_endproc .size _dl_runtime_profile, . - _dl_runtime_profile #endif