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
30 * and pushed the address of the the mach header this pointer comes from.
31 *
32 * sp+4	address of lazy pointer
33 * sp+0	address of mach header
34 *
35 * Some inter-image function calls pass parameters in registers EAX, ECX, EDX, or XXM0-3,
36 * Therefore those registers need to be preserved during the lazy binding.
37 *
38 * After the symbol has been resolved and the lazy pointer filled in, this jumps
39 * to the target address.
40 */
41#define MH_PARAM_OUT			0
42#define LP_PARAM_OUT			4
43#define XMMM0_SAVE			16	/* 16-byte align */
44#define XMMM1_SAVE			32
45#define XMMM2_SAVE			48
46#define XMMM3_SAVE			64
47#define EAX_SAVE			84
48#define ECX_SAVE			88
49#define EDX_SAVE			92
50#define LP_LOCAL			96
51#define MH_LOCAL			100
52#define STACK_SIZE			100	/* must be 4 mod 16 so that stack winds up 16-byte aliged  */
53#define LP_OLD_BP_SAVE			104
54
55    .text
56    .align 4,0x90
57	.globl _stub_binding_helper_i386_old
58_stub_binding_helper_i386_old:
59	pushl		$0
60    .globl _stub_binding_helper
61    .globl _misaligned_stack_error
62_stub_binding_helper:
63	subl		$STACK_SIZE,%esp	    # makes stack 16-byte aligned
64	movl		%eax,EAX_SAVE(%esp)
65	movl		LP_OLD_BP_SAVE(%esp),%eax   # get lazy-pointer meta-parameter
66	movl		%eax,LP_LOCAL(%esp)
67	movl		%ebp,LP_OLD_BP_SAVE(%esp)   # store epb back chain
68	movl		%esp,%ebp		    # set epb to be this frame
69	add		$LP_OLD_BP_SAVE,%ebp
70	movl		%ecx,ECX_SAVE(%esp)
71	movl		%edx,EDX_SAVE(%esp)
72	.align 0,0x90
73_misaligned_stack_error:
74	movdqa		%xmm0,XMMM0_SAVE(%esp)
75	movdqa		%xmm1,XMMM1_SAVE(%esp)
76	movdqa		%xmm2,XMMM2_SAVE(%esp)
77	movdqa		%xmm3,XMMM3_SAVE(%esp)
78_stub_binding_helper_interface2:
79	movl		MH_LOCAL(%esp),%eax	# call dyld::bindLazySymbol(mh, lazy_ptr)
80	movl		%eax,MH_PARAM_OUT(%esp)
81	movl		LP_LOCAL(%esp),%eax
82	movl		%eax,LP_PARAM_OUT(%esp)
83	call		__ZN4dyld14bindLazySymbolEPK11mach_headerPm
84	movdqa		XMMM0_SAVE(%esp),%xmm0	# restore registers
85	movdqa		XMMM1_SAVE(%esp),%xmm1
86	movdqa		XMMM2_SAVE(%esp),%xmm2
87	movdqa		XMMM3_SAVE(%esp),%xmm3
88	movl		ECX_SAVE(%esp),%ecx
89	movl		EDX_SAVE(%esp),%edx
90	movl		%eax,%ebp		# move target address to epb
91	movl		EAX_SAVE(%esp),%eax	# restore eaz
92	addl		$STACK_SIZE+4,%esp	# cut back stack
93	xchg		%ebp, (%esp)		# restore ebp and set target to top of stack
94	ret					# jump to target
95
96#endif /* __i386__ */
97
98
99#if __x86_64__
100/*
101 * This is the interface for the stub_binding_helper for x86_64:
102 * The caller has pushed the address of the a lazy pointer to be filled in with
103 * the value for the defined symbol and pushed the address of the the mach
104 * header this pointer comes from.
105 *
106 * sp+8	address of lazy pointer
107 * sp+0	address of mach header
108 *
109 * All parameters registers must be preserved.
110 *
111 * After the symbol has been resolved and the pointer filled in this is to pop
112 * these arguments off the stack and jump to the address of the defined symbol.
113 */
114#define MH_PARAM_BP			8
115#define LP_PARAM_BP			16
116
117#define RDI_SAVE			0
118#define RSI_SAVE			8
119#define RDX_SAVE			16
120#define RCX_SAVE			24
121#define R8_SAVE				32
122#define R9_SAVE				40
123#define RAX_SAVE			48
124#define XMMM0_SAVE			64    /* 16-byte align */
125#define XMMM1_SAVE			80
126#define XMMM2_SAVE			96
127#define XMMM3_SAVE			112
128#define XMMM4_SAVE			128
129#define XMMM5_SAVE			144
130#define XMMM6_SAVE			160
131#define XMMM7_SAVE			176
132#define STACK_SIZE			192 /*  (XMMM7_SAVE+16) must be 16 byte aligned too */
133
134    .text
135    .align 2,0x90
136    .globl _stub_binding_helper
137_stub_binding_helper:
138	pushq		%rbp
139	movq		%rsp,%rbp
140	subq		$STACK_SIZE,%rsp	# at this point stack is 16-byte aligned because two meta-parameters where pushed
141	movq		%rdi,RDI_SAVE(%rsp)	# save registers that might be used as parameters
142	movq		%rsi,RSI_SAVE(%rsp)
143	movq		%rdx,RDX_SAVE(%rsp)
144	movq		%rcx,RCX_SAVE(%rsp)
145	movq		%r8,R8_SAVE(%rsp)
146	movq		%r9,R9_SAVE(%rsp)
147	movq		%rax,RAX_SAVE(%rsp)
148	movdqa		%xmm0,XMMM0_SAVE(%rsp)
149	movdqa		%xmm1,XMMM1_SAVE(%rsp)
150	movdqa		%xmm2,XMMM2_SAVE(%rsp)
151	movdqa		%xmm3,XMMM3_SAVE(%rsp)
152	movdqa		%xmm4,XMMM4_SAVE(%rsp)
153	movdqa		%xmm5,XMMM5_SAVE(%rsp)
154	movdqa		%xmm6,XMMM6_SAVE(%rsp)
155	movdqa		%xmm7,XMMM7_SAVE(%rsp)
156	movq		MH_PARAM_BP(%rbp),%rdi	# call dyld::bindLazySymbol(mh, lazy_ptr)
157	movq		LP_PARAM_BP(%rbp),%rsi
158	call		__ZN4dyld14bindLazySymbolEPK11mach_headerPm
159	movq		%rax,%r11		# save target
160	movdqa		XMMM0_SAVE(%rsp),%xmm0	# restore registers
161	movdqa		XMMM1_SAVE(%rsp),%xmm1
162	movdqa		XMMM2_SAVE(%rsp),%xmm2
163	movdqa		XMMM3_SAVE(%rsp),%xmm3
164	movdqa		XMMM4_SAVE(%rsp),%xmm4
165	movdqa		XMMM5_SAVE(%rsp),%xmm5
166	movdqa		XMMM6_SAVE(%rsp),%xmm6
167	movdqa		XMMM7_SAVE(%rsp),%xmm7
168	movq		RDI_SAVE(%rsp),%rdi
169	movq		RSI_SAVE(%rsp),%rsi
170	movq		RDX_SAVE(%rsp),%rdx
171	movq		RCX_SAVE(%rsp),%rcx
172	movq		R8_SAVE(%rsp),%r8
173	movq		R9_SAVE(%rsp),%r9
174	movq		RAX_SAVE(%rsp),%rax
175	addq		$STACK_SIZE,%rsp
176	popq		%rbp
177	addq		$16,%rsp		# remove meta-parameters
178	jmp		*%r11			# jmp to target
179
180#endif
181
182
183#if __arm__
184/*
185 * This is the interface for the stub_binding_helper for ARM:
186 * The caller has pushed the address of the a lazy pointer to be filled in with
187 * the value for the defined symbol and pushed the address of the the mach
188 * header this pointer comes from.
189 *
190 * sp+4        address of lazy pointer
191 * sp+0        address of mach header
192 *
193 * After the symbol has been resolved and the pointer filled in this is to pop
194 * these arguments off the stack and jump to the address of the defined symbol.
195 */
196
197	.text
198	.align 2
199	.globl	_stub_binding_helper
200_stub_binding_helper:
201	stmfd	sp!, {r0,r1,r2,r3,r7,lr}	// save registers
202	add	r7, sp, #16			// point FP to previous FP
203
204	ldr	r0, [sp, #24]			// move address of mach header to 1st parameter
205	ldr	r1, [sp, #28]			// move address of lazy pointer to 2nd parameter
206
207	// call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address)
208	bl	__ZN4dyld14bindLazySymbolEPK11mach_headerPm
209	mov	ip, r0				// move the symbol`s address into ip
210
211	ldmfd	sp!, {r0,r1,r2,r3,r7,lr}	// restore registers
212	add	sp, sp, #8			// remove meta-parameters
213
214	bx	ip				// jump to the symbol`s address that was bound
215
216#endif /* __arm__ */
217
218
219
220
221
222
223
224
225
226
227