8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / i386 / boot_elf.s
blobaf7abf3305f4090c4786c572507f252c3f658e64
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"
32 #if defined(lint)
34 #include <sys/types.h>
35 #include "_rtld.h"
36 #include "_audit.h"
37 #include "_elf.h"
39 /* ARGSUSED0 */
40 int
41 elf_plt_trace()
43 return (0);
45 #else
47 #include <link.h>
48 #include "_audit.h"
50 .file "boot_elf.s"
51 .text
54 * On entry the 'glue code' has already done the following:
56 * pushl %ebp
57 * movl %esp, %ebp
58 * pushl dyndata_ptr
59 * jmp elf_plt_trace
61 * so - -4(%ebp) contains the dyndata ptr
63 * 0x0 uintptr_t reflmp
64 * 0x4 uintptr_t deflmp
65 * 0x8 ulong_t symndx
66 * 0xc ulont_t sb_flags
67 * 0x10 Elf32_Sym symdef.st_name
68 * 0x14 symdef.st_value
69 * 0x18 symdef.st_size
70 * 0x1c symdef.st_info
71 * 0x1d symdef.st_other
72 * 0x1e symdef.st_shndx
74 #define REFLMP_OFF 0x0
75 #define DEFLMP_OFF 0x4
76 #define SYMNDX_OFF 0x8
77 #define SBFLAGS_OFF 0xc
78 #define SYMDEF_OFF 0x10
79 #define SYMDEF_VALUE_OFF 0x14
81 .globl elf_plt_trace
82 .type elf_plt_trace,@function
83 .align 16
84 elf_plt_trace:
85 subl $84,%esp / create some local storage
86 pushl %eax
87 pushl %ebx
88 pushl %edi
89 pushl %esi
90 call .L1 / initialize %ebx to GOT
91 .L1:
92 popl %ebx
93 addl $_GLOBAL_OFFSET_TABLE_+[.-.L1], %ebx
95 * Local stack space storage is allocated as follows:
97 * -4(%ebp) store dyndata ptr
98 * -8(%ebp) store call destination
99 * -84(%ebp) space for gregset
100 * -88(%ebp) prev stack size
101 * -92(%ebp) entering %eax
102 * -96(%ebp) entering %ebx
103 * -100(%ebp) entering %edi
104 * -104(%ebp) entering %esi
106 movl -4(%ebp), %eax / %eax = dyndata
107 testb $LA_SYMB_NOPLTENTER, 0xc(%eax) / <link.h>
108 je .start_pltenter
109 movl SYMDEF_VALUE_OFF(%eax), %edi
110 movl %edi, -8(%ebp) / save destination address
111 jmp .end_pltenter
113 .start_pltenter:
115 * save all registers into gregset_t
117 lea 4(%ebp), %edi
118 movl %edi, -84(%ebp) / %esp
119 movl 0(%ebp), %edi
120 movl %edi, -80(%ebp) / %ebp
122 * trapno, err, eip, cs, efl, uesp, ss
124 movl -4(%ebp), %edi
125 lea SBFLAGS_OFF(%edi), %eax
126 pushl %eax / arg5 (&sb_flags)
127 lea -84(%ebp), %eax
128 pushl %eax / arg4 (regset)
129 pushl SYMNDX_OFF(%edi) / arg3 (symndx)
130 lea SYMDEF_OFF(%edi), %eax
131 pushl %eax / arg2 (&sym)
132 pushl DEFLMP_OFF(%edi) / arg1 (dlmp)
133 pushl REFLMP_OFF(%edi) / arg0 (rlmp)
134 call audit_pltenter@PLT
135 addl $24, %esp / cleanup stack
136 movl %eax, -8(%ebp) / save calling address
137 .end_pltenter:
140 * If *no* la_pltexit() routines exist
141 * we do not need to keep the stack frame
142 * before we call the actual routine. Instead we
143 * jump to it and remove our stack from the stack
144 * at the same time.
146 movl audit_flags@GOT(%ebx), %eax
147 movl (%eax), %eax
148 andl $AF_PLTEXIT, %eax / value of audit.h:AF_PLTEXIT
149 cmpl $0, %eax
150 je .bypass_pltexit
152 * Has the *nopltexit* flag been set for this entry point
154 testb $LA_SYMB_NOPLTEXIT, 12(%edi)
155 je .start_pltexit
157 .bypass_pltexit:
159 * No PLTEXIT processing required.
161 movl 0(%ebp), %eax
162 movl %eax, -4(%ebp)
163 movl -8(%ebp), %eax / eax == calling destination
164 movl %eax, 0(%ebp) / store destination at top
166 popl %esi /
167 popl %edi / clean up stack
168 popl %ebx /
169 popl %eax /
170 subl $4, %ebp / adjust %ebp for 'ret'
172 * At this point, after a little doctoring, we should
173 * have the following on the stack:
175 * 8(%esp): ret addr
176 * 4(%esp): dest_addr
177 * 0(%esp): Previous %ebp
179 * So - we pop the previous %ebp, and then
180 * ret to our final destination.
182 movl %ebp, %esp /
183 popl %ebp /
184 ret / jmp to final destination
185 / and clean up stack :)
187 .start_pltexit:
190 * In order to call the destination procedure and then return
191 * to audit_pltexit() for post analysis we must first grow
192 * our stack frame and then duplicate the original callers
193 * stack state. This duplicates all of the arguements
194 * that were to be passed to the destination procedure.
196 movl %ebp, %edi /
197 addl $8, %edi / %edi = src
198 movl (%ebp), %edx /
199 subl %edi, %edx / %edx == prev frame sz
201 * If audit_argcnt > 0 then we limit the number of
202 * arguements that will be duplicated to audit_argcnt.
204 * If (prev_stack_size > (audit_argcnt * 4))
205 * prev_stack_size = audit_argcnt * 4;
207 movl audit_argcnt@GOT(%ebx),%eax
208 movl (%eax), %eax / %eax = audit_argcnt
209 cmpl $0, %eax
210 jle .grow_stack
211 lea (,%eax,4), %eax / %eax = %eax * 4
212 cmpl %eax,%edx
213 jle .grow_stack
214 movl %eax, %edx
216 * Grow the stack and duplicate the arguements of the
217 * original caller.
219 .grow_stack:
220 subl %edx, %esp / grow the stack
221 movl %edx, -88(%ebp) / -88(%ebp) == prev frame sz
222 movl %esp, %ecx / %ecx = dest
223 addl %ecx, %edx / %edx == tail of dest
224 .while_base:
225 cmpl %edx, %ecx / while (base+size >= src++) {
226 jge .end_while /
227 movl (%edi), %esi
228 movl %esi,(%ecx) / *dest = *src
229 addl $4, %edi / src++
230 addl $4, %ecx / dest++
231 jmp .while_base / }
234 * The above stack is now an exact duplicate of
235 * the stack of the original calling procedure.
237 .end_while:
238 movl -92(%ebp), %eax / restore %eax
239 movl -96(%ebp), %ebx / restore %ebx
240 movl -104(%ebp), %esi / restore %esi
242 movl -8(%ebp), %edi
243 call *%edi / call dest_proc()
245 addl -88(%ebp), %esp / cleanup dupped stack
247 movl -4(%ebp), %edi
248 pushl SYMNDX_OFF(%edi) / arg4 (symndx)
249 lea SYMDEF_OFF(%edi), %ecx
250 pushl %ecx / arg3 (symp)
251 pushl DEFLMP_OFF(%edi) / arg2 (dlmp)
252 pushl REFLMP_OFF(%edi) / arg1 (rlmp)
253 pushl %eax / arg0 (retval)
254 call audit_pltexit@PLT
255 addl $20, %esp / cleanup stack
258 * Clean up after ourselves and return to the
259 * original calling procedure.
261 popl %esi /
262 popl %edi / clean up stack
263 popl %ebx /
264 movl %ebp, %esp /
265 popl %ebp /
266 ret / return to caller
267 .size elf_plt_trace, .-elf_plt_trace
268 #endif
271 * We got here because a call to a function resolved to a procedure
272 * linkage table entry. That entry did a JMPL to the first PLT entry, which
273 * in turn did a call to elf_rtbndr.
275 * the code sequence that got us here was:
277 * PLT entry for foo:
278 * jmp *name1@GOT(%ebx)
279 * pushl $rel.plt.foo
280 * jmp PLT0
282 * 1st PLT entry (PLT0):
283 * pushl 4(%ebx)
284 * jmp *8(%ebx)
285 * nop; nop; nop;nop;
288 #if defined(lint)
290 extern unsigned long elf_bndr(Rt_map *, unsigned long, caddr_t);
292 void
293 elf_rtbndr(Rt_map * lmp, unsigned long reloc, caddr_t pc)
295 (void) elf_bndr(lmp, reloc, pc);
298 #else
299 .globl elf_bndr
300 .globl elf_rtbndr
301 .weak _elf_rtbndr
302 _elf_rtbndr = elf_rtbndr / Make dbx happy
303 .type elf_rtbndr,@function
304 .align 4
306 elf_rtbndr:
307 pushl %ebp
308 movl %esp, %ebp
309 pushl %eax
310 pushl %ecx
311 pushl %edx
312 pushl 12(%ebp) / push pc
313 pushl 8(%ebp) / push reloc
314 pushl 4(%ebp) / push *lmp
315 call elf_bndr@PLT / call the C binder code
316 addl $12, %esp / pop args
317 movl %eax, 8(%ebp) / store final destination
318 popl %edx
319 popl %ecx
320 popl %eax
321 movl %ebp, %esp
322 popl %ebp
323 addl $4,%esp / pop args
324 ret / invoke resolved function
325 .size elf_rtbndr, .-elf_rtbndr
326 #endif