17c478bd9Sstevel@tonic-gate/* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate/* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * All Rights Reserved 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * 277c478bd9Sstevel@tonic-gate * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved. 287c478bd9Sstevel@tonic-gate * Use is subject to license terms. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate#if defined(lint) 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate#include <sys/types.h> 347c478bd9Sstevel@tonic-gate#include "_rtld.h" 357c478bd9Sstevel@tonic-gate#include "_audit.h" 367c478bd9Sstevel@tonic-gate#include "_elf.h" 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate/* ARGSUSED0 */ 397c478bd9Sstevel@tonic-gateint 407c478bd9Sstevel@tonic-gateelf_plt_trace() 417c478bd9Sstevel@tonic-gate{ 427c478bd9Sstevel@tonic-gate return (0); 437c478bd9Sstevel@tonic-gate} 447c478bd9Sstevel@tonic-gate#else 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate#include <link.h> 477c478bd9Sstevel@tonic-gate#include "_audit.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate .file "boot_elf.s" 507c478bd9Sstevel@tonic-gate .text 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate/* 537c478bd9Sstevel@tonic-gate * On entry the 'glue code' has already done the following: 547c478bd9Sstevel@tonic-gate * 557c478bd9Sstevel@tonic-gate * pushl %ebp 567c478bd9Sstevel@tonic-gate * movl %esp, %ebp 577c478bd9Sstevel@tonic-gate * pushl dyndata_ptr 587c478bd9Sstevel@tonic-gate * jmp elf_plt_trace 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * so - -4(%ebp) contains the dyndata ptr 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * 0x0 uintptr_t reflmp 637c478bd9Sstevel@tonic-gate * 0x4 uintptr_t deflmp 647c478bd9Sstevel@tonic-gate * 0x8 ulong_t symndx 657c478bd9Sstevel@tonic-gate * 0xc ulont_t sb_flags 667c478bd9Sstevel@tonic-gate * 0x10 Elf32_Sym symdef.st_name 677c478bd9Sstevel@tonic-gate * 0x14 symdef.st_value 687c478bd9Sstevel@tonic-gate * 0x18 symdef.st_size 697c478bd9Sstevel@tonic-gate * 0x1c symdef.st_info 707c478bd9Sstevel@tonic-gate * 0x1d symdef.st_other 717c478bd9Sstevel@tonic-gate * 0x1e symdef.st_shndx 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate#define REFLMP_OFF 0x0 747c478bd9Sstevel@tonic-gate#define DEFLMP_OFF 0x4 757c478bd9Sstevel@tonic-gate#define SYMNDX_OFF 0x8 767c478bd9Sstevel@tonic-gate#define SBFLAGS_OFF 0xc 777c478bd9Sstevel@tonic-gate#define SYMDEF_OFF 0x10 787c478bd9Sstevel@tonic-gate#define SYMDEF_VALUE_OFF 0x14 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate .globl elf_plt_trace 817c478bd9Sstevel@tonic-gate .type elf_plt_trace,@function 827c478bd9Sstevel@tonic-gate .align 16 837c478bd9Sstevel@tonic-gateelf_plt_trace: 847c478bd9Sstevel@tonic-gate subl $84,%esp / create some local storage 857c478bd9Sstevel@tonic-gate pushl %eax 867c478bd9Sstevel@tonic-gate pushl %ebx 877c478bd9Sstevel@tonic-gate pushl %edi 887c478bd9Sstevel@tonic-gate pushl %esi 897c478bd9Sstevel@tonic-gate call .L1 / initialize %ebx to GOT 907c478bd9Sstevel@tonic-gate.L1: 917c478bd9Sstevel@tonic-gate popl %ebx 927c478bd9Sstevel@tonic-gate addl $_GLOBAL_OFFSET_TABLE_+[.-.L1], %ebx 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Local stack space storage is allocated as follows: 957c478bd9Sstevel@tonic-gate * 967c478bd9Sstevel@tonic-gate * -4(%ebp) store dyndata ptr 977c478bd9Sstevel@tonic-gate * -8(%ebp) store call destination 987c478bd9Sstevel@tonic-gate * -84(%ebp) space for gregset 997c478bd9Sstevel@tonic-gate * -88(%ebp) prev stack size 1007c478bd9Sstevel@tonic-gate * -92(%ebp) entering %eax 1017c478bd9Sstevel@tonic-gate * -96(%ebp) entering %ebx 1027c478bd9Sstevel@tonic-gate * -100(%ebp) entering %edi 1037c478bd9Sstevel@tonic-gate * -104(%ebp) entering %esi 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate movl -4(%ebp), %eax / %eax = dyndata 1067c478bd9Sstevel@tonic-gate testb $LA_SYMB_NOPLTENTER, 0xc(%eax) / <link.h> 1077c478bd9Sstevel@tonic-gate je .start_pltenter 1087c478bd9Sstevel@tonic-gate movl SYMDEF_VALUE_OFF(%eax), %edi 1097c478bd9Sstevel@tonic-gate movl %edi, -8(%ebp) / save destination address 1107c478bd9Sstevel@tonic-gate jmp .end_pltenter 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate.start_pltenter: 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * save all registers into gregset_t 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate lea 4(%ebp), %edi 1177c478bd9Sstevel@tonic-gate movl %edi, -84(%ebp) / %esp 1187c478bd9Sstevel@tonic-gate movl 0(%ebp), %edi 1197c478bd9Sstevel@tonic-gate movl %edi, -80(%ebp) / %ebp 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * trapno, err, eip, cs, efl, uesp, ss 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate movl -4(%ebp), %edi 1247c478bd9Sstevel@tonic-gate lea SBFLAGS_OFF(%edi), %eax 1257c478bd9Sstevel@tonic-gate pushl %eax / arg5 (&sb_flags) 1267c478bd9Sstevel@tonic-gate lea -84(%ebp), %eax 1277c478bd9Sstevel@tonic-gate pushl %eax / arg4 (regset) 1287c478bd9Sstevel@tonic-gate pushl SYMNDX_OFF(%edi) / arg3 (symndx) 1297c478bd9Sstevel@tonic-gate lea SYMDEF_OFF(%edi), %eax 1307c478bd9Sstevel@tonic-gate pushl %eax / arg2 (&sym) 1317c478bd9Sstevel@tonic-gate pushl DEFLMP_OFF(%edi) / arg1 (dlmp) 1327c478bd9Sstevel@tonic-gate pushl REFLMP_OFF(%edi) / arg0 (rlmp) 1337c478bd9Sstevel@tonic-gate call audit_pltenter@PLT 1347c478bd9Sstevel@tonic-gate addl $24, %esp / cleanup stack 1357c478bd9Sstevel@tonic-gate movl %eax, -8(%ebp) / save calling address 1367c478bd9Sstevel@tonic-gate.end_pltenter: 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * If *no* la_pltexit() routines exist 1407c478bd9Sstevel@tonic-gate * we do not need to keep the stack frame 1417c478bd9Sstevel@tonic-gate * before we call the actual routine. Instead we 1427c478bd9Sstevel@tonic-gate * jump to it and remove our stack from the stack 1437c478bd9Sstevel@tonic-gate * at the same time. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate movl audit_flags@GOT(%ebx), %eax 1467c478bd9Sstevel@tonic-gate movl (%eax), %eax 1477c478bd9Sstevel@tonic-gate andl $AF_PLTEXIT, %eax / value of audit.h:AF_PLTEXIT 1487c478bd9Sstevel@tonic-gate cmpl $0, %eax 1497c478bd9Sstevel@tonic-gate je .bypass_pltexit 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * Has the *nopltexit* flag been set for this entry point 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate testb $LA_SYMB_NOPLTEXIT, 12(%edi) 1547c478bd9Sstevel@tonic-gate je .start_pltexit 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate.bypass_pltexit: 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * No PLTEXIT processing required. 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate movl 0(%ebp), %eax 1617c478bd9Sstevel@tonic-gate movl %eax, -4(%ebp) 1627c478bd9Sstevel@tonic-gate movl -8(%ebp), %eax / eax == calling destination 1637c478bd9Sstevel@tonic-gate movl %eax, 0(%ebp) / store destination at top 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate popl %esi / 1667c478bd9Sstevel@tonic-gate popl %edi / clean up stack 1677c478bd9Sstevel@tonic-gate popl %ebx / 1687c478bd9Sstevel@tonic-gate popl %eax / 1697c478bd9Sstevel@tonic-gate subl $4, %ebp / adjust %ebp for 'ret' 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * At this point, after a little doctoring, we should 1727c478bd9Sstevel@tonic-gate * have the following on the stack: 1737c478bd9Sstevel@tonic-gate * 1747c478bd9Sstevel@tonic-gate * 8(%esp): ret addr 1757c478bd9Sstevel@tonic-gate * 4(%esp): dest_addr 1767c478bd9Sstevel@tonic-gate * 0(%esp): Previous %ebp 1777c478bd9Sstevel@tonic-gate * 1787c478bd9Sstevel@tonic-gate * So - we pop the previous %ebp, and then 1797c478bd9Sstevel@tonic-gate * ret to our final destination. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate movl %ebp, %esp / 1827c478bd9Sstevel@tonic-gate popl %ebp / 1837c478bd9Sstevel@tonic-gate ret / jmp to final destination 1847c478bd9Sstevel@tonic-gate / and clean up stack :) 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate.start_pltexit: 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * In order to call the destination procedure and then return 1907c478bd9Sstevel@tonic-gate * to audit_pltexit() for post analysis we must first grow 1917c478bd9Sstevel@tonic-gate * our stack frame and then duplicate the original callers 1927c478bd9Sstevel@tonic-gate * stack state. This duplicates all of the arguements 1937c478bd9Sstevel@tonic-gate * that were to be passed to the destination procedure. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate movl %ebp, %edi / 1967c478bd9Sstevel@tonic-gate addl $8, %edi / %edi = src 1977c478bd9Sstevel@tonic-gate movl (%ebp), %edx / 1987c478bd9Sstevel@tonic-gate subl %edi, %edx / %edx == prev frame sz 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * If audit_argcnt > 0 then we limit the number of 2017c478bd9Sstevel@tonic-gate * arguements that will be duplicated to audit_argcnt. 2027c478bd9Sstevel@tonic-gate * 2037c478bd9Sstevel@tonic-gate * If (prev_stack_size > (audit_argcnt * 4)) 2047c478bd9Sstevel@tonic-gate * prev_stack_size = audit_argcnt * 4; 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate movl audit_argcnt@GOT(%ebx),%eax 2077c478bd9Sstevel@tonic-gate movl (%eax), %eax / %eax = audit_argcnt 2087c478bd9Sstevel@tonic-gate cmpl $0, %eax 2097c478bd9Sstevel@tonic-gate jle .grow_stack 2107c478bd9Sstevel@tonic-gate lea (,%eax,4), %eax / %eax = %eax * 4 2117c478bd9Sstevel@tonic-gate cmpl %eax,%edx 2127c478bd9Sstevel@tonic-gate jle .grow_stack 2137c478bd9Sstevel@tonic-gate movl %eax, %edx 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Grow the stack and duplicate the arguements of the 2167c478bd9Sstevel@tonic-gate * original caller. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate.grow_stack: 2192a8bcb4eSToomas Soome subl %edx, %esp / grow the stack 2207c478bd9Sstevel@tonic-gate movl %edx, -88(%ebp) / -88(%ebp) == prev frame sz 2217c478bd9Sstevel@tonic-gate movl %esp, %ecx / %ecx = dest 2227c478bd9Sstevel@tonic-gate addl %ecx, %edx / %edx == tail of dest 2237c478bd9Sstevel@tonic-gate.while_base: 2247c478bd9Sstevel@tonic-gate cmpl %edx, %ecx / while (base+size >= src++) { 2257c478bd9Sstevel@tonic-gate jge .end_while / 2267c478bd9Sstevel@tonic-gate movl (%edi), %esi 2277c478bd9Sstevel@tonic-gate movl %esi,(%ecx) / *dest = *src 2287c478bd9Sstevel@tonic-gate addl $4, %edi / src++ 2297c478bd9Sstevel@tonic-gate addl $4, %ecx / dest++ 2307c478bd9Sstevel@tonic-gate jmp .while_base / } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * The above stack is now an exact duplicate of 2347c478bd9Sstevel@tonic-gate * the stack of the original calling procedure. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate.end_while: 2377c478bd9Sstevel@tonic-gate movl -92(%ebp), %eax / restore %eax 2387c478bd9Sstevel@tonic-gate movl -96(%ebp), %ebx / restore %ebx 2397c478bd9Sstevel@tonic-gate movl -104(%ebp), %esi / restore %esi 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate movl -8(%ebp), %edi 2427c478bd9Sstevel@tonic-gate call *%edi / call dest_proc() 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate addl -88(%ebp), %esp / cleanup dupped stack 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate movl -4(%ebp), %edi 2477c478bd9Sstevel@tonic-gate pushl SYMNDX_OFF(%edi) / arg4 (symndx) 2487c478bd9Sstevel@tonic-gate lea SYMDEF_OFF(%edi), %ecx 2497c478bd9Sstevel@tonic-gate pushl %ecx / arg3 (symp) 2507c478bd9Sstevel@tonic-gate pushl DEFLMP_OFF(%edi) / arg2 (dlmp) 2517c478bd9Sstevel@tonic-gate pushl REFLMP_OFF(%edi) / arg1 (rlmp) 2527c478bd9Sstevel@tonic-gate pushl %eax / arg0 (retval) 2537c478bd9Sstevel@tonic-gate call audit_pltexit@PLT 2547c478bd9Sstevel@tonic-gate addl $20, %esp / cleanup stack 2552a8bcb4eSToomas Soome 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Clean up after ourselves and return to the 2587c478bd9Sstevel@tonic-gate * original calling procedure. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate popl %esi / 2617c478bd9Sstevel@tonic-gate popl %edi / clean up stack 2627c478bd9Sstevel@tonic-gate popl %ebx / 2637c478bd9Sstevel@tonic-gate movl %ebp, %esp / 2647c478bd9Sstevel@tonic-gate popl %ebp / 2657c478bd9Sstevel@tonic-gate ret / return to caller 2667c478bd9Sstevel@tonic-gate .size elf_plt_trace, .-elf_plt_trace 2677c478bd9Sstevel@tonic-gate#endif 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate/* 2707c478bd9Sstevel@tonic-gate * We got here because a call to a function resolved to a procedure 2717c478bd9Sstevel@tonic-gate * linkage table entry. That entry did a JMPL to the first PLT entry, which 2727c478bd9Sstevel@tonic-gate * in turn did a call to elf_rtbndr. 2737c478bd9Sstevel@tonic-gate * 2747c478bd9Sstevel@tonic-gate * the code sequence that got us here was: 2757c478bd9Sstevel@tonic-gate * 2767c478bd9Sstevel@tonic-gate * PLT entry for foo: 2777c478bd9Sstevel@tonic-gate * jmp *name1@GOT(%ebx) 2787c478bd9Sstevel@tonic-gate * pushl $rel.plt.foo 2797c478bd9Sstevel@tonic-gate * jmp PLT0 2807c478bd9Sstevel@tonic-gate * 2817c478bd9Sstevel@tonic-gate * 1st PLT entry (PLT0): 2827c478bd9Sstevel@tonic-gate * pushl 4(%ebx) 2837c478bd9Sstevel@tonic-gate * jmp *8(%ebx) 2847c478bd9Sstevel@tonic-gate * nop; nop; nop;nop; 2857c478bd9Sstevel@tonic-gate * 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate#if defined(lint) 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gateextern unsigned long elf_bndr(Rt_map *, unsigned long, caddr_t); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gatevoid 2927c478bd9Sstevel@tonic-gateelf_rtbndr(Rt_map * lmp, unsigned long reloc, caddr_t pc) 2937c478bd9Sstevel@tonic-gate{ 2947c478bd9Sstevel@tonic-gate (void) elf_bndr(lmp, reloc, pc); 2957c478bd9Sstevel@tonic-gate} 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate#else 2987c478bd9Sstevel@tonic-gate .globl elf_bndr 2997c478bd9Sstevel@tonic-gate .globl elf_rtbndr 3007c478bd9Sstevel@tonic-gate .weak _elf_rtbndr 3017c478bd9Sstevel@tonic-gate _elf_rtbndr = elf_rtbndr / Make dbx happy 3027c478bd9Sstevel@tonic-gate .type elf_rtbndr,@function 3037c478bd9Sstevel@tonic-gate .align 4 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gateelf_rtbndr: 3067c478bd9Sstevel@tonic-gate pushl %ebp 3077c478bd9Sstevel@tonic-gate movl %esp, %ebp 3087c478bd9Sstevel@tonic-gate pushl %eax 3097c478bd9Sstevel@tonic-gate pushl %ecx 3107c478bd9Sstevel@tonic-gate pushl %edx 3117c478bd9Sstevel@tonic-gate pushl 12(%ebp) / push pc 3127c478bd9Sstevel@tonic-gate pushl 8(%ebp) / push reloc 3137c478bd9Sstevel@tonic-gate pushl 4(%ebp) / push *lmp 3147c478bd9Sstevel@tonic-gate call elf_bndr@PLT / call the C binder code 3157c478bd9Sstevel@tonic-gate addl $12, %esp / pop args 3167c478bd9Sstevel@tonic-gate movl %eax, 8(%ebp) / store final destination 3177c478bd9Sstevel@tonic-gate popl %edx 3187c478bd9Sstevel@tonic-gate popl %ecx 3197c478bd9Sstevel@tonic-gate popl %eax 3207c478bd9Sstevel@tonic-gate movl %ebp, %esp 3217c478bd9Sstevel@tonic-gate popl %ebp 3227c478bd9Sstevel@tonic-gate addl $4,%esp / pop args 3237c478bd9Sstevel@tonic-gate ret / invoke resolved function 3247c478bd9Sstevel@tonic-gate .size elf_rtbndr, .-elf_rtbndr 3257c478bd9Sstevel@tonic-gate#endif 326