|  | /* PLT trampolines. hppa version. | 
|  | Copyright (C) 2005-2016 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 |