dyld-732.8.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