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