1*0Sstevel@tonic-gate/* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate/* 23*0Sstevel@tonic-gate * Copyright (c) 1988 AT&T 24*0Sstevel@tonic-gate * All Rights Reserved 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * 27*0Sstevel@tonic-gate * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. 28*0Sstevel@tonic-gate * Use is subject to license terms. 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate#pragma ident "%Z%%M% %I% %E% SMI" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate#if defined(lint) 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate#include <sys/types.h> 35*0Sstevel@tonic-gate#include "_rtld.h" 36*0Sstevel@tonic-gate#include "_audit.h" 37*0Sstevel@tonic-gate#include "_elf.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate/* ARGSUSED0 */ 40*0Sstevel@tonic-gateint 41*0Sstevel@tonic-gateelf_plt_trace() 42*0Sstevel@tonic-gate{ 43*0Sstevel@tonic-gate return (0); 44*0Sstevel@tonic-gate} 45*0Sstevel@tonic-gate#else 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate#include <link.h> 48*0Sstevel@tonic-gate#include "_audit.h" 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate .file "boot_elf.s" 51*0Sstevel@tonic-gate .text 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate/* 54*0Sstevel@tonic-gate * On entry the 'glue code' has already done the following: 55*0Sstevel@tonic-gate * 56*0Sstevel@tonic-gate * pushl %ebp 57*0Sstevel@tonic-gate * movl %esp, %ebp 58*0Sstevel@tonic-gate * pushl dyndata_ptr 59*0Sstevel@tonic-gate * jmp elf_plt_trace 60*0Sstevel@tonic-gate * 61*0Sstevel@tonic-gate * so - -4(%ebp) contains the dyndata ptr 62*0Sstevel@tonic-gate * 63*0Sstevel@tonic-gate * 0x0 uintptr_t reflmp 64*0Sstevel@tonic-gate * 0x4 uintptr_t deflmp 65*0Sstevel@tonic-gate * 0x8 ulong_t symndx 66*0Sstevel@tonic-gate * 0xc ulont_t sb_flags 67*0Sstevel@tonic-gate * 0x10 Elf32_Sym symdef.st_name 68*0Sstevel@tonic-gate * 0x14 symdef.st_value 69*0Sstevel@tonic-gate * 0x18 symdef.st_size 70*0Sstevel@tonic-gate * 0x1c symdef.st_info 71*0Sstevel@tonic-gate * 0x1d symdef.st_other 72*0Sstevel@tonic-gate * 0x1e symdef.st_shndx 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate#define REFLMP_OFF 0x0 75*0Sstevel@tonic-gate#define DEFLMP_OFF 0x4 76*0Sstevel@tonic-gate#define SYMNDX_OFF 0x8 77*0Sstevel@tonic-gate#define SBFLAGS_OFF 0xc 78*0Sstevel@tonic-gate#define SYMDEF_OFF 0x10 79*0Sstevel@tonic-gate#define SYMDEF_VALUE_OFF 0x14 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate .globl elf_plt_trace 82*0Sstevel@tonic-gate .type elf_plt_trace,@function 83*0Sstevel@tonic-gate .align 16 84*0Sstevel@tonic-gateelf_plt_trace: 85*0Sstevel@tonic-gate subl $84,%esp / create some local storage 86*0Sstevel@tonic-gate pushl %eax 87*0Sstevel@tonic-gate pushl %ebx 88*0Sstevel@tonic-gate pushl %edi 89*0Sstevel@tonic-gate pushl %esi 90*0Sstevel@tonic-gate call .L1 / initialize %ebx to GOT 91*0Sstevel@tonic-gate.L1: 92*0Sstevel@tonic-gate popl %ebx 93*0Sstevel@tonic-gate addl $_GLOBAL_OFFSET_TABLE_+[.-.L1], %ebx 94*0Sstevel@tonic-gate /* 95*0Sstevel@tonic-gate * Local stack space storage is allocated as follows: 96*0Sstevel@tonic-gate * 97*0Sstevel@tonic-gate * -4(%ebp) store dyndata ptr 98*0Sstevel@tonic-gate * -8(%ebp) store call destination 99*0Sstevel@tonic-gate * -84(%ebp) space for gregset 100*0Sstevel@tonic-gate * -88(%ebp) prev stack size 101*0Sstevel@tonic-gate * -92(%ebp) entering %eax 102*0Sstevel@tonic-gate * -96(%ebp) entering %ebx 103*0Sstevel@tonic-gate * -100(%ebp) entering %edi 104*0Sstevel@tonic-gate * -104(%ebp) entering %esi 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate movl -4(%ebp), %eax / %eax = dyndata 107*0Sstevel@tonic-gate testb $LA_SYMB_NOPLTENTER, 0xc(%eax) / <link.h> 108*0Sstevel@tonic-gate je .start_pltenter 109*0Sstevel@tonic-gate movl SYMDEF_VALUE_OFF(%eax), %edi 110*0Sstevel@tonic-gate movl %edi, -8(%ebp) / save destination address 111*0Sstevel@tonic-gate jmp .end_pltenter 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate.start_pltenter: 114*0Sstevel@tonic-gate /* 115*0Sstevel@tonic-gate * save all registers into gregset_t 116*0Sstevel@tonic-gate */ 117*0Sstevel@tonic-gate lea 4(%ebp), %edi 118*0Sstevel@tonic-gate movl %edi, -84(%ebp) / %esp 119*0Sstevel@tonic-gate movl 0(%ebp), %edi 120*0Sstevel@tonic-gate movl %edi, -80(%ebp) / %ebp 121*0Sstevel@tonic-gate /* 122*0Sstevel@tonic-gate * trapno, err, eip, cs, efl, uesp, ss 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate movl -4(%ebp), %edi 125*0Sstevel@tonic-gate lea SBFLAGS_OFF(%edi), %eax 126*0Sstevel@tonic-gate pushl %eax / arg5 (&sb_flags) 127*0Sstevel@tonic-gate lea -84(%ebp), %eax 128*0Sstevel@tonic-gate pushl %eax / arg4 (regset) 129*0Sstevel@tonic-gate pushl SYMNDX_OFF(%edi) / arg3 (symndx) 130*0Sstevel@tonic-gate lea SYMDEF_OFF(%edi), %eax 131*0Sstevel@tonic-gate pushl %eax / arg2 (&sym) 132*0Sstevel@tonic-gate pushl DEFLMP_OFF(%edi) / arg1 (dlmp) 133*0Sstevel@tonic-gate pushl REFLMP_OFF(%edi) / arg0 (rlmp) 134*0Sstevel@tonic-gate call audit_pltenter@PLT 135*0Sstevel@tonic-gate addl $24, %esp / cleanup stack 136*0Sstevel@tonic-gate movl %eax, -8(%ebp) / save calling address 137*0Sstevel@tonic-gate.end_pltenter: 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate /* 140*0Sstevel@tonic-gate * If *no* la_pltexit() routines exist 141*0Sstevel@tonic-gate * we do not need to keep the stack frame 142*0Sstevel@tonic-gate * before we call the actual routine. Instead we 143*0Sstevel@tonic-gate * jump to it and remove our stack from the stack 144*0Sstevel@tonic-gate * at the same time. 145*0Sstevel@tonic-gate */ 146*0Sstevel@tonic-gate movl audit_flags@GOT(%ebx), %eax 147*0Sstevel@tonic-gate movl (%eax), %eax 148*0Sstevel@tonic-gate andl $AF_PLTEXIT, %eax / value of audit.h:AF_PLTEXIT 149*0Sstevel@tonic-gate cmpl $0, %eax 150*0Sstevel@tonic-gate je .bypass_pltexit 151*0Sstevel@tonic-gate /* 152*0Sstevel@tonic-gate * Has the *nopltexit* flag been set for this entry point 153*0Sstevel@tonic-gate */ 154*0Sstevel@tonic-gate testb $LA_SYMB_NOPLTEXIT, 12(%edi) 155*0Sstevel@tonic-gate je .start_pltexit 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate.bypass_pltexit: 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * No PLTEXIT processing required. 160*0Sstevel@tonic-gate */ 161*0Sstevel@tonic-gate movl 0(%ebp), %eax 162*0Sstevel@tonic-gate movl %eax, -4(%ebp) 163*0Sstevel@tonic-gate movl -8(%ebp), %eax / eax == calling destination 164*0Sstevel@tonic-gate movl %eax, 0(%ebp) / store destination at top 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate popl %esi / 167*0Sstevel@tonic-gate popl %edi / clean up stack 168*0Sstevel@tonic-gate popl %ebx / 169*0Sstevel@tonic-gate popl %eax / 170*0Sstevel@tonic-gate subl $4, %ebp / adjust %ebp for 'ret' 171*0Sstevel@tonic-gate /* 172*0Sstevel@tonic-gate * At this point, after a little doctoring, we should 173*0Sstevel@tonic-gate * have the following on the stack: 174*0Sstevel@tonic-gate * 175*0Sstevel@tonic-gate * 8(%esp): ret addr 176*0Sstevel@tonic-gate * 4(%esp): dest_addr 177*0Sstevel@tonic-gate * 0(%esp): Previous %ebp 178*0Sstevel@tonic-gate * 179*0Sstevel@tonic-gate * So - we pop the previous %ebp, and then 180*0Sstevel@tonic-gate * ret to our final destination. 181*0Sstevel@tonic-gate */ 182*0Sstevel@tonic-gate movl %ebp, %esp / 183*0Sstevel@tonic-gate popl %ebp / 184*0Sstevel@tonic-gate ret / jmp to final destination 185*0Sstevel@tonic-gate / and clean up stack :) 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate.start_pltexit: 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate /* 190*0Sstevel@tonic-gate * In order to call the destination procedure and then return 191*0Sstevel@tonic-gate * to audit_pltexit() for post analysis we must first grow 192*0Sstevel@tonic-gate * our stack frame and then duplicate the original callers 193*0Sstevel@tonic-gate * stack state. This duplicates all of the arguements 194*0Sstevel@tonic-gate * that were to be passed to the destination procedure. 195*0Sstevel@tonic-gate */ 196*0Sstevel@tonic-gate movl %ebp, %edi / 197*0Sstevel@tonic-gate addl $8, %edi / %edi = src 198*0Sstevel@tonic-gate movl (%ebp), %edx / 199*0Sstevel@tonic-gate subl %edi, %edx / %edx == prev frame sz 200*0Sstevel@tonic-gate /* 201*0Sstevel@tonic-gate * If audit_argcnt > 0 then we limit the number of 202*0Sstevel@tonic-gate * arguements that will be duplicated to audit_argcnt. 203*0Sstevel@tonic-gate * 204*0Sstevel@tonic-gate * If (prev_stack_size > (audit_argcnt * 4)) 205*0Sstevel@tonic-gate * prev_stack_size = audit_argcnt * 4; 206*0Sstevel@tonic-gate */ 207*0Sstevel@tonic-gate movl audit_argcnt@GOT(%ebx),%eax 208*0Sstevel@tonic-gate movl (%eax), %eax / %eax = audit_argcnt 209*0Sstevel@tonic-gate cmpl $0, %eax 210*0Sstevel@tonic-gate jle .grow_stack 211*0Sstevel@tonic-gate lea (,%eax,4), %eax / %eax = %eax * 4 212*0Sstevel@tonic-gate cmpl %eax,%edx 213*0Sstevel@tonic-gate jle .grow_stack 214*0Sstevel@tonic-gate movl %eax, %edx 215*0Sstevel@tonic-gate /* 216*0Sstevel@tonic-gate * Grow the stack and duplicate the arguements of the 217*0Sstevel@tonic-gate * original caller. 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate.grow_stack: 220*0Sstevel@tonic-gate subl %edx, %esp / grow the stack 221*0Sstevel@tonic-gate movl %edx, -88(%ebp) / -88(%ebp) == prev frame sz 222*0Sstevel@tonic-gate movl %esp, %ecx / %ecx = dest 223*0Sstevel@tonic-gate addl %ecx, %edx / %edx == tail of dest 224*0Sstevel@tonic-gate.while_base: 225*0Sstevel@tonic-gate cmpl %edx, %ecx / while (base+size >= src++) { 226*0Sstevel@tonic-gate jge .end_while / 227*0Sstevel@tonic-gate movl (%edi), %esi 228*0Sstevel@tonic-gate movl %esi,(%ecx) / *dest = *src 229*0Sstevel@tonic-gate addl $4, %edi / src++ 230*0Sstevel@tonic-gate addl $4, %ecx / dest++ 231*0Sstevel@tonic-gate jmp .while_base / } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate /* 234*0Sstevel@tonic-gate * The above stack is now an exact duplicate of 235*0Sstevel@tonic-gate * the stack of the original calling procedure. 236*0Sstevel@tonic-gate */ 237*0Sstevel@tonic-gate.end_while: 238*0Sstevel@tonic-gate movl -92(%ebp), %eax / restore %eax 239*0Sstevel@tonic-gate movl -96(%ebp), %ebx / restore %ebx 240*0Sstevel@tonic-gate movl -104(%ebp), %esi / restore %esi 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate movl -8(%ebp), %edi 243*0Sstevel@tonic-gate call *%edi / call dest_proc() 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate addl -88(%ebp), %esp / cleanup dupped stack 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate movl -4(%ebp), %edi 248*0Sstevel@tonic-gate pushl SYMNDX_OFF(%edi) / arg4 (symndx) 249*0Sstevel@tonic-gate lea SYMDEF_OFF(%edi), %ecx 250*0Sstevel@tonic-gate pushl %ecx / arg3 (symp) 251*0Sstevel@tonic-gate pushl DEFLMP_OFF(%edi) / arg2 (dlmp) 252*0Sstevel@tonic-gate pushl REFLMP_OFF(%edi) / arg1 (rlmp) 253*0Sstevel@tonic-gate pushl %eax / arg0 (retval) 254*0Sstevel@tonic-gate call audit_pltexit@PLT 255*0Sstevel@tonic-gate addl $20, %esp / cleanup stack 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate /* 258*0Sstevel@tonic-gate * Clean up after ourselves and return to the 259*0Sstevel@tonic-gate * original calling procedure. 260*0Sstevel@tonic-gate */ 261*0Sstevel@tonic-gate popl %esi / 262*0Sstevel@tonic-gate popl %edi / clean up stack 263*0Sstevel@tonic-gate popl %ebx / 264*0Sstevel@tonic-gate movl %ebp, %esp / 265*0Sstevel@tonic-gate popl %ebp / 266*0Sstevel@tonic-gate ret / return to caller 267*0Sstevel@tonic-gate .size elf_plt_trace, .-elf_plt_trace 268*0Sstevel@tonic-gate#endif 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate/* 271*0Sstevel@tonic-gate * We got here because a call to a function resolved to a procedure 272*0Sstevel@tonic-gate * linkage table entry. That entry did a JMPL to the first PLT entry, which 273*0Sstevel@tonic-gate * in turn did a call to elf_rtbndr. 274*0Sstevel@tonic-gate * 275*0Sstevel@tonic-gate * the code sequence that got us here was: 276*0Sstevel@tonic-gate * 277*0Sstevel@tonic-gate * PLT entry for foo: 278*0Sstevel@tonic-gate * jmp *name1@GOT(%ebx) 279*0Sstevel@tonic-gate * pushl $rel.plt.foo 280*0Sstevel@tonic-gate * jmp PLT0 281*0Sstevel@tonic-gate * 282*0Sstevel@tonic-gate * 1st PLT entry (PLT0): 283*0Sstevel@tonic-gate * pushl 4(%ebx) 284*0Sstevel@tonic-gate * jmp *8(%ebx) 285*0Sstevel@tonic-gate * nop; nop; nop;nop; 286*0Sstevel@tonic-gate * 287*0Sstevel@tonic-gate */ 288*0Sstevel@tonic-gate#if defined(lint) 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gateextern unsigned long elf_bndr(Rt_map *, unsigned long, caddr_t); 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gatevoid 293*0Sstevel@tonic-gateelf_rtbndr(Rt_map * lmp, unsigned long reloc, caddr_t pc) 294*0Sstevel@tonic-gate{ 295*0Sstevel@tonic-gate (void) elf_bndr(lmp, reloc, pc); 296*0Sstevel@tonic-gate} 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate#else 299*0Sstevel@tonic-gate .globl elf_bndr 300*0Sstevel@tonic-gate .globl elf_rtbndr 301*0Sstevel@tonic-gate .weak _elf_rtbndr 302*0Sstevel@tonic-gate _elf_rtbndr = elf_rtbndr / Make dbx happy 303*0Sstevel@tonic-gate .type elf_rtbndr,@function 304*0Sstevel@tonic-gate .align 4 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gateelf_rtbndr: 307*0Sstevel@tonic-gate pushl %ebp 308*0Sstevel@tonic-gate movl %esp, %ebp 309*0Sstevel@tonic-gate pushl %eax 310*0Sstevel@tonic-gate pushl %ecx 311*0Sstevel@tonic-gate pushl %edx 312*0Sstevel@tonic-gate pushl 12(%ebp) / push pc 313*0Sstevel@tonic-gate pushl 8(%ebp) / push reloc 314*0Sstevel@tonic-gate pushl 4(%ebp) / push *lmp 315*0Sstevel@tonic-gate call elf_bndr@PLT / call the C binder code 316*0Sstevel@tonic-gate addl $12, %esp / pop args 317*0Sstevel@tonic-gate movl %eax, 8(%ebp) / store final destination 318*0Sstevel@tonic-gate popl %edx 319*0Sstevel@tonic-gate popl %ecx 320*0Sstevel@tonic-gate popl %eax 321*0Sstevel@tonic-gate movl %ebp, %esp 322*0Sstevel@tonic-gate popl %ebp 323*0Sstevel@tonic-gate addl $4,%esp / pop args 324*0Sstevel@tonic-gate ret / invoke resolved function 325*0Sstevel@tonic-gate .size elf_rtbndr, .-elf_rtbndr 326*0Sstevel@tonic-gate#endif 327