dyld-46.16.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 #if __x86_64__
97 /*
98  * This is the interface for the stub_binding_helper for x86_64:
99  * The caller has pushed the address of the a lazy pointer to be filled in with
100  * the value for the defined symbol and pushed the address of the the mach
101  * header this pointer comes from.
102  *
103  * sp+4 address of lazy pointer
104  * sp+0 address of mach header
105  *
106  * All parameters registers must be preserved.
107  * 
108  * After the symbol has been resolved and the pointer filled in this is to pop
109  * these arguments off the stack and jump to the address of the defined symbol.
110  */
111 #define MH_PARAM_BP                     8
112 #define LP_PARAM_BP                     16
113
114 #define RDI_SAVE                        0
115 #define RSI_SAVE                        8
116 #define RDX_SAVE                        16
117 #define RCX_SAVE                        24
118 #define R8_SAVE                         32
119 #define R9_SAVE                         40
120 #define RAX_SAVE                        48
121 #define XMMM0_SAVE                      64    /* 16-byte align */
122 #define XMMM1_SAVE                      80
123 #define XMMM2_SAVE                      96
124 #define XMMM3_SAVE                      112
125 #define XMMM4_SAVE                      128
126 #define XMMM5_SAVE                      144
127 #define XMMM6_SAVE                      160
128 #define XMMM7_SAVE                      176
129 #define STACK_SIZE                      192 /*  (XMMM7_SAVE+16) must be 16 byte aligned too */
130     
131     .text
132     .align 2,0x90
133     .globl _stub_binding_helper_interface
134 _stub_binding_helper_interface:
135         pushq           %rbp
136         movq            %rsp,%rbp
137         subq            $STACK_SIZE,%rsp        # at this point stack is 16-byte aligned because two meta-parameters where pushed
138         movq            %rdi,RDI_SAVE(%rsp)     # save registers that might be used as parameters
139         movq            %rsi,RSI_SAVE(%rsp)
140         movq            %rdx,RDX_SAVE(%rsp)
141         movq            %rcx,RCX_SAVE(%rsp)
142         movq            %r8,R8_SAVE(%rsp)
143         movq            %r9,R9_SAVE(%rsp)
144         movq            %rax,RAX_SAVE(%rsp)
145         movdqa          %xmm0,XMMM0_SAVE(%rsp)
146         movdqa          %xmm1,XMMM1_SAVE(%rsp)
147         movdqa          %xmm2,XMMM2_SAVE(%rsp)
148         movdqa          %xmm3,XMMM3_SAVE(%rsp)
149         movdqa          %xmm4,XMMM4_SAVE(%rsp)
150         movdqa          %xmm5,XMMM5_SAVE(%rsp)
151         movdqa          %xmm6,XMMM6_SAVE(%rsp)
152         movdqa          %xmm7,XMMM7_SAVE(%rsp)
153         movq            MH_PARAM_BP(%rbp),%rdi  # call dyld::bindLazySymbol(mh, lazy_ptr)
154         movq            LP_PARAM_BP(%rbp),%rsi
155         call            __ZN4dyld14bindLazySymbolEPK11mach_headerPm
156         movq            %rax,%r11               # save target
157         movdqa          XMMM0_SAVE(%rsp),%xmm0  # restore registers
158         movdqa          XMMM1_SAVE(%rsp),%xmm1
159         movdqa          XMMM2_SAVE(%rsp),%xmm2
160         movdqa          XMMM3_SAVE(%rsp),%xmm3
161         movdqa          XMMM4_SAVE(%rsp),%xmm4
162         movdqa          XMMM5_SAVE(%rsp),%xmm5
163         movdqa          XMMM6_SAVE(%rsp),%xmm6
164         movdqa          XMMM7_SAVE(%rsp),%xmm7
165         movq            RDI_SAVE(%rsp),%rdi
166         movq            RSI_SAVE(%rsp),%rsi
167         movq            RDX_SAVE(%rsp),%rdx
168         movq            RCX_SAVE(%rsp),%rcx
169         movq            R8_SAVE(%rsp),%r8
170         movq            R9_SAVE(%rsp),%r9
171         movq            RAX_SAVE(%rsp),%rax
172         addq            $STACK_SIZE,%rsp
173         popq            %rbp
174         addq            $16,%rsp                # remove meta-parameters
175         jmp             *%r11                   # jmp to target
176
177 #endif
178
179 #if __ppc__ || __ppc64__
180 #include <architecture/ppc/mode_independent_asm.h>
181 /*
182  * This is the interface for the stub_binding_helper for the ppc:
183  * The caller has placed in r11 the address of the a lazy pointer to be filled
184  * in with the value for the defined symbol and placed in r12 the address of
185  * the the mach header this pointer comes from.
186  *
187  * r11 address of lazy pointer
188  * r12 address of mach header
189  */
190 #define LRSAVE          MODE_CHOICE(8,16)
191 #define STACK_SIZE      MODE_CHOICE(144,288)
192 #define R3SAVE          MODE_CHOICE(56,112)
193 #define R4SAVE          MODE_CHOICE(60,120)
194 #define R5SAVE          MODE_CHOICE(64,128)
195 #define R6SAVE          MODE_CHOICE(68,136)
196 #define R7SAVE          MODE_CHOICE(72,144)
197 #define R8SAVE          MODE_CHOICE(76,152)
198 #define R9SAVE          MODE_CHOICE(80,160)
199 #define R10SAVE         MODE_CHOICE(84,168)
200
201   
202         .text
203         .align 2
204         .globl _stub_binding_helper_interface
205 _stub_binding_helper_interface:
206         mflr    r0                  ; get link register value
207         stg     r0,LRSAVE(r1)       ; save link register value in the linkage area
208         stgu    r1,-STACK_SIZE(r1)  ; save stack pointer and update it
209
210         stg     r3,R3SAVE(r1)   ; save all registers that could contain
211         stg     r4,R4SAVE(r1)   ;  parameters to the routine that is being
212         stg     r5,R5SAVE(r1)   ;  bound.
213         stg     r6,R6SAVE(r1)
214         stg     r7,R7SAVE(r1)
215         stg     r8,R8SAVE(r1)
216         stg     r9,R9SAVE(r1)
217         stg     r10,R10SAVE(r1)
218
219         mr      r3,r12          ; move address of mach header to 1st parameter
220         mr      r4,r11          ; move address of lazy pointer to 2nd parameter
221         ; call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address)
222         bl      __ZN4dyld14bindLazySymbolEPK11mach_headerPm
223         mr      r12,r3          ; move the symbol`s address into r12
224         mtctr   r12             ; move the symbol`s address into count register
225
226         lg      r0,STACK_SIZE+LRSAVE(r1)        ; get old link register value
227
228         lg      r3,R3SAVE(r1)   ; restore all registers that could contain
229         lg      r4,R4SAVE(r1)   ;  parameters to the routine that was bound.
230         lg      r5,R5SAVE(r1)
231         lg      r6,R6SAVE(r1)
232         lg      r7,R7SAVE(r1)
233         lg      r8,R8SAVE(r1)
234         lg      r9,R9SAVE(r1)
235         lg      r10,R10SAVE(r1)
236
237         addi    r1,r1,STACK_SIZE; restore old stack pointer
238         mtlr    r0              ; restore link register
239
240         bctr                    ; jump to the symbol`s address that was bound
241
242 #endif /* __ppc__ */
243
244
245
246
247
248
249
250
251
252
253