xref: /onnv-gate/usr/src/cmd/sgs/rtld/amd64/boot_elf.s (revision 6186:ae3aa141e3fa)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52133Sab196087 * Common Development and Distribution License (the "License").
62133Sab196087 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
216158Sbholler
220Sstevel@tonic-gate/*
236158Sbholler * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
246158Sbholler * Use is subject to license terms.
250Sstevel@tonic-gate */
266158Sbholler
270Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate#if	defined(lint)
300Sstevel@tonic-gate
310Sstevel@tonic-gate#include	<sys/types.h>
320Sstevel@tonic-gate#include	<_rtld.h>
330Sstevel@tonic-gate#include	<_audit.h>
340Sstevel@tonic-gate#include	<_elf.h>
350Sstevel@tonic-gate#include	<sys/regset.h>
360Sstevel@tonic-gate
370Sstevel@tonic-gate/* ARGSUSED0 */
380Sstevel@tonic-gateint
390Sstevel@tonic-gateelf_plt_trace()
400Sstevel@tonic-gate{
410Sstevel@tonic-gate	return (0);
420Sstevel@tonic-gate}
430Sstevel@tonic-gate#else
440Sstevel@tonic-gate
450Sstevel@tonic-gate#include	<link.h>
460Sstevel@tonic-gate#include	<_audit.h>
470Sstevel@tonic-gate#include	<sys/asm_linkage.h>
480Sstevel@tonic-gate
490Sstevel@tonic-gate	.file	"boot_elf.s"
500Sstevel@tonic-gate	.text
510Sstevel@tonic-gate
520Sstevel@tonic-gate/*
530Sstevel@tonic-gate * On entry the 'glue code' has already  done the following:
540Sstevel@tonic-gate *
550Sstevel@tonic-gate *	pushq	%rbp
560Sstevel@tonic-gate *	movq	%rsp, %rbp
570Sstevel@tonic-gate *	subq	$0x10, %rsp
580Sstevel@tonic-gate *	leaq	trace_fields(%rip), %r11
590Sstevel@tonic-gate *	movq	%r11, -0x8(%rbp)
600Sstevel@tonic-gate *	movq	$elf_plt_trace, %r11
610Sstevel@tonic-gate *	jmp	*%r11
620Sstevel@tonic-gate *
630Sstevel@tonic-gate * so - -8(%rbp) contains the dyndata ptr
640Sstevel@tonic-gate *
650Sstevel@tonic-gate *	0x0	Addr		*reflmp
660Sstevel@tonic-gate *	0x8	Addr		*deflmp
670Sstevel@tonic-gate *	0x10	Word		symndx
680Sstevel@tonic-gate *	0x14	Word		sb_flags
690Sstevel@tonic-gate *	0x18	Sym		symdef.st_name
700Sstevel@tonic-gate *	0x1c			symdef.st_info
710Sstevel@tonic-gate *	0x1d			symdef.st_other
720Sstevel@tonic-gate *	0x1e			symdef.st_shndx
730Sstevel@tonic-gate *	0x20			symdef.st_value
740Sstevel@tonic-gate *	0x28			symdef.st_size
750Sstevel@tonic-gate *
760Sstevel@tonic-gate * Also note - on entry 16 bytes have already been subtracted
770Sstevel@tonic-gate * from the %rsp.  The first 8 bytes is for the dyn_data_ptr,
780Sstevel@tonic-gate * the second 8 bytes are to align the stack and are available
790Sstevel@tonic-gate * for use.
800Sstevel@tonic-gate */
810Sstevel@tonic-gate#define	REFLMP_OFF		0x0
820Sstevel@tonic-gate#define	DEFLMP_OFF		0x8
830Sstevel@tonic-gate#define	SYMNDX_OFF		0x10
840Sstevel@tonic-gate#define	SBFLAGS_OFF		0x14
850Sstevel@tonic-gate#define	SYMDEF_OFF		0x18
860Sstevel@tonic-gate#define	SYMDEF_VALUE_OFF	0x20
870Sstevel@tonic-gate/*
880Sstevel@tonic-gate * Local stack space storage for elf_plt_trace is allocated
890Sstevel@tonic-gate * as follows:
900Sstevel@tonic-gate *
910Sstevel@tonic-gate *  First - before we got here - %rsp has been decremented
920Sstevel@tonic-gate *  by 0x10 to make space for the dyndata ptr (and another
930Sstevel@tonic-gate *  free word).  In addition to that, we create space
940Sstevel@tonic-gate *  for the following:
950Sstevel@tonic-gate *
960Sstevel@tonic-gate *	La_amd64_regs	    8 * 8:	64
970Sstevel@tonic-gate *	prev_stack_size	    8		 8
980Sstevel@tonic-gate *	Saved regs:
990Sstevel@tonic-gate *	    %rdi			 8
1000Sstevel@tonic-gate *	    %rsi			 8
1010Sstevel@tonic-gate *	    %rdx			 8
1020Sstevel@tonic-gate *	    %rcx			 8
1030Sstevel@tonic-gate *	    %r8				 8
1040Sstevel@tonic-gate *	    %r9				 8
1050Sstevel@tonic-gate *	    %r10			 8
1060Sstevel@tonic-gate *	    %r11			 8
1070Sstevel@tonic-gate *	    %rax			 8
1080Sstevel@tonic-gate *				    =======
1092133Sab196087 *			    Subtotal:	144 (16byte aligned)
1102133Sab196087 *
1112133Sab196087 *	Saved Media Regs (used to pass floating point args):
1122133Sab196087 *	    %xmm0 - %xmm7   16 * 8:	128
1132133Sab196087 *				    =======
1142133Sab196087 *			    Total:	272 (16byte aligned)
1150Sstevel@tonic-gate *
1160Sstevel@tonic-gate *  So - will subtract the following to create enough space
1170Sstevel@tonic-gate *
1180Sstevel@tonic-gate *	-8(%rbp)	store dyndata ptr
1190Sstevel@tonic-gate *	-16(%rbp)	store call destination
1200Sstevel@tonic-gate *	-80(%rbp)	space for La_amd64_regs
1210Sstevel@tonic-gate *	-88(%rbp)	prev stack size
122*6186Sbholler *  The next %rbp offsets are only true if the caller had correct stack
123*6186Sbholler *  alignment.  See note above SPRDIOFF for why we use %rsp alignment to
124*6186Sbholler *  access these stack fields.
1250Sstevel@tonic-gate *	-96(%rbp)	entering %rdi
1260Sstevel@tonic-gate *	-104(%rbp)	entering %rsi
1270Sstevel@tonic-gate *	-112(%rbp)	entering %rdx
1280Sstevel@tonic-gate *	-120(%rbp)	entering %rcx
1290Sstevel@tonic-gate *	-128(%rbp)	entering %r8
1300Sstevel@tonic-gate *	-136(%rbp)	entering %r9
1310Sstevel@tonic-gate *	-144(%rbp)	entering %r10
1320Sstevel@tonic-gate *	-152(%rbp)	entering %r11
133*6186Sbholler *	-160(%rbp)	entering %rax
134*6186Sbholler *	-176(%rbp)	entering %xmm0
135*6186Sbholler *	-192(%rbp)	entering %xmm1
136*6186Sbholler *	-208(%rbp)	entering %xmm2
137*6186Sbholler *	-224(%rbp)	entering %xmm3
138*6186Sbholler *	-240(%rbp)	entering %xmm4
139*6186Sbholler *	-256(%rbp)	entering %xmm5
140*6186Sbholler *	-272(%rbp)	entering %xmm6
141*6186Sbholler *	-288(%rbp)	entering %xmm7
1420Sstevel@tonic-gate *
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate#define	SPDYNOFF    -8
1450Sstevel@tonic-gate#define	SPDESTOFF   -16
1460Sstevel@tonic-gate#define	SPLAREGOFF  -80
1470Sstevel@tonic-gate#define	SPPRVSTKOFF -88
148*6186Sbholler
149*6186Sbholler/*
150*6186Sbholler * The next set of offsets are relative to %rsp.
151*6186Sbholler * We guarantee %rsp is ABI compliant 16-byte aligned.  This guarantees the
152*6186Sbholler * xmm registers are saved to 16-byte aligned addresses.
153*6186Sbholler * %rbp may only be 8 byte aligned if we came in from non-ABI compliant code.
154*6186Sbholler */
155*6186Sbholler#define	SPRDIOFF	192
156*6186Sbholler#define	SPRSIOFF	184
157*6186Sbholler#define	SPRDXOFF	176
158*6186Sbholler#define	SPRCXOFF	168
159*6186Sbholler#define	SPR8OFF		160
160*6186Sbholler#define	SPR9OFF		152
161*6186Sbholler#define	SPR10OFF	144
162*6186Sbholler#define	SPR11OFF	136
163*6186Sbholler#define	SPRAXOFF	128
164*6186Sbholler#define	SPXMM0OFF	112
165*6186Sbholler#define	SPXMM1OFF	96
166*6186Sbholler#define	SPXMM2OFF	80
167*6186Sbholler#define	SPXMM3OFF	64
168*6186Sbholler#define	SPXMM4OFF	48
169*6186Sbholler#define	SPXMM5OFF	32
170*6186Sbholler#define	SPXMM6OFF	16
171*6186Sbholler#define	SPXMM7OFF	0
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate	.globl	elf_plt_trace
1740Sstevel@tonic-gate	.type	elf_plt_trace,@function
1750Sstevel@tonic-gate	.align 16
1760Sstevel@tonic-gateelf_plt_trace:
177*6186Sbholler	/*
178*6186Sbholler	 * Enforce ABI 16-byte stack alignment here.
179*6186Sbholler	 * The next andq instruction does this pseudo code:
180*6186Sbholler	 * If %rsp is 8 byte aligned then subtract 8 from %rsp.
181*6186Sbholler	 */
182*6186Sbholler	andq    $-16, %rsp	/* enforce ABI 16-byte stack alignment */
1832133Sab196087	subq	$272,%rsp	/ create some local storage
184*6186Sbholler
185*6186Sbholler	movq	%rdi, SPRDIOFF(%rsp)
186*6186Sbholler	movq	%rsi, SPRSIOFF(%rsp)
187*6186Sbholler	movq	%rdx, SPRDXOFF(%rsp)
188*6186Sbholler	movq	%rcx, SPRCXOFF(%rsp)
189*6186Sbholler	movq	%r8, SPR8OFF(%rsp)
190*6186Sbholler	movq	%r9, SPR9OFF(%rsp)
191*6186Sbholler	movq	%r10, SPR10OFF(%rsp)
192*6186Sbholler	movq	%r11, SPR11OFF(%rsp)
193*6186Sbholler	movq	%rax, SPRAXOFF(%rsp)
194*6186Sbholler	movdqa	%xmm0, SPXMM0OFF(%rsp)
195*6186Sbholler	movdqa	%xmm1, SPXMM1OFF(%rsp)
196*6186Sbholler	movdqa	%xmm2, SPXMM2OFF(%rsp)
197*6186Sbholler	movdqa	%xmm3, SPXMM3OFF(%rsp)
198*6186Sbholler	movdqa	%xmm4, SPXMM4OFF(%rsp)
199*6186Sbholler	movdqa	%xmm5, SPXMM5OFF(%rsp)
200*6186Sbholler	movdqa	%xmm6, SPXMM6OFF(%rsp)
201*6186Sbholler	movdqa	%xmm7, SPXMM7OFF(%rsp)
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate	movq	SPDYNOFF(%rbp), %rax			/ %rax = dyndata
2040Sstevel@tonic-gate	testb	$LA_SYMB_NOPLTENTER, SBFLAGS_OFF(%rax)	/ <link.h>
2050Sstevel@tonic-gate	je	.start_pltenter
2060Sstevel@tonic-gate	movq	SYMDEF_VALUE_OFF(%rax), %rdi
2070Sstevel@tonic-gate	movq	%rdi, SPDESTOFF(%rbp)		/ save destination address
2080Sstevel@tonic-gate	jmp	.end_pltenter
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate.start_pltenter:
2110Sstevel@tonic-gate	/*
2120Sstevel@tonic-gate	 * save all registers into La_amd64_regs
2130Sstevel@tonic-gate	 */
2140Sstevel@tonic-gate	leaq	SPLAREGOFF(%rbp), %rsi	/ %rsi = &La_amd64_regs
2150Sstevel@tonic-gate	leaq	8(%rbp), %rdi
2160Sstevel@tonic-gate	movq	%rdi, 0(%rsi)		/ la_rsp
2170Sstevel@tonic-gate	movq	0(%rbp), %rdi
2180Sstevel@tonic-gate	movq	%rdi, 8(%rsi)		/ la_rbp
219*6186Sbholler	movq	SPRDIOFF(%rsp), %rdi
2200Sstevel@tonic-gate	movq	%rdi, 16(%rsi)		/ la_rdi
221*6186Sbholler	movq	SPRSIOFF(%rsp), %rdi
2220Sstevel@tonic-gate	movq	%rdi, 24(%rsi)		/ la_rsi
223*6186Sbholler	movq	SPRDXOFF(%rsp), %rdi
2240Sstevel@tonic-gate	movq	%rdi, 32(%rsi)		/ la_rdx
225*6186Sbholler	movq	SPRCXOFF(%rsp), %rdi
2260Sstevel@tonic-gate	movq	%rdi, 40(%rsi)		/ la_rcx
227*6186Sbholler	movq	SPR8OFF(%rsp), %rdi
2280Sstevel@tonic-gate	movq	%rdi, 48(%rsi)		/ la_r8
229*6186Sbholler	movq	SPR9OFF(%rsp), %rdi
2300Sstevel@tonic-gate	movq	%rdi, 56(%rsi)		/ la_r9
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate	/*
2330Sstevel@tonic-gate	 * prepare for call to la_pltenter
2340Sstevel@tonic-gate	 */
2350Sstevel@tonic-gate	movq	SPDYNOFF(%rbp), %r11		/ %r11 = &dyndata
2360Sstevel@tonic-gate	leaq	SBFLAGS_OFF(%r11), %r9		/ arg6 (&sb_flags)
2370Sstevel@tonic-gate	leaq	SPLAREGOFF(%rbp), %r8		/ arg5 (&La_amd64_regs)
2380Sstevel@tonic-gate	movl	SYMNDX_OFF(%r11), %ecx		/ arg4 (symndx)
2390Sstevel@tonic-gate	leaq	SYMDEF_OFF(%r11), %rdx		/ arg3 (&Sym)
2400Sstevel@tonic-gate	movq	DEFLMP_OFF(%r11), %rsi		/ arg2 (dlmp)
2410Sstevel@tonic-gate	movq	REFLMP_OFF(%r11), %rdi		/ arg1 (rlmp)
2420Sstevel@tonic-gate	call	audit_pltenter@PLT
2430Sstevel@tonic-gate	movq	%rax, SPDESTOFF(%rbp)		/ save calling address
2440Sstevel@tonic-gate.end_pltenter:
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate	/*
2470Sstevel@tonic-gate	 * If *no* la_pltexit() routines exist
2480Sstevel@tonic-gate	 * we do not need to keep the stack frame
2490Sstevel@tonic-gate	 * before we call the actual routine.  Instead we
2500Sstevel@tonic-gate	 * jump to it and remove our stack from the stack
2510Sstevel@tonic-gate	 * at the same time.
2520Sstevel@tonic-gate	 */
2530Sstevel@tonic-gate	movl	audit_flags(%rip), %eax
2540Sstevel@tonic-gate	andl	$AF_PLTEXIT, %eax		/ value of audit.h:AF_PLTEXIT
2550Sstevel@tonic-gate	cmpl	$0, %eax
2560Sstevel@tonic-gate	je	.bypass_pltexit
2570Sstevel@tonic-gate	/*
2580Sstevel@tonic-gate	 * Has the *nopltexit* flag been set for this entry point
2590Sstevel@tonic-gate	 */
2600Sstevel@tonic-gate	movq	SPDYNOFF(%rbp), %r11		/ %r11 = &dyndata
2610Sstevel@tonic-gate	testb	$LA_SYMB_NOPLTEXIT, SBFLAGS_OFF(%r11)
2620Sstevel@tonic-gate	je	.start_pltexit
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate.bypass_pltexit:
2650Sstevel@tonic-gate	/*
2660Sstevel@tonic-gate	 * No PLTEXIT processing required.
2670Sstevel@tonic-gate	 */
2680Sstevel@tonic-gate	movq	0(%rbp), %r11
2690Sstevel@tonic-gate	movq	%r11, -8(%rbp)			/ move prev %rbp
2700Sstevel@tonic-gate	movq	SPDESTOFF(%rbp), %r11		/ r11 == calling destination
2710Sstevel@tonic-gate	movq	%r11, 0(%rbp)			/ store destination at top
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate	/
2740Sstevel@tonic-gate	/ Restore registers
2750Sstevel@tonic-gate	/
276*6186Sbholler	movq	SPRDIOFF(%rsp), %rdi
277*6186Sbholler	movq	SPRSIOFF(%rsp), %rsi
278*6186Sbholler	movq	SPRDXOFF(%rsp), %rdx
279*6186Sbholler	movq	SPRCXOFF(%rsp), %rcx
280*6186Sbholler	movq	SPR8OFF(%rsp), %r8
281*6186Sbholler	movq	SPR9OFF(%rsp), %r9
282*6186Sbholler	movq	SPR10OFF(%rsp), %r10
283*6186Sbholler	movq	SPR11OFF(%rsp), %r11
284*6186Sbholler	movq	SPRAXOFF(%rsp), %rax
285*6186Sbholler	movdqa	SPXMM0OFF(%rsp), %xmm0
286*6186Sbholler	movdqa	SPXMM1OFF(%rsp), %xmm1
287*6186Sbholler	movdqa	SPXMM2OFF(%rsp), %xmm2
288*6186Sbholler	movdqa	SPXMM3OFF(%rsp), %xmm3
289*6186Sbholler	movdqa	SPXMM4OFF(%rsp), %xmm4
290*6186Sbholler	movdqa	SPXMM5OFF(%rsp), %xmm5
291*6186Sbholler	movdqa	SPXMM6OFF(%rsp), %xmm6
292*6186Sbholler	movdqa	SPXMM7OFF(%rsp), %xmm7
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate	subq	$8, %rbp			/ adjust %rbp for 'ret'
2950Sstevel@tonic-gate	movq	%rbp, %rsp			/
2960Sstevel@tonic-gate	/*
2970Sstevel@tonic-gate	 * At this point, after a little doctoring, we should
2980Sstevel@tonic-gate	 * have the following on the stack:
2990Sstevel@tonic-gate	 *
3000Sstevel@tonic-gate	 *	16(%rsp):  ret addr
3010Sstevel@tonic-gate	 *	8(%rsp):  dest_addr
3020Sstevel@tonic-gate	 *	0(%rsp):  Previous %rbp
3030Sstevel@tonic-gate	 *
3040Sstevel@tonic-gate	 * So - we pop the previous %rbp, and then
3050Sstevel@tonic-gate	 * ret to our final destination.
3060Sstevel@tonic-gate	 */
3070Sstevel@tonic-gate	popq	%rbp				/
3080Sstevel@tonic-gate	ret					/ jmp to final destination
3090Sstevel@tonic-gate						/ and clean up stack :)
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate.start_pltexit:
3120Sstevel@tonic-gate	/*
3130Sstevel@tonic-gate	 * In order to call the destination procedure and then return
3140Sstevel@tonic-gate	 * to audit_pltexit() for post analysis we must first grow
3150Sstevel@tonic-gate	 * our stack frame and then duplicate the original callers
3160Sstevel@tonic-gate	 * stack state.  This duplicates all of the arguements
3170Sstevel@tonic-gate	 * that were to be passed to the destination procedure.
3180Sstevel@tonic-gate	 */
3190Sstevel@tonic-gate	movq	%rbp, %rdi			/
3200Sstevel@tonic-gate	addq	$16, %rdi			/    %rdi = src
3210Sstevel@tonic-gate	movq	(%rbp), %rdx			/
3220Sstevel@tonic-gate	subq	%rdi, %rdx			/    %rdx == prev frame sz
3230Sstevel@tonic-gate	/*
3240Sstevel@tonic-gate	 * If audit_argcnt > 0 then we limit the number of
3250Sstevel@tonic-gate	 * arguements that will be duplicated to audit_argcnt.
3260Sstevel@tonic-gate	 *
3270Sstevel@tonic-gate	 * If (prev_stack_size > (audit_argcnt * 8))
3280Sstevel@tonic-gate	 *	prev_stack_size = audit_argcnt * 8;
3290Sstevel@tonic-gate	 */
3300Sstevel@tonic-gate	movl	audit_argcnt(%rip),%eax		/   %eax = audit_argcnt
3310Sstevel@tonic-gate	cmpl	$0, %eax
3320Sstevel@tonic-gate	jle	.grow_stack
3330Sstevel@tonic-gate	leaq	(,%rax,8), %rax			/    %eax = %eax * 4
3340Sstevel@tonic-gate	cmpq	%rax,%rdx
3350Sstevel@tonic-gate	jle	.grow_stack
3360Sstevel@tonic-gate	movq	%rax, %rdx
3370Sstevel@tonic-gate	/*
3380Sstevel@tonic-gate	 * Grow the stack and duplicate the arguements of the
3390Sstevel@tonic-gate	 * original caller.
340*6186Sbholler	 *
341*6186Sbholler	 * We save %rsp in %r11 since we need to use the current rsp for
342*6186Sbholler	 * accessing the registers saved in our stack frame.
3430Sstevel@tonic-gate	 */
3440Sstevel@tonic-gate.grow_stack:
345*6186Sbholler	movq	%rsp, %r11
3460Sstevel@tonic-gate	subq	%rdx, %rsp			/    grow the stack
3470Sstevel@tonic-gate	movq	%rdx, SPPRVSTKOFF(%rbp)		/    -88(%rbp) == prev frame sz
3480Sstevel@tonic-gate	movq	%rsp, %rcx			/    %rcx = dest
3490Sstevel@tonic-gate	addq	%rcx, %rdx			/    %rdx == tail of dest
3500Sstevel@tonic-gate.while_base:
3510Sstevel@tonic-gate	cmpq	%rdx, %rcx			/   while (base+size >= src++) {
3520Sstevel@tonic-gate	jge	.end_while			/
3530Sstevel@tonic-gate	movq	(%rdi), %rsi
3540Sstevel@tonic-gate	movq	%rsi,(%rcx)			/        *dest = *src
3550Sstevel@tonic-gate	addq	$8, %rdi			/	 src++
3560Sstevel@tonic-gate	addq	$8, %rcx			/        dest++
3570Sstevel@tonic-gate	jmp	.while_base			/    }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate	/*
3600Sstevel@tonic-gate	 * The above stack is now an exact duplicate of
3610Sstevel@tonic-gate	 * the stack of the original calling procedure.
3620Sstevel@tonic-gate	 */
3630Sstevel@tonic-gate.end_while:
3640Sstevel@tonic-gate	/
365*6186Sbholler	/ Restore registers using %r11 which contains our old %rsp value
366*6186Sbholler	/ before growing the stack.
3670Sstevel@tonic-gate	/
368*6186Sbholler	movq	SPRDIOFF(%r11), %rdi
369*6186Sbholler	movq	SPRSIOFF(%r11), %rsi
370*6186Sbholler	movq	SPRDXOFF(%r11), %rdx
371*6186Sbholler	movq	SPRCXOFF(%r11), %rcx
372*6186Sbholler	movq	SPR8OFF(%r11), %r8
373*6186Sbholler	movq	SPR9OFF(%r11), %r9
374*6186Sbholler	movq	SPR10OFF(%r11), %r10
375*6186Sbholler	movq	SPRAXOFF(%r11), %rax
376*6186Sbholler	movdqa	SPXMM0OFF(%r11), %xmm0
377*6186Sbholler	movdqa	SPXMM1OFF(%r11), %xmm1
378*6186Sbholler	movdqa	SPXMM2OFF(%r11), %xmm2
379*6186Sbholler	movdqa	SPXMM3OFF(%r11), %xmm3
380*6186Sbholler	movdqa	SPXMM4OFF(%r11), %xmm4
381*6186Sbholler	movdqa	SPXMM5OFF(%r11), %xmm5
382*6186Sbholler	movdqa	SPXMM6OFF(%r11), %xmm6
383*6186Sbholler	movdqa	SPXMM7OFF(%r11), %xmm7
384*6186Sbholler	movq	SPR11OFF(%r11), %r11		/ retore %r11 last
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate	/*
3870Sstevel@tonic-gate	 * Call to desitnation function - we'll return here
3880Sstevel@tonic-gate	 * for pltexit monitoring.
3890Sstevel@tonic-gate	 */
3900Sstevel@tonic-gate	call	*SPDESTOFF(%rbp)
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate	addq	SPPRVSTKOFF(%rbp), %rsp	/ cleanup dupped stack
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate	/
3950Sstevel@tonic-gate	/ prepare for call to audit_pltenter()
3960Sstevel@tonic-gate	/
3970Sstevel@tonic-gate	movq	SPDYNOFF(%rbp), %r11		/ %r11 = &dyndata
3980Sstevel@tonic-gate	movq	SYMNDX_OFF(%r11), %r8		/ arg5 (symndx)
3990Sstevel@tonic-gate	leaq	SYMDEF_OFF(%r11), %rcx		/ arg4 (&Sym)
4000Sstevel@tonic-gate	movq	DEFLMP_OFF(%r11), %rdx		/ arg3 (dlmp)
4010Sstevel@tonic-gate	movq	REFLMP_OFF(%r11), %rsi		/ arg2 (rlmp)
4020Sstevel@tonic-gate	movq	%rax, %rdi			/ arg1 (returnval)
4030Sstevel@tonic-gate	call	audit_pltexit@PLT
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate	/*
4060Sstevel@tonic-gate	 * Clean up after ourselves and return to the
4070Sstevel@tonic-gate	 * original calling procedure.
4080Sstevel@tonic-gate	 */
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate	/
4110Sstevel@tonic-gate	/ Restore registers
4120Sstevel@tonic-gate	/
413*6186Sbholler	movq	SPRDIOFF(%rsp), %rdi
414*6186Sbholler	movq	SPRSIOFF(%rsp), %rsi
415*6186Sbholler	movq	SPRDXOFF(%rsp), %rdx
416*6186Sbholler	movq	SPRCXOFF(%rsp), %rcx
417*6186Sbholler	movq	SPR8OFF(%rsp), %r8
418*6186Sbholler	movq	SPR9OFF(%rsp), %r9
419*6186Sbholler	movq	SPR10OFF(%rsp), %r10
420*6186Sbholler	movq	SPR11OFF(%rsp), %r11
4210Sstevel@tonic-gate	// rax already contains return value
422*6186Sbholler	movdqa	SPXMM0OFF(%rsp), %xmm0
423*6186Sbholler	movdqa	SPXMM1OFF(%rsp), %xmm1
424*6186Sbholler	movdqa	SPXMM2OFF(%rsp), %xmm2
425*6186Sbholler	movdqa	SPXMM3OFF(%rsp), %xmm3
426*6186Sbholler	movdqa	SPXMM4OFF(%rsp), %xmm4
427*6186Sbholler	movdqa	SPXMM5OFF(%rsp), %xmm5
428*6186Sbholler	movdqa	SPXMM6OFF(%rsp), %xmm6
429*6186Sbholler	movdqa	SPXMM7OFF(%rsp), %xmm7
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate	movq	%rbp, %rsp			/
4320Sstevel@tonic-gate	popq	%rbp				/
4330Sstevel@tonic-gate	ret					/ return to caller
4340Sstevel@tonic-gate	.size	elf_plt_trace, .-elf_plt_trace
4350Sstevel@tonic-gate#endif
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate/*
4380Sstevel@tonic-gate * We got here because a call to a function resolved to a procedure
4390Sstevel@tonic-gate * linkage table entry.  That entry did a JMPL to the first PLT entry, which
4400Sstevel@tonic-gate * in turn did a call to elf_rtbndr.
4410Sstevel@tonic-gate *
4420Sstevel@tonic-gate * the code sequence that got us here was:
4430Sstevel@tonic-gate *
4440Sstevel@tonic-gate * .PLT0:
4450Sstevel@tonic-gate *	pushq	GOT+8(%rip)	#GOT[1]
4460Sstevel@tonic-gate *	jmp	*GOT+16(%rip)	#GOT[2]
4470Sstevel@tonic-gate *	nop
4480Sstevel@tonic-gate *	nop
4490Sstevel@tonic-gate *	nop
4500Sstevel@tonic-gate *	nop
4510Sstevel@tonic-gate *	...
4520Sstevel@tonic-gate * PLT entry for foo:
4530Sstevel@tonic-gate *	jmp	*name1@GOTPCREL(%rip)
4540Sstevel@tonic-gate *	pushl	$rel.plt.foo
4550Sstevel@tonic-gate *	jmp	PLT0
4560Sstevel@tonic-gate *
4570Sstevel@tonic-gate * At entry, the stack looks like this:
4580Sstevel@tonic-gate *
4590Sstevel@tonic-gate *	return address			16(%rsp)
4600Sstevel@tonic-gate *	$rel.plt.foo	(plt index)	8(%rsp)
4610Sstevel@tonic-gate *	lmp				0(%rsp)
4620Sstevel@tonic-gate *
4630Sstevel@tonic-gate */
4640Sstevel@tonic-gate#if defined(lint)
4650Sstevel@tonic-gate
4660Sstevel@tonic-gateextern unsigned long	elf_bndr(Rt_map *, unsigned long, caddr_t);
4670Sstevel@tonic-gate
4680Sstevel@tonic-gatevoid
4690Sstevel@tonic-gateelf_rtbndr(Rt_map * lmp, unsigned long reloc, caddr_t pc)
4700Sstevel@tonic-gate{
4710Sstevel@tonic-gate	(void) elf_bndr(lmp, reloc, pc);
4720Sstevel@tonic-gate}
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate#else
4756158Sbholler
4766158Sbholler/*
4776158Sbholler * The PLT code that landed us here placed 2 arguments on the stack as
4786158Sbholler * arguments to elf_rtbndr.
4796158Sbholler * Additionally the pc of caller is below these 2 args.
4806158Sbholler * Our stack will look like this after we establish a stack frame with
4816158Sbholler * push %rbp; movq %rsp, %rbp sequence:
4826158Sbholler *
4836158Sbholler *	8(%rbp)			arg1 - *lmp
4846158Sbholler *	16(%rbp), %rsi		arg2 - reloc index
4856158Sbholler *	24(%rbp), %rdx		arg3 - pc of caller
4866158Sbholler */
4876158Sbholler#define	LBPLMPOFF	8	/* arg1 - *lmp */
4886158Sbholler#define	LBPRELOCOFF	16	/* arg2 - reloc index */
4896158Sbholler#define	LBRPCOFF	24	/* arg3 - pc of caller */
4906158Sbholler
4916158Sbholler/*
4926158Sbholler * Possible arguments for the resolved function are in registers as per
4936158Sbholler * the AMD64 ABI.  We must save on the local stack all possible register
4946158Sbholler * arguments before interposing functions to resolve the called function.
4956158Sbholler * Possible arguments must be restored before invoking the resolved function.
4966158Sbholler *
4976158Sbholler * Local stack space storage for elf_rtbndr is allocated as follows:
4986158Sbholler *
4996158Sbholler *	Saved regs:
5006158Sbholler *	    %rax			 8
5016158Sbholler *	    %rdi			 8
5026158Sbholler *	    %rsi			 8
5036158Sbholler *	    %rdx			 8
5046158Sbholler *	    %rcx			 8
5056158Sbholler *	    %r8				 8
5066158Sbholler *	    %r9				 8
5076158Sbholler *	    %r10			 8
5086158Sbholler *				    =======
5096158Sbholler *			    Subtotal:   64 (16byte aligned)
5106158Sbholler *
5116158Sbholler *	Saved Media Regs (used to pass floating point args):
5126158Sbholler *	    %xmm0 - %xmm7   16 * 8:    128
5136158Sbholler *				    =======
5146158Sbholler *			    Total:     192 (16byte aligned)
5156158Sbholler *
5166158Sbholler *  So - will subtract the following to create enough space
5176158Sbholler *
518*6186Sbholler *	0(%rsp)		save %rax
519*6186Sbholler *	8(%rsp)		save %rdi
520*6186Sbholler *	16(%rsp)	save %rsi
521*6186Sbholler *	24(%rsp)	save %rdx
522*6186Sbholler *	32(%rsp)	save %rcx
523*6186Sbholler *	40(%rsp)	save %r8
524*6186Sbholler *	48(%rsp)	save %r9
525*6186Sbholler *	56(%rsp)	save %r10
526*6186Sbholler *	64(%rsp)	save %xmm0
527*6186Sbholler *	80(%rsp)	save %xmm1
528*6186Sbholler *	96(%rsp)	save %xmm2
529*6186Sbholler *	112(%rsp)	save %xmm3
530*6186Sbholler *	128(%rsp)	save %xmm4
531*6186Sbholler *	144(%rsp)	save %xmm5
532*6186Sbholler *	160(%rsp)	save %xmm6
533*6186Sbholler *	176(%rsp)	save %xmm7
534*6186Sbholler *
535*6186Sbholler * Note: Some callers may use 8-byte stack alignment instead of the
536*6186Sbholler * ABI required 16-byte alignment.  We use %rsp offsets to save/restore
537*6186Sbholler * registers because %rbp may not be 16-byte aligned.  We guarantee %rsp
538*6186Sbholler * is 16-byte aligned in the function preamble.
5396158Sbholler */
5406158Sbholler#define	LS_SIZE	$192	/* local stack space to save all possible arguments */
541*6186Sbholler#define	LSRAXOFF	0	/* for SSE register count */
542*6186Sbholler#define	LSRDIOFF	8	/* arg 0 ... */
543*6186Sbholler#define	LSRSIOFF	16
544*6186Sbholler#define	LSRDXOFF	24
545*6186Sbholler#define	LSRCXOFF	32
546*6186Sbholler#define	LSR8OFF		40
547*6186Sbholler#define	LSR9OFF		48
548*6186Sbholler#define	LSR10OFF	56	/* ... arg 5 */
549*6186Sbholler#define	LSXMM0OFF	64	/* SSE arg 0 ... */
550*6186Sbholler#define	LSXMM1OFF	80
551*6186Sbholler#define	LSXMM2OFF	96
552*6186Sbholler#define	LSXMM3OFF	112
553*6186Sbholler#define	LSXMM4OFF	128
554*6186Sbholler#define	LSXMM5OFF	144
555*6186Sbholler#define	LSXMM6OFF	160
556*6186Sbholler#define	LSXMM7OFF	176	/* ... SSE arg 7 */
5576158Sbholler
5580Sstevel@tonic-gate	.weak	_elf_rtbndr
5590Sstevel@tonic-gate	_elf_rtbndr = elf_rtbndr
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate	ENTRY(elf_rtbndr)
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate	pushq	%rbp
5640Sstevel@tonic-gate	movq	%rsp, %rbp
5650Sstevel@tonic-gate
566*6186Sbholler	/*
567*6186Sbholler	 * Some libraries may (incorrectly) use non-ABI compliant 8-byte stack
568*6186Sbholler	 * alignment.  Enforce ABI 16-byte stack alignment here.
569*6186Sbholler	 * The next andq instruction does this pseudo code:
570*6186Sbholler	 * If %rsp is 8 byte aligned then subtract 8 from %rsp.
571*6186Sbholler	 */
572*6186Sbholler	andq	$-16, %rsp	/* enforce ABI 16-byte stack alignment */
573*6186Sbholler
5746158Sbholler	subq	LS_SIZE, %rsp	/* save all ABI defined argument registers */
5756158Sbholler
576*6186Sbholler	movq	%rax, LSRAXOFF(%rsp)	/* for SSE register count */
577*6186Sbholler	movq	%rdi, LSRDIOFF(%rsp)	/*  arg 0 .. */
578*6186Sbholler	movq	%rsi, LSRSIOFF(%rsp)
579*6186Sbholler	movq	%rdx, LSRDXOFF(%rsp)
580*6186Sbholler	movq	%rcx, LSRCXOFF(%rsp)
581*6186Sbholler	movq	%r8, LSR8OFF(%rsp)
582*6186Sbholler	movq	%r9, LSR9OFF(%rsp)	/* .. arg 5 */
583*6186Sbholler	movq	%r10, LSR10OFF(%rsp)	/* call chain reg */
5846158Sbholler
585*6186Sbholler	movdqa	%xmm0, LSXMM0OFF(%rsp)	/* SSE arg 0 ... */
586*6186Sbholler	movdqa	%xmm1, LSXMM1OFF(%rsp)
587*6186Sbholler	movdqa	%xmm2, LSXMM2OFF(%rsp)
588*6186Sbholler	movdqa	%xmm3, LSXMM3OFF(%rsp)
589*6186Sbholler	movdqa	%xmm4, LSXMM4OFF(%rsp)
590*6186Sbholler	movdqa	%xmm5, LSXMM5OFF(%rsp)
591*6186Sbholler	movdqa	%xmm6, LSXMM6OFF(%rsp)
592*6186Sbholler	movdqa	%xmm7, LSXMM7OFF(%rsp)	/* ... SSE arg 7 */
5930Sstevel@tonic-gate
5946158Sbholler	movq	LBPLMPOFF(%rbp), %rdi	/* arg1 - *lmp */
5956158Sbholler	movq	LBPRELOCOFF(%rbp), %rsi	/* arg2 - reloc index */
5966158Sbholler	movq	LBRPCOFF(%rbp), %rdx	/* arg3 - pc of caller */
5976158Sbholler	call	elf_bndr@PLT		/* call elf_rtbndr(lmp, relndx, pc) */
5986158Sbholler	movq	%rax, LBPRELOCOFF(%rbp)	/* store final destination */
5990Sstevel@tonic-gate
6006158Sbholler	/* restore possible arguments before invoking resolved function */
601*6186Sbholler	movq	LSRAXOFF(%rsp), %rax
602*6186Sbholler	movq	LSRDIOFF(%rsp), %rdi
603*6186Sbholler	movq	LSRSIOFF(%rsp), %rsi
604*6186Sbholler	movq	LSRDXOFF(%rsp), %rdx
605*6186Sbholler	movq	LSRCXOFF(%rsp), %rcx
606*6186Sbholler	movq	LSR8OFF(%rsp), %r8
607*6186Sbholler	movq	LSR9OFF(%rsp), %r9
608*6186Sbholler	movq	LSR10OFF(%rsp), %r10
6096158Sbholler
610*6186Sbholler	movdqa	LSXMM0OFF(%rsp), %xmm0
611*6186Sbholler	movdqa	LSXMM1OFF(%rsp), %xmm1
612*6186Sbholler	movdqa	LSXMM2OFF(%rsp), %xmm2
613*6186Sbholler	movdqa	LSXMM3OFF(%rsp), %xmm3
614*6186Sbholler	movdqa	LSXMM4OFF(%rsp), %xmm4
615*6186Sbholler	movdqa	LSXMM5OFF(%rsp), %xmm5
616*6186Sbholler	movdqa	LSXMM6OFF(%rsp), %xmm6
617*6186Sbholler	movdqa	LSXMM7OFF(%rsp), %xmm7
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate	movq	%rbp, %rsp
6200Sstevel@tonic-gate	popq	%rbp
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate	addq	$8, %rsp	/* pop 1st plt-pushed args */
6230Sstevel@tonic-gate				/* the second arguement is used */
6240Sstevel@tonic-gate				/* for the 'return' address to our */
6250Sstevel@tonic-gate				/* final destination */
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate	ret			/* invoke resolved function */
6280Sstevel@tonic-gate	.size 	elf_rtbndr, .-elf_rtbndr
6290Sstevel@tonic-gate#endif
630