Blame sysdeps/hppa/dl-trampoline.S

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