1/*
2 * Copyright (c) 1999-2008 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
25
26#if __i386__
27/*
28 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for i386
29 * on versions before Macs OS X 10.6.  On entry the address of the lazy pointer
30 * has been pushed on the stack.
31 *
32 * After the symbol has been resolved and the lazy pointer filled in, this jumps
33 * to the target address.
34 */
35#define LP_PARAM_OUT			0
36#define XMMM0_SAVE			16	/* 16-byte align */
37#define XMMM1_SAVE			32
38#define XMMM2_SAVE			48
39#define XMMM3_SAVE			64
40#define EAX_SAVE			84
41#define ECX_SAVE			88
42#define EDX_SAVE			92
43#define LP_LOCAL			96
44#define STACK_SIZE			104	/* must be 8 mod 16 so that stack winds up 16-byte aliged  */
45#define LP_OLD_BP_SAVE			104
46
47    .text
48    .align 4,0x90
49    .globl dyld_lazy_dylib_stub_binding_helper
50    .private_extern dyld_lazy_dylib_stub_binding_helper
51dyld_lazy_dylib_stub_binding_helper:
52	subl		$STACK_SIZE,%esp	    # makes stack 16-byte aligned
53	movl		%eax,EAX_SAVE(%esp)
54	movl		LP_OLD_BP_SAVE(%esp),%eax   # get lazy-pointer meta-parameter
55	movl		%eax,LP_LOCAL(%esp)
56	movl		%ebp,LP_OLD_BP_SAVE(%esp)   # store epb back chain
57	movl		%esp,%ebp		    # set epb to be this frame
58	add		$LP_OLD_BP_SAVE,%ebp
59	movl		%ecx,ECX_SAVE(%esp)
60	movl		%edx,EDX_SAVE(%esp)
61	movdqu		%xmm0,XMMM0_SAVE(%esp)
62	movdqu		%xmm1,XMMM1_SAVE(%esp)
63	movdqu		%xmm2,XMMM2_SAVE(%esp)
64	movdqu		%xmm3,XMMM3_SAVE(%esp)
65	movl		LP_LOCAL(%esp),%eax
66	movl		%eax,LP_PARAM_OUT(%esp) # call lazy_load_dylib(lazy_ptr)
67	call		_lazy_load_dylib
68	movdqu		XMMM0_SAVE(%esp),%xmm0	# restore registers
69	movdqu		XMMM1_SAVE(%esp),%xmm1
70	movdqu		XMMM2_SAVE(%esp),%xmm2
71	movdqu		XMMM3_SAVE(%esp),%xmm3
72	movl		ECX_SAVE(%esp),%ecx
73	movl		EDX_SAVE(%esp),%edx
74	movl		%eax,%ebp		# move target address to epb
75	movl		EAX_SAVE(%esp),%eax	# restore eax
76	addl		$STACK_SIZE,%esp	# cut back stack
77	xchg		%ebp, (%esp)		# restore ebp and set target to top of stack
78	ret					# jump to target
79
80#endif /* __i386__ */
81
82
83#if __x86_64__
84/*
85 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for x86_64
86 * on versions before Macs OS X 10.6.  On entry r11 contains address of the
87 * lazy pointer.
88 *
89 * All parameters registers must be preserved.
90 *
91 * After the symbol has been resolved and the pointer filled in this is to pop
92 * these arguments off the stack and jump to the address of the defined symbol.
93 */
94#define RDI_SAVE			0
95#define RSI_SAVE			8
96#define RDX_SAVE			16
97#define RCX_SAVE			24
98#define R8_SAVE				32
99#define R9_SAVE				40
100#define RAX_SAVE			48
101#define XMMM0_SAVE			64    /* 16-byte align */
102#define XMMM1_SAVE			80
103#define XMMM2_SAVE			96
104#define XMMM3_SAVE			112
105#define XMMM4_SAVE			128
106#define XMMM5_SAVE			144
107#define XMMM6_SAVE			160
108#define XMMM7_SAVE			176
109#define STACK_SIZE			192 /*  (XMMM7_SAVE+16) must be 16 byte aligned too */
110
111    .text
112    .align 2,0x90
113    .globl dyld_lazy_dylib_stub_binding_helper
114    .private_extern dyld_lazy_dylib_stub_binding_helper
115dyld_lazy_dylib_stub_binding_helper:
116	pushq		%rbp
117	movq		%rsp,%rbp
118	subq		$STACK_SIZE,%rsp
119	movq		%rdi,RDI_SAVE(%rsp)	# save registers that might be used as parameters
120	movq		%rsi,RSI_SAVE(%rsp)
121	movq		%rdx,RDX_SAVE(%rsp)
122	movq		%rcx,RCX_SAVE(%rsp)
123	movq		%r8,R8_SAVE(%rsp)
124	movq		%r9,R9_SAVE(%rsp)
125	movq		%rax,RAX_SAVE(%rsp)
126	movdqa		%xmm0,XMMM0_SAVE(%rsp)
127	movdqa		%xmm1,XMMM1_SAVE(%rsp)
128	movdqa		%xmm2,XMMM2_SAVE(%rsp)
129	movdqa		%xmm3,XMMM3_SAVE(%rsp)
130	movdqa		%xmm4,XMMM4_SAVE(%rsp)
131	movdqa		%xmm5,XMMM5_SAVE(%rsp)
132	movdqa		%xmm6,XMMM6_SAVE(%rsp)
133	movdqa		%xmm7,XMMM7_SAVE(%rsp)
134	movq		%r11,%rdi			# call lazy_load_dylib(lazy_ptr)
135	call		_lazy_load_dylib
136	movq		%rax,%r11			# save target
137	movdqa		XMMM0_SAVE(%rsp),%xmm0	# restore registers
138	movdqa		XMMM1_SAVE(%rsp),%xmm1
139	movdqa		XMMM2_SAVE(%rsp),%xmm2
140	movdqa		XMMM3_SAVE(%rsp),%xmm3
141	movdqa		XMMM4_SAVE(%rsp),%xmm4
142	movdqa		XMMM5_SAVE(%rsp),%xmm5
143	movdqa		XMMM6_SAVE(%rsp),%xmm6
144	movdqa		XMMM7_SAVE(%rsp),%xmm7
145	movq		RDI_SAVE(%rsp),%rdi
146	movq		RSI_SAVE(%rsp),%rsi
147	movq		RDX_SAVE(%rsp),%rdx
148	movq		RCX_SAVE(%rsp),%rcx
149	movq		R8_SAVE(%rsp),%r8
150	movq		R9_SAVE(%rsp),%r9
151	movq		RAX_SAVE(%rsp),%rax
152	addq		$STACK_SIZE,%rsp
153	popq		%rbp
154	jmp			*%r11			# jmp to target
155
156#endif
157
158
159#if __ppc__ || __ppc64__
160#include <architecture/ppc/mode_independent_asm.h>
161/*
162 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for ppc
163 * on versions before Macs OS X 10.6.  On entry r11 contains address of the
164 * lazy pointer to be filled
165 *
166 * r11 address of lazy pointer
167 */
168#define LRSAVE		MODE_CHOICE(8,16)
169#define STACK_SIZE	MODE_CHOICE(144,288)
170#define R3SAVE          MODE_CHOICE(56,112)
171#define R4SAVE          MODE_CHOICE(60,120)
172#define R5SAVE          MODE_CHOICE(64,128)
173#define R6SAVE          MODE_CHOICE(68,136)
174#define R7SAVE          MODE_CHOICE(72,144)
175#define R8SAVE          MODE_CHOICE(76,152)
176#define R9SAVE          MODE_CHOICE(80,160)
177#define R10SAVE         MODE_CHOICE(84,168)
178
179
180	.text
181	.align 2
182    .globl dyld_lazy_dylib_stub_binding_helper
183    .private_extern dyld_lazy_dylib_stub_binding_helper
184dyld_lazy_dylib_stub_binding_helper:
185	mflr	r0		    ; get link register value
186	stg	r0,LRSAVE(r1)	    ; save link register value in the linkage area
187	stgu	r1,-STACK_SIZE(r1)  ; save stack pointer and update it
188
189	stg	r3,R3SAVE(r1)	; save all registers that could contain
190	stg	r4,R4SAVE(r1)	;  parameters to the routine that is being
191	stg	r5,R5SAVE(r1)	;  bound.
192	stg	r6,R6SAVE(r1)
193	stg	r7,R7SAVE(r1)
194	stg	r8,R8SAVE(r1)
195	stg	r9,R9SAVE(r1)
196	stg	r10,R10SAVE(r1)
197
198	mr	r3,r11		; move address of lazy pointer to 1st parameter
199				; call lazy_load_dylib(lazy_ptr)
200	bl	_lazy_load_dylib
201	mr	r12,r3		; move the symbol`s address into r12
202	mtctr	r12		; move the symbol`s address into count register
203
204	lg	r0,STACK_SIZE+LRSAVE(r1)	; get old link register value
205
206	lg	r3,R3SAVE(r1)	; restore all registers that could contain
207	lg	r4,R4SAVE(r1)	;  parameters to the routine that was bound.
208	lg	r5,R5SAVE(r1)
209	lg	r6,R6SAVE(r1)
210	lg	r7,R7SAVE(r1)
211	lg	r8,R8SAVE(r1)
212	lg	r9,R9SAVE(r1)
213	lg	r10,R10SAVE(r1)
214
215	addi	r1,r1,STACK_SIZE; restore old stack pointer
216	mtlr	r0		; restore link register
217
218	bctr			; jump to the symbol`s address that was bound
219
220#endif /* __ppc__ */
221
222#if __arm__
223/*
224 * This is the implementation of dyld_lazy_dylib_stub_binding_helper for ARM
225 * The caller has pushed the address of the a lazy pointer to be filled in with
226 * the value for the defined symbol
227 *
228 * ip        address of lazy pointer
229 *
230 * After the symbol has been resolved and the pointer filled in this is to pop
231 * these arguments off the stack and jump to the address of the defined symbol.
232 */
233	.text
234	.align 2
235    .globl dyld_lazy_dylib_stub_binding_helper
236    .private_extern dyld_lazy_dylib_stub_binding_helper
237dyld_lazy_dylib_stub_binding_helper:
238	stmfd	sp!, {r0,r1,r2,r3,r7,lr}	// save registers
239	add	r7, sp, #16			// point FP to previous FP
240
241	mov	r0, ip				// move address of lazy pointer to 1st parameter
242						// call lazy_load_dylib(lazy_ptr)
243	bl	_lazy_load_dylib
244	mov	ip, r0				// move the symbol`s address into ip
245
246	ldmfd	sp!, {r0,r1,r2,r3,r7,lr}	// restore registers
247
248	bx	ip				// jump to the symbol`s address that was bound
249
250#endif /* __arm__ */
251
252
253
254
255// This code has be written to allow dead code stripping
256	.subsections_via_symbols
257
258
259
260
261
262