dyld-45.1.tar.gz
[apple/dyld.git] / src / stub_binding_helper.s
1 /*
2  * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  * 
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. Please obtain a copy of the License at
10  * http://www.opensource.apple.com/apsl/ and read it before using this
11  * file.
12  * 
13  * The Original Code and all software distributed under the License are
14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18  * Please see the License for the specific language governing rights and
19  * limitations under the License.
20  * 
21  * @APPLE_LICENSE_HEADER_END@
22  */
23  
24  
25
26 #ifdef __i386__
27 /*
28  * This is the interface for the stub_binding_helper for i386:
29  * The caller has pushed the address of the a lazy pointer to be filled in with
30  * the value for the defined symbol and pushed the address of the the mach
31  * header this pointer comes from.
32  *
33  * sp+4 address of lazy pointer
34  * sp+0 address of mach header
35  *
36  * Some inter-image function calls pass parameters in registers EAX, ECX, EDX, or XXM0-3,
37  * Therefore those registers need to be preserved during the lazy binding.
38  * 
39  * After the symbol has been resolved and the pointer filled in this is to pop
40  * these arguments off the stack and jump to the address of the defined symbol.
41  */
42 #define MH_PARAM_BP                     4
43 #define LP_PARAM_BP                     8
44 #define RESULT_BP                       8    /* in order to trash no registers, the target is stored back on the stack then ret it done to it */
45
46 #define MH_PARAM_OUT        0
47 #define LP_PARAM_OUT        4
48 #define EAX_SAVE                        8
49 #define ECX_SAVE                        12
50 #define EDX_SAVE                        16
51 #define XMMM0_SAVE                      32    /* 16-byte align */
52 #define XMMM1_SAVE                      48
53 #define XMMM2_SAVE                      64
54 #define XMMM3_SAVE                      80
55 #define STACK_SIZE                      96 /*  (XMMM3_SAVE+16) must be 16 byte aligned too */
56
57
58     .text
59     .align 4,0x90
60         .globl _fast_stub_binding_helper_interface
61 _fast_stub_binding_helper_interface:
62         pushl           $0
63     .globl _stub_binding_helper_interface
64 _stub_binding_helper_interface:
65         pushl           %ebp
66         movl            %esp,%ebp
67         subl            $STACK_SIZE,%esp                # at this point stack is 16-byte aligned because two meta-parameters where pushed
68         movl            %eax,EAX_SAVE(%esp)             # save registers that might be used as parameters
69         movl            %ecx,ECX_SAVE(%esp)
70         movl            %edx,EDX_SAVE(%esp)
71         movdqa          %xmm0,XMMM0_SAVE(%esp)
72         movdqa          %xmm1,XMMM1_SAVE(%esp)
73         movdqa          %xmm2,XMMM2_SAVE(%esp)
74         movdqa          %xmm3,XMMM3_SAVE(%esp)
75         movl            MH_PARAM_BP(%ebp),%eax  # call dyld::bindLazySymbol(mh, lazy_ptr)
76         movl            %eax,MH_PARAM_OUT(%esp)
77         movl            LP_PARAM_BP(%ebp),%eax
78         movl            %eax,LP_PARAM_OUT(%esp)
79         call            __ZN4dyld14bindLazySymbolEPK11mach_headerPm
80         movl            %eax,RESULT_BP(%ebp)    # store target for ret
81         movdqa          XMMM0_SAVE(%esp),%xmm0  # restore registers
82         movdqa          XMMM1_SAVE(%esp),%xmm1
83         movdqa          XMMM2_SAVE(%esp),%xmm2
84         movdqa          XMMM3_SAVE(%esp),%xmm3
85         movl            EAX_SAVE(%esp),%eax
86         movl            ECX_SAVE(%esp),%ecx
87         movl            EDX_SAVE(%esp),%edx
88         addl            $STACK_SIZE,%esp
89         popl            %ebp
90         addl            $4,%esp                                 # remove meta-parameter, other meta-parmaeter now holds target for ret
91         ret
92 #endif /* __i386__ */
93
94
95
96
97 #if __ppc__ || __ppc64__
98 #include <architecture/ppc/mode_independent_asm.h>
99 /*
100  * This is the interface for the stub_binding_helper for the ppc:
101  * The caller has placed in r11 the address of the a lazy pointer to be filled
102  * in with the value for the defined symbol and placed in r12 the address of
103  * the the mach header this pointer comes from.
104  *
105  * r11 address of lazy pointer
106  * r12 address of mach header
107  */
108 #define LRSAVE          MODE_CHOICE(8,16)
109 #define STACK_SIZE      MODE_CHOICE(144,288)
110 #define R3SAVE          MODE_CHOICE(56,112)
111 #define R4SAVE          MODE_CHOICE(60,120)
112 #define R5SAVE          MODE_CHOICE(64,128)
113 #define R6SAVE          MODE_CHOICE(68,136)
114 #define R7SAVE          MODE_CHOICE(72,144)
115 #define R8SAVE          MODE_CHOICE(76,152)
116 #define R9SAVE          MODE_CHOICE(80,160)
117 #define R10SAVE         MODE_CHOICE(84,168)
118
119   
120         .text
121         .align 2
122         .globl _stub_binding_helper_interface
123 _stub_binding_helper_interface:
124         mflr    r0                  ; get link register value
125         stg     r0,LRSAVE(r1)       ; save link register value in the linkage area
126         stgu    r1,-STACK_SIZE(r1)  ; save stack pointer and update it
127
128         stg     r3,R3SAVE(r1)   ; save all registers that could contain
129         stg     r4,R4SAVE(r1)   ;  parameters to the routine that is being
130         stg     r5,R5SAVE(r1)   ;  bound.
131         stg     r6,R6SAVE(r1)
132         stg     r7,R7SAVE(r1)
133         stg     r8,R8SAVE(r1)
134         stg     r9,R9SAVE(r1)
135         stg     r10,R10SAVE(r1)
136
137         mr      r3,r12          ; move address of mach header to 1st parameter
138         mr      r4,r11          ; move address of lazy pointer to 2nd parameter
139         ; call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address)
140         bl      __ZN4dyld14bindLazySymbolEPK11mach_headerPm
141         mr      r12,r3          ; move the symbol`s address into r12
142         mtctr   r12             ; move the symbol`s address into count register
143
144         lg      r0,STACK_SIZE+LRSAVE(r1)        ; get old link register value
145
146         lg      r3,R3SAVE(r1)   ; restore all registers that could contain
147         lg      r4,R4SAVE(r1)   ;  parameters to the routine that was bound.
148         lg      r5,R5SAVE(r1)
149         lg      r6,R6SAVE(r1)
150         lg      r7,R7SAVE(r1)
151         lg      r8,R8SAVE(r1)
152         lg      r9,R9SAVE(r1)
153         lg      r10,R10SAVE(r1)
154
155         addi    r1,r1,STACK_SIZE; restore old stack pointer
156         mtlr    r0              ; restore link register
157
158         bctr                    ; jump to the symbol`s address that was bound
159
160 #endif /* __ppc__ */
161
162
163
164
165
166
167
168
169
170
171