boot_elf.s revision 33b4ce79552fff296683103b596e95c150930f5f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#if defined(lint)
#include <_rtld.h>
#include <_audit.h>
#include <_elf.h>
/* ARGSUSED0 */
int
{
return (0);
}
#else
#include <link.h>
#include <_audit.h>
#include <sys/asm_linkage.h>
.file "boot_elf.s"
.text
/*
* On entry the 'glue code' has already done the following:
*
* pushq %rbp
* movq %rsp, %rbp
* subq $0x10, %rsp
* leaq trace_fields(%rip), %r11
* movq %r11, -0x8(%rbp)
* movq $elf_plt_trace, %r11
* jmp *%r11
*
* so - -8(%rbp) contains the dyndata ptr
*
* 0x0 Addr *reflmp
* 0x8 Addr *deflmp
* 0x10 Word symndx
* 0x14 Word sb_flags
* 0x18 Sym symdef.st_name
* 0x1c symdef.st_info
* 0x1d symdef.st_other
* 0x1e symdef.st_shndx
* 0x20 symdef.st_value
* 0x28 symdef.st_size
*
* Also note - on entry 16 bytes have already been subtracted
* from the %rsp. The first 8 bytes is for the dyn_data_ptr,
* the second 8 bytes are to align the stack and are available
* for use.
*/
#define REFLMP_OFF 0x0
#define DEFLMP_OFF 0x8
#define SYMNDX_OFF 0x10
#define SBFLAGS_OFF 0x14
#define SYMDEF_OFF 0x18
#define SYMDEF_VALUE_OFF 0x20
/*
* Local stack space storage for elf_plt_trace is allocated
* as follows:
*
* First - before we got here - %rsp has been decremented
* by 0x10 to make space for the dyndata ptr (and another
* free word). In addition to that, we create space
* for the following:
*
* La_amd64_regs 8 * 8: 64
* prev_stack_size 8 8
* Saved regs:
* %rdi 8
* %rsi 8
* %rdx 8
* %rcx 8
* %r8 8
* %r9 8
* %r10 8
* %r11 8
* %rax 8
* =======
* Subtotal: 144 (16byte aligned)
*
* Saved Media Regs (used to pass floating point args):
* %xmm0 - %xmm7 16 * 8: 128
* =======
* Total: 272 (16byte aligned)
*
* So - will subtract the following to create enough space
*
* -8(%rbp) store dyndata ptr
* -16(%rbp) store call destination
* -80(%rbp) space for La_amd64_regs
* -88(%rbp) prev stack size
* -96(%rbp) entering %rdi
* -104(%rbp) entering %rsi
* -112(%rbp) entering %rdx
* -120(%rbp) entering %rcx
* -128(%rbp) entering %r8
* -136(%rbp) entering %r9
* -144(%rbp) entering %r10
* -152(%rbp) entering %r11
* -160(%rax) entering %rax
* -176(%xmm0) entering %xmm0
* -192(%xmm1) entering %xmm1
* -208(%xmm2) entering %xmm2
* -224(%xmm3) entering %xmm3
* -240(%xmm4) entering %xmm4
* -256(%xmm5) entering %xmm5
* -272(%xmm6) entering %xmm6
* -288(%xmm7) entering %xmm7
*
*/
#define SPDYNOFF -8
#define SPDESTOFF -16
#define SPLAREGOFF -80
#define SPPRVSTKOFF -88
#define SPRDIOFF -96
#define SPRSIOFF -104
#define SPRDXOFF -112
#define SPRCXOFF -120
#define SPR8OFF -128
#define SPR9OFF -136
#define SPR10OFF -144
#define SPR11OFF -152
#define SPRAXOFF -160
#define SPXMM0OFF -176
#define SPXMM1OFF -192
#define SPXMM2OFF -208
#define SPXMM3OFF -224
#define SPXMM4OFF -240
#define SPXMM5OFF -256
#define SPXMM6OFF -272
#define SPXMM7OFF -288
.align 16
/*
* save all registers into La_amd64_regs
*/
/*
* prepare for call to la_pltenter
*/
/*
* If *no* la_pltexit() routines exist
* we do not need to keep the stack frame
* before we call the actual routine. Instead we
* jump to it and remove our stack from the stack
* at the same time.
*/
/*
* Has the *nopltexit* flag been set for this entry point
*/
/*
* No PLTEXIT processing required.
*/
/
/
/*
* At this point, after a little doctoring, we should
* have the following on the stack:
*
* 16(%rsp): ret addr
* 8(%rsp): dest_addr
* 0(%rsp): Previous %rbp
*
* So - we pop the previous %rbp, and then
* ret to our final destination.
*/
/*
* In order to call the destination procedure and then return
* to audit_pltexit() for post analysis we must first grow
* our stack frame and then duplicate the original callers
* stack state. This duplicates all of the arguements
* that were to be passed to the destination procedure.
*/
/*
* If audit_argcnt > 0 then we limit the number of
* arguements that will be duplicated to audit_argcnt.
*
* If (prev_stack_size > (audit_argcnt * 8))
* prev_stack_size = audit_argcnt * 8;
*/
/*
* Grow the stack and duplicate the arguements of the
* original caller.
*/
jmp .while_base / }
/*
* The above stack is now an exact duplicate of
* the stack of the original calling procedure.
*/
/
/
/*
* Call to desitnation function - we'll return here
* for pltexit monitoring.
*/
/
/
/*
* Clean up after ourselves and return to the
* original calling procedure.
*/
/
/
// rax already contains return value
#endif
/*
* We got here because a call to a function resolved to a procedure
* linkage table entry. That entry did a JMPL to the first PLT entry, which
* in turn did a call to elf_rtbndr.
*
* the code sequence that got us here was:
*
* .PLT0:
* pushq GOT+8(%rip) #GOT[1]
* jmp *GOT+16(%rip) #GOT[2]
* nop
* nop
* nop
* nop
* ...
* PLT entry for foo:
* jmp *name1@GOTPCREL(%rip)
* pushl $rel.plt.foo
* jmp PLT0
*
* At entry, the stack looks like this:
*
* return address 16(%rsp)
* $rel.plt.foo (plt index) 8(%rsp)
* lmp 0(%rsp)
*
*/
#if defined(lint)
void
{
}
#else
/* the second arguement is used */
/* for the 'return' address to our */
/* final destination */
ret /* invoke resolved function */
#endif