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