]> git.saurik.com Git - apple/dyld.git/blob - src/dyld_stub_binder.s
dyld-851.27.tar.gz
[apple/dyld.git] / src / dyld_stub_binder.s
1 /*
2 * Copyright (c) 2008-2013 Apple 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 #include <TargetConditionals.h>
25
26 #include <System/machine/cpu_capabilities.h>
27
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
60 add $LP_OLD_BP_SAVE,%ebp
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
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
117
118 /*
119 * sp+16 return address
120 * sp+8 lazy binding info offset
121 * sp+0 address of ImageLoader cache
122 */
123 .align 2,0x90
124 .globl dyld_stub_binder
125 dyld_stub_binder:
126 pushq %rbp
127 test $0xF,%rsp # at this point stack should be 16-byte aligned
128 jne _stack_not_16_byte_aligned_error
129 movq %rsp,%rbp
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
202 call __Z21_dyld_fast_stub_entryPvl
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
234 popq %rbp
235 addq $16,%rsp # remove meta-parameters
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
251
252 #endif
253
254
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
271 #if __ARM_ARCH_7K__
272 vpush {d0, d1, d2, d3, d4, d5, d6, d7}
273 sub sp, sp, #8 // Align stack to 16 bytes.
274 #endif
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
279 #if __ARM_ARCH_7K__
280 add sp, sp, #8
281 vpop {d0, d1, d2, d3, d4, d5, d6, d7}
282 #endif
283
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__ */
290
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
319
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]
330
331 mov sp, fp
332 ldp fp, lr, [sp], #16
333 add sp, sp, #16 ; remove meta-parameters
334 #if __arm64e__
335 // Note arm64e executables will never hit this line as they don't have lazy binding.
336 // However, arm64 binaries running on an arm64e system will hit this line but the
337 // authentication won't have any effect there.
338 braaz x16
339 #else
340 br x16
341 #endif
342
343 #endif
344