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
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]
23 * Copyright (c) 1988 AT&T
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"
40 * On entry the 'glue code' has already done the following:
47 * so - -4(%ebp) contains the dyndata ptr
49 * 0x0 uintptr_t reflmp
50 * 0x4 uintptr_t deflmp
52 * 0xc ulont_t sb_flags
53 * 0x10 Elf32_Sym symdef.st_name
54 * 0x14 symdef.st_value
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
68 .type elf_plt_trace,@function
71 subl $
84,%esp
/ create some local storage
76 call
.L1 / initialize %ebx to GOT
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
>
95 movl SYMDEF_VALUE_OFF
(%eax
), %edi
96 movl
%edi
, -8(%ebp
) / save destination address
101 * save all registers into gregset_t
104 movl
%edi
, -84(%ebp
) / %esp
106 movl
%edi
, -80(%ebp
) / %ebp
108 * trapno, err, eip, cs, efl, uesp, ss
111 lea SBFLAGS_OFF
(%edi
), %eax
112 pushl
%eax
/ arg5
(&sb_flags
)
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
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
132 movl audit_flags@GOT
(%ebx
), %eax
134 andl $AF_PLTEXIT
, %eax
/ value of audit.h
:AF_PLTEXIT
138 * Has the *nopltexit* flag been set for this entry point
140 testb $LA_SYMB_NOPLTEXIT
, 12(%edi
)
145 * No PLTEXIT processing required.
149 movl
-8(%ebp
), %eax
/ eax
== calling destination
150 movl
%eax
, 0(%ebp
) / store destination at top
153 popl
%edi
/ clean up stack
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:
163 * 0(%esp): Previous %ebp
165 * So - we pop the previous %ebp, and then
166 * ret to our final destination.
170 ret
/ jmp to final destination
171 / and clean up stack
:)
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.
183 addl $
8, %edi
/ %edi
= src
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
197 lea
(,%eax
,4), %eax
/ %eax
= %eax
* 4
202 * Grow the stack and duplicate the arguements of the
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
211 cmpl %edx
, %ecx
/ while
(base+size
>= src+
+) {
214 movl
%esi
,(%ecx
) / *dest
= *src
215 addl $
4, %edi
/ src+
+
216 addl $
4, %ecx
/ dest+
+
220 * The above stack is now an exact duplicate of
221 * the stack of the original calling procedure.
224 movl
-92(%ebp
), %eax
/ restore
%eax
225 movl
-96(%ebp
), %ebx
/ restore
%ebx
226 movl
-104(%ebp
), %esi
/ restore
%esi
229 call
*%edi
/ call dest_proc
()
231 addl
-88(%ebp
), %esp
/ cleanup dupped stack
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.
248 popl
%edi
/ clean up stack
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:
263 * jmp *name1@GOT(%ebx)
267 * 1st PLT entry (PLT0):
276 _elf_rtbndr
= elf_rtbndr
/ Make dbx happy
277 .type elf_rtbndr,@function
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
297 addl $
4,%esp
/ pop args
298 ret
/ invoke resolved function
299 .size elf_rtbndr, .-elf_rtbndr