]>
Commit | Line | Data |
---|---|---|
39a8cd10 | 1 | /* |
2fd3f4e8 | 2 | * Copyright (c) 2008-2013 Apple Inc. All rights reserved. |
39a8cd10 A |
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 | ||
2fd3f4e8 | 24 | #include <TargetConditionals.h> |
39a8cd10 | 25 | |
2fd3f4e8 A |
26 | #include <System/machine/cpu_capabilities.h> |
27 | ||
39a8cd10 A |
28 | |
29 | #ifdef __i386__ | |
30 | ||
31 | #define MH_PARAM_OUT 0 | |
32 | #define LP_PARAM_OUT 4 | |
33 | #define XMMM0_SAVE 16 /* 16-byte align */ | |
34 | #define XMMM1_SAVE 32 | |
35 | #define XMMM2_SAVE 48 | |
36 | #define XMMM3_SAVE 64 | |
37 | #define EAX_SAVE 84 | |
38 | #define ECX_SAVE 88 | |
39 | #define EDX_SAVE 92 | |
40 | #define LP_LOCAL 96 | |
41 | #define MH_LOCAL 100 | |
42 | #define STACK_SIZE 100 /* must be 4 mod 16 so that stack winds up 16-byte aliged */ | |
43 | #define LP_OLD_BP_SAVE 104 | |
44 | ||
45 | /* | |
46 | * sp+4 lazy binding info offset | |
47 | * sp+0 address of ImageLoader cache | |
48 | */ | |
49 | .text | |
50 | .align 4,0x90 | |
51 | .globl dyld_stub_binder | |
52 | .globl _misaligned_stack_error | |
53 | dyld_stub_binder: | |
54 | subl $STACK_SIZE,%esp # makes stack 16-byte aligned | |
55 | movl %eax,EAX_SAVE(%esp) | |
56 | movl LP_OLD_BP_SAVE(%esp),%eax # get lazy-pointer meta-parameter | |
57 | movl %eax,LP_LOCAL(%esp) | |
58 | movl %ebp,LP_OLD_BP_SAVE(%esp) # store epb back chain | |
59 | movl %esp,%ebp # set epb to be this frame | |
2fd3f4e8 | 60 | add $LP_OLD_BP_SAVE,%ebp |
39a8cd10 A |
61 | movl %ecx,ECX_SAVE(%esp) |
62 | movl %edx,EDX_SAVE(%esp) | |
63 | .align 0,0x90 | |
64 | _misaligned_stack_error_: | |
65 | movdqa %xmm0,XMMM0_SAVE(%esp) | |
66 | movdqa %xmm1,XMMM1_SAVE(%esp) | |
67 | movdqa %xmm2,XMMM2_SAVE(%esp) | |
68 | movdqa %xmm3,XMMM3_SAVE(%esp) | |
69 | dyld_stub_binder_: | |
70 | movl MH_LOCAL(%esp),%eax # call dyld::fastBindLazySymbol(loadercache, lazyinfo) | |
71 | movl %eax,MH_PARAM_OUT(%esp) | |
72 | movl LP_LOCAL(%esp),%eax | |
73 | movl %eax,LP_PARAM_OUT(%esp) | |
74 | call __Z21_dyld_fast_stub_entryPvl | |
75 | movdqa XMMM0_SAVE(%esp),%xmm0 # restore registers | |
76 | movdqa XMMM1_SAVE(%esp),%xmm1 | |
77 | movdqa XMMM2_SAVE(%esp),%xmm2 | |
78 | movdqa XMMM3_SAVE(%esp),%xmm3 | |
79 | movl ECX_SAVE(%esp),%ecx | |
80 | movl EDX_SAVE(%esp),%edx | |
81 | movl %eax,%ebp # move target address to epb | |
82 | movl EAX_SAVE(%esp),%eax # restore eax | |
83 | addl $STACK_SIZE+4,%esp # cut back stack | |
84 | xchg %ebp, (%esp) # restore ebp and set target to top of stack | |
85 | ret # jump to target | |
86 | ||
87 | ||
88 | #endif /* __i386__ */ | |
89 | ||
90 | ||
91 | #if __x86_64__ | |
92 | ||
19894a12 A |
93 | #define RET_ADDR_RBP 24 |
94 | #define LP_PARAM_RBP 16 | |
95 | #define MH_PARAM_RBP 8 | |
96 | #define OLD_RBP_RBP 0 | |
97 | ||
98 | #define RDI_SAVE_RBP -8 | |
99 | #define RSI_SAVE_RBP -16 | |
100 | #define RDX_SAVE_RBP -24 | |
101 | #define RCX_SAVE_RBP -32 | |
102 | #define RBX_SAVE_RBP -40 | |
103 | #define RAX_SAVE_RBP -48 | |
104 | #define R8_SAVE_RBP -56 | |
105 | #define R9_SAVE_RBP -64 | |
106 | #define STATIC_STACK_SIZE 256 // extra padding to allow it to be 64-byte aligned | |
107 | ||
108 | #define XMM0_SAVE_RSP 0x00 | |
109 | #define XMM1_SAVE_RSP 0x10 | |
110 | #define XMM2_SAVE_RSP 0x20 | |
111 | #define XMM3_SAVE_RSP 0x30 | |
112 | #define XMM4_SAVE_RSP 0x40 | |
113 | #define XMM5_SAVE_RSP 0x50 | |
114 | #define XMM6_SAVE_RSP 0x60 | |
115 | #define XMM7_SAVE_RSP 0x70 | |
116 | ||
39a8cd10 A |
117 | |
118 | /* | |
19894a12 A |
119 | * sp+16 return address |
120 | * sp+8 lazy binding info offset | |
121 | * sp+0 address of ImageLoader cache | |
39a8cd10 A |
122 | */ |
123 | .align 2,0x90 | |
124 | .globl dyld_stub_binder | |
125 | dyld_stub_binder: | |
126 | pushq %rbp | |
19894a12 A |
127 | test $0xF,%rsp # at this point stack should be 16-byte aligned |
128 | jne _stack_not_16_byte_aligned_error | |
39a8cd10 | 129 | movq %rsp,%rbp |
19894a12 A |
130 | subq $STATIC_STACK_SIZE,%rsp |
131 | movq %rdi,RDI_SAVE_RBP(%rbp) # save registers that might be used as parameters | |
132 | movq %rsi,RSI_SAVE_RBP(%rbp) | |
133 | movq %rdx,RDX_SAVE_RBP(%rbp) | |
134 | movq %rcx,RCX_SAVE_RBP(%rbp) | |
135 | movq %rbx,RBX_SAVE_RBP(%rbp) | |
136 | movq %rax,RAX_SAVE_RBP(%rbp) | |
137 | movq %r8, R8_SAVE_RBP(%rbp) | |
138 | movq %r9, R9_SAVE_RBP(%rbp) | |
139 | ||
140 | cmpl $0, _inited(%rip) | |
141 | jne Linited | |
142 | movl $0x01,%eax | |
143 | cpuid # get cpu features to check on xsave instruction support | |
144 | andl $0x08000000,%ecx # check OSXSAVE bit | |
145 | movl %ecx,_hasXSave(%rip) | |
146 | cmpl $0, %ecx | |
147 | jne LxsaveInfo | |
148 | movl $1, _inited(%rip) | |
149 | jmp Lsse | |
150 | ||
151 | LxsaveInfo: | |
152 | movl $0x0D,%eax | |
153 | movl $0x00,%ecx | |
154 | cpuid # get xsave parameter info | |
155 | movl %eax,_features_lo32(%rip) | |
156 | movl %edx,_features_hi32(%rip) | |
157 | movl %ecx,_bufferSize32(%rip) | |
158 | movl $1, _inited(%rip) | |
159 | ||
160 | Linited: | |
161 | cmpl $0, _hasXSave(%rip) | |
162 | jne Lxsave | |
163 | ||
164 | Lsse: | |
165 | subq $128, %rsp | |
166 | movdqa %xmm0, XMM0_SAVE_RSP(%rsp) | |
167 | movdqa %xmm1, XMM1_SAVE_RSP(%rsp) | |
168 | movdqa %xmm2, XMM2_SAVE_RSP(%rsp) | |
169 | movdqa %xmm3, XMM3_SAVE_RSP(%rsp) | |
170 | movdqa %xmm4, XMM4_SAVE_RSP(%rsp) | |
171 | movdqa %xmm5, XMM5_SAVE_RSP(%rsp) | |
172 | movdqa %xmm6, XMM6_SAVE_RSP(%rsp) | |
173 | movdqa %xmm7, XMM7_SAVE_RSP(%rsp) | |
174 | jmp Lbind | |
175 | ||
176 | Lxsave: | |
177 | movl _bufferSize32(%rip),%eax | |
178 | movq %rsp, %rdi | |
179 | subq %rax, %rdi # stack alloc buffer | |
180 | andq $-64, %rdi # 64-byte align stack | |
181 | movq %rdi, %rsp | |
182 | # xsave requires buffer to be zero'ed out | |
183 | movq $0, %rcx | |
184 | movq %rdi, %r8 | |
185 | movq %rdi, %r9 | |
186 | addq %rax, %r9 | |
187 | Lz: movq %rcx, (%r8) | |
188 | addq $8, %r8 | |
189 | cmpq %r8,%r9 | |
190 | ja Lz | |
191 | ||
192 | movl _features_lo32(%rip),%eax | |
193 | movl _features_hi32(%rip),%edx | |
194 | # call xsave with buffer on stack and eax:edx flag bits | |
195 | # note: do not use xsaveopt, it assumes you are using the same | |
196 | # buffer as previous xsaves, and this thread is on the same cpu. | |
197 | xsave (%rsp) | |
198 | ||
199 | Lbind: | |
200 | movq MH_PARAM_RBP(%rbp),%rdi # call fastBindLazySymbol(loadercache, lazyinfo) | |
201 | movq LP_PARAM_RBP(%rbp),%rsi | |
39a8cd10 | 202 | call __Z21_dyld_fast_stub_entryPvl |
19894a12 A |
203 | movq %rax,%r11 # copy jump target |
204 | ||
205 | cmpl $0, _hasXSave(%rip) | |
206 | jne Lxrstror | |
207 | ||
208 | movdqa XMM0_SAVE_RSP(%rsp),%xmm0 | |
209 | movdqa XMM1_SAVE_RSP(%rsp),%xmm1 | |
210 | movdqa XMM2_SAVE_RSP(%rsp),%xmm2 | |
211 | movdqa XMM3_SAVE_RSP(%rsp),%xmm3 | |
212 | movdqa XMM4_SAVE_RSP(%rsp),%xmm4 | |
213 | movdqa XMM5_SAVE_RSP(%rsp),%xmm5 | |
214 | movdqa XMM6_SAVE_RSP(%rsp),%xmm6 | |
215 | movdqa XMM7_SAVE_RSP(%rsp),%xmm7 | |
216 | jmp Ldone | |
217 | ||
218 | Lxrstror: | |
219 | movl _features_lo32(%rip),%eax | |
220 | movl _features_hi32(%rip),%edx | |
221 | # call xsave with buffer on stack and eax:edx flag bits | |
222 | xrstor (%rsp) | |
223 | ||
224 | Ldone: | |
225 | movq RDI_SAVE_RBP(%rbp),%rdi | |
226 | movq RSI_SAVE_RBP(%rbp),%rsi | |
227 | movq RDX_SAVE_RBP(%rbp),%rdx | |
228 | movq RCX_SAVE_RBP(%rbp),%rcx | |
229 | movq RBX_SAVE_RBP(%rbp),%rbx | |
230 | movq RAX_SAVE_RBP(%rbp),%rax | |
231 | movq R8_SAVE_RBP(%rbp),%r8 | |
232 | movq R9_SAVE_RBP(%rbp),%r9 | |
233 | movq %rbp,%rsp | |
39a8cd10 A |
234 | popq %rbp |
235 | addq $16,%rsp # remove meta-parameters | |
19894a12 A |
236 | jmp *%r11 # jmp to target |
237 | ||
238 | _stack_not_16_byte_aligned_error: | |
239 | movdqa %xmm0, 0(%rsp) | |
240 | int3 | |
241 | ||
242 | .data | |
243 | # Cached info from cpuid. These must be lazily evaluated. | |
244 | # You cannot initalize these from _dyld_initializer() because | |
245 | # that function is called from another dylib... | |
246 | _inited: .long 0 | |
247 | _features_lo32: .long 0 | |
248 | _features_hi32: .long 0 | |
249 | _bufferSize32: .long 0 | |
250 | _hasXSave: .long 0 | |
39a8cd10 A |
251 | |
252 | #endif | |
253 | ||
254 | ||
412ebb8e A |
255 | #if __arm__ |
256 | /* | |
257 | * sp+4 lazy binding info offset | |
258 | * sp+0 address of ImageLoader cache | |
259 | */ | |
260 | ||
261 | .text | |
262 | .align 2 | |
263 | .globl dyld_stub_binder | |
264 | dyld_stub_binder: | |
265 | stmfd sp!, {r0,r1,r2,r3,r7,lr} // save registers | |
266 | add r7, sp, #16 // point FP to previous FP | |
267 | ||
268 | ldr r0, [sp, #24] // move address ImageLoader cache to 1st parameter | |
269 | ldr r1, [sp, #28] // move lazy info offset 2nd parameter | |
270 | ||
19894a12 A |
271 | #if __ARM_ARCH_7K__ |
272 | vpush {d0, d1, d2, d3, d4, d5, d6, d7} | |
df9d6cf7 | 273 | sub sp, sp, #8 // Align stack to 16 bytes. |
19894a12 | 274 | #endif |
412ebb8e A |
275 | // call dyld::fastBindLazySymbol(loadercache, lazyinfo) |
276 | bl __Z21_dyld_fast_stub_entryPvl | |
277 | mov ip, r0 // move the symbol`s address into ip | |
278 | ||
19894a12 | 279 | #if __ARM_ARCH_7K__ |
df9d6cf7 | 280 | add sp, sp, #8 |
19894a12 A |
281 | vpop {d0, d1, d2, d3, d4, d5, d6, d7} |
282 | #endif | |
283 | ||
412ebb8e A |
284 | ldmfd sp!, {r0,r1,r2,r3,r7,lr} // restore registers |
285 | add sp, sp, #8 // remove meta-parameters | |
286 | ||
287 | bx ip // jump to the symbol`s address that was bound | |
288 | ||
289 | #endif /* __arm__ */ | |
39a8cd10 | 290 | |
19894a12 A |
291 | |
292 | #if __arm64__ | |
293 | /* | |
294 | * sp+0 lazy binding info offset | |
295 | * sp+8 address of ImageLoader cache | |
296 | */ | |
297 | .text | |
298 | .align 2 | |
299 | .globl dyld_stub_binder | |
300 | dyld_stub_binder: | |
301 | stp fp, lr, [sp, #-16]! | |
302 | mov fp, sp | |
303 | sub sp, sp, #240 | |
304 | stp x0,x1, [fp, #-16] ; x0-x7 are int parameter registers | |
305 | stp x2,x3, [fp, #-32] | |
306 | stp x4,x5, [fp, #-48] | |
307 | stp x6,x7, [fp, #-64] | |
308 | stp x8,x9, [fp, #-80] ; x8 is used for struct returns | |
309 | stp q0,q1, [fp, #-128] ; q0-q7 are vector/fp parameter registers | |
310 | stp q2,q3, [fp, #-160] | |
311 | stp q4,q5, [fp, #-192] | |
312 | stp q6,q7, [fp, #-224] | |
313 | ||
314 | ldr x0, [fp, #24] ; move address ImageLoader cache to 1st parameter | |
315 | ldr x1, [fp, #16] ; move lazy info offset 2nd parameter | |
316 | ; call dyld::fastBindLazySymbol(loadercache, lazyinfo) | |
317 | bl __Z21_dyld_fast_stub_entryPvl | |
318 | mov x16,x0 ; save target function address in lr | |
2fd3f4e8 | 319 | |
19894a12 A |
320 | ; restore parameter registers |
321 | ldp x0,x1, [fp, #-16] | |
322 | ldp x2,x3, [fp, #-32] | |
323 | ldp x4,x5, [fp, #-48] | |
324 | ldp x6,x7, [fp, #-64] | |
325 | ldp x8,x9, [fp, #-80] | |
326 | ldp q0,q1, [fp, #-128] | |
327 | ldp q2,q3, [fp, #-160] | |
328 | ldp q4,q5, [fp, #-192] | |
329 | ldp q6,q7, [fp, #-224] | |
2fd3f4e8 | 330 | |
19894a12 A |
331 | mov sp, fp |
332 | ldp fp, lr, [sp], #16 | |
333 | add sp, sp, #16 ; remove meta-parameters | |
334 | br x16 | |
335 | ||
336 | #endif | |
337 |