dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / i386 / boot_elf.s
blobcceb143720a8980e3b16f102fab9e22e871be6b5
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
27 * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <link.h>
34 #include "_audit.h"
36 .file "boot_elf.s"
37 .text
40 * On entry the 'glue code' has already done the following:
42 * pushl %ebp
43 * movl %esp, %ebp
44 * pushl dyndata_ptr
45 * jmp elf_plt_trace
47 * so - -4(%ebp) contains the dyndata ptr
49 * 0x0 uintptr_t reflmp
50 * 0x4 uintptr_t deflmp
51 * 0x8 ulong_t symndx
52 * 0xc ulont_t sb_flags
53 * 0x10 Elf32_Sym symdef.st_name
54 * 0x14 symdef.st_value
55 * 0x18 symdef.st_size
56 * 0x1c symdef.st_info
57 * 0x1d symdef.st_other
58 * 0x1e symdef.st_shndx
60 #define REFLMP_OFF 0x0
61 #define DEFLMP_OFF 0x4
62 #define SYMNDX_OFF 0x8
63 #define SBFLAGS_OFF 0xc
64 #define SYMDEF_OFF 0x10
65 #define SYMDEF_VALUE_OFF 0x14
67 .globl elf_plt_trace
68 .type elf_plt_trace,@function
69 .align 16
70 elf_plt_trace:
71 subl $84,%esp / create some local storage
72 pushl %eax
73 pushl %ebx
74 pushl %edi
75 pushl %esi
76 call .L1 / initialize %ebx to GOT
77 .L1:
78 popl %ebx
79 addl $_GLOBAL_OFFSET_TABLE_+[.-.L1], %ebx
81 * Local stack space storage is allocated as follows:
83 * -4(%ebp) store dyndata ptr
84 * -8(%ebp) store call destination
85 * -84(%ebp) space for gregset
86 * -88(%ebp) prev stack size
87 * -92(%ebp) entering %eax
88 * -96(%ebp) entering %ebx
89 * -100(%ebp) entering %edi
90 * -104(%ebp) entering %esi
92 movl -4(%ebp), %eax / %eax = dyndata
93 testb $LA_SYMB_NOPLTENTER, 0xc(%eax) / <link.h>
94 je .start_pltenter
95 movl SYMDEF_VALUE_OFF(%eax), %edi
96 movl %edi, -8(%ebp) / save destination address
97 jmp .end_pltenter
99 .start_pltenter:
101 * save all registers into gregset_t
103 lea 4(%ebp), %edi
104 movl %edi, -84(%ebp) / %esp
105 movl 0(%ebp), %edi
106 movl %edi, -80(%ebp) / %ebp
108 * trapno, err, eip, cs, efl, uesp, ss
110 movl -4(%ebp), %edi
111 lea SBFLAGS_OFF(%edi), %eax
112 pushl %eax / arg5 (&sb_flags)
113 lea -84(%ebp), %eax
114 pushl %eax / arg4 (regset)
115 pushl SYMNDX_OFF(%edi) / arg3 (symndx)
116 lea SYMDEF_OFF(%edi), %eax
117 pushl %eax / arg2 (&sym)
118 pushl DEFLMP_OFF(%edi) / arg1 (dlmp)
119 pushl REFLMP_OFF(%edi) / arg0 (rlmp)
120 call audit_pltenter@PLT
121 addl $24, %esp / cleanup stack
122 movl %eax, -8(%ebp) / save calling address
123 .end_pltenter:
126 * If *no* la_pltexit() routines exist
127 * we do not need to keep the stack frame
128 * before we call the actual routine. Instead we
129 * jump to it and remove our stack from the stack
130 * at the same time.
132 movl audit_flags@GOT(%ebx), %eax
133 movl (%eax), %eax
134 andl $AF_PLTEXIT, %eax / value of audit.h:AF_PLTEXIT
135 cmpl $0, %eax
136 je .bypass_pltexit
138 * Has the *nopltexit* flag been set for this entry point
140 testb $LA_SYMB_NOPLTEXIT, 12(%edi)
141 je .start_pltexit
143 .bypass_pltexit:
145 * No PLTEXIT processing required.
147 movl 0(%ebp), %eax
148 movl %eax, -4(%ebp)
149 movl -8(%ebp), %eax / eax == calling destination
150 movl %eax, 0(%ebp) / store destination at top
152 popl %esi /
153 popl %edi / clean up stack
154 popl %ebx /
155 popl %eax /
156 subl $4, %ebp / adjust %ebp for 'ret'
158 * At this point, after a little doctoring, we should
159 * have the following on the stack:
161 * 8(%esp): ret addr
162 * 4(%esp): dest_addr
163 * 0(%esp): Previous %ebp
165 * So - we pop the previous %ebp, and then
166 * ret to our final destination.
168 movl %ebp, %esp /
169 popl %ebp /
170 ret / jmp to final destination
171 / and clean up stack :)
173 .start_pltexit:
176 * In order to call the destination procedure and then return
177 * to audit_pltexit() for post analysis we must first grow
178 * our stack frame and then duplicate the original callers
179 * stack state. This duplicates all of the arguements
180 * that were to be passed to the destination procedure.
182 movl %ebp, %edi /
183 addl $8, %edi / %edi = src
184 movl (%ebp), %edx /
185 subl %edi, %edx / %edx == prev frame sz
187 * If audit_argcnt > 0 then we limit the number of
188 * arguements that will be duplicated to audit_argcnt.
190 * If (prev_stack_size > (audit_argcnt * 4))
191 * prev_stack_size = audit_argcnt * 4;
193 movl audit_argcnt@GOT(%ebx),%eax
194 movl (%eax), %eax / %eax = audit_argcnt
195 cmpl $0, %eax
196 jle .grow_stack
197 lea (,%eax,4), %eax / %eax = %eax * 4
198 cmpl %eax,%edx
199 jle .grow_stack
200 movl %eax, %edx
202 * Grow the stack and duplicate the arguements of the
203 * original caller.
205 .grow_stack:
206 subl %edx, %esp / grow the stack
207 movl %edx, -88(%ebp) / -88(%ebp) == prev frame sz
208 movl %esp, %ecx / %ecx = dest
209 addl %ecx, %edx / %edx == tail of dest
210 .while_base:
211 cmpl %edx, %ecx / while (base+size >= src++) {
212 jge .end_while /
213 movl (%edi), %esi
214 movl %esi,(%ecx) / *dest = *src
215 addl $4, %edi / src++
216 addl $4, %ecx / dest++
217 jmp .while_base / }
220 * The above stack is now an exact duplicate of
221 * the stack of the original calling procedure.
223 .end_while:
224 movl -92(%ebp), %eax / restore %eax
225 movl -96(%ebp), %ebx / restore %ebx
226 movl -104(%ebp), %esi / restore %esi
228 movl -8(%ebp), %edi
229 call *%edi / call dest_proc()
231 addl -88(%ebp), %esp / cleanup dupped stack
233 movl -4(%ebp), %edi
234 pushl SYMNDX_OFF(%edi) / arg4 (symndx)
235 lea SYMDEF_OFF(%edi), %ecx
236 pushl %ecx / arg3 (symp)
237 pushl DEFLMP_OFF(%edi) / arg2 (dlmp)
238 pushl REFLMP_OFF(%edi) / arg1 (rlmp)
239 pushl %eax / arg0 (retval)
240 call audit_pltexit@PLT
241 addl $20, %esp / cleanup stack
244 * Clean up after ourselves and return to the
245 * original calling procedure.
247 popl %esi /
248 popl %edi / clean up stack
249 popl %ebx /
250 movl %ebp, %esp /
251 popl %ebp /
252 ret / return to caller
253 .size elf_plt_trace, .-elf_plt_trace
256 * We got here because a call to a function resolved to a procedure
257 * linkage table entry. That entry did a JMPL to the first PLT entry, which
258 * in turn did a call to elf_rtbndr.
260 * the code sequence that got us here was:
262 * PLT entry for foo:
263 * jmp *name1@GOT(%ebx)
264 * pushl $rel.plt.foo
265 * jmp PLT0
267 * 1st PLT entry (PLT0):
268 * pushl 4(%ebx)
269 * jmp *8(%ebx)
270 * nop; nop; nop;nop;
273 .globl elf_bndr
274 .globl elf_rtbndr
275 .weak _elf_rtbndr
276 _elf_rtbndr = elf_rtbndr / Make dbx happy
277 .type elf_rtbndr,@function
278 .align 4
280 elf_rtbndr:
281 pushl %ebp
282 movl %esp, %ebp
283 pushl %eax
284 pushl %ecx
285 pushl %edx
286 pushl 12(%ebp) / push pc
287 pushl 8(%ebp) / push reloc
288 pushl 4(%ebp) / push *lmp
289 call elf_bndr@PLT / call the C binder code
290 addl $12, %esp / pop args
291 movl %eax, 8(%ebp) / store final destination
292 popl %edx
293 popl %ecx
294 popl %eax
295 movl %ebp, %esp
296 popl %ebp
297 addl $4,%esp / pop args
298 ret / invoke resolved function
299 .size elf_rtbndr, .-elf_rtbndr