1/*
2 * Copyright (c) 2006-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#if __ppc__ && __PIC__
26//
27// Force stub section next to __text section to minimize chance that
28// a bl to a stub will be out of range.
29//
30	.text
31 	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
32#endif
33
34////////////////////////////////////////////////////////////////////
35//
36// The dyld_stub_binding_helper adds the mach_header parameter
37// and then jumps into dyld via a pointer in __dyld section
38//
39////////////////////////////////////////////////////////////////////
40	.text
41	.private_extern dyld_stub_binding_helper
42	.align 2
43dyld_stub_binding_helper:
44
45#if __ppc__
46 // for ppc the mach_header parameter is place in r12
47 // and the lazy_pointer is already in r11
48 #if __PIC__
49	mflr	r0
50	bcl     20,31,L1
51L1:	mflr    r12
52	mtlr	r0
53	mr      r0,r12
54	addis	r12,r12,ha16(Ldyld_content_lazy_binder-L1)
55	lwz     r12,lo16(Ldyld_content_lazy_binder-L1)(r12)
56	mtctr	r12
57	mr      r12,r0
58	addis	r12,r12,ha16(dyld__mach_header-L1)
59	lwz     r12,lo16(dyld__mach_header-L1)(r12)
60	bctr
61 #else
62	lis		r12,ha16(Ldyld_content_lazy_binder)
63	lwz		r12,lo16(Ldyld_content_lazy_binder)(r12)
64	mtctr	r12
65	lis		r12,ha16(___dso_handle)
66	la		r12,lo16(___dso_handle)(r12)
67	bctr
68 #endif
69
70#elif __ppc64__
71 // for ppc the mach_header parameter is place in r12
72 // and the lazy_pointer is already in r11
73 // always use PIC code so we can have 4GB zero page
74	mflr	r0
75	bcl     20,31,L1
76L1:	mflr    r12
77	mtlr	r0
78	mr      r0,r12
79	addis	r12,r12,ha16(Ldyld_content_lazy_binder-L1)
80	ld      r12,lo16(Ldyld_content_lazy_binder-L1)(r12)
81	mtctr	r12
82	mr      r12,r0
83	addis	r12,r12,ha16(dyld__mach_header-L1)
84	ld      r12,lo16(dyld__mach_header-L1)(r12)
85	bctr
86
87#elif __i386__
88 // for i386 the mach_header parameter is pushed on the stack
89 // and the lazy_pointer is already on the stack
90 #if __PIC__
91	subl	$8,%esp
92	pushl	%eax
93	pushl	%ecx
94	call	L1
95L1:	popl	%eax
96	movl	dyld__mach_header-L1(%eax),%ecx
97	movl	%ecx,12(%esp)
98	movl    Ldyld_content_lazy_binder-L1(%eax),%ecx
99	movl	%ecx,8(%esp)
100	popl	%ecx
101	popl	%eax
102	ret		// jumps into dyld with lp and mh on the stack
103 #else
104	pushl   $___dso_handle
105	jmpl    *Ldyld_content_lazy_binder
106 #endif
107
108#elif __x86_64__
109 // for x86_64 the mach_header parameter is pushed on the stack
110 // and the lazy_pointer was in r11 and is pushed on the stack
111	pushq	%r11
112	leaq	___dso_handle(%rip), %r11
113	pushq	%r11
114	jmp		*Ldyld_content_lazy_binder(%rip)
115
116#elif __arm__
117	str	ip, [sp, #-4]!  // push address of lazy pointer
118	ldr	ip, Ldyld__mach_header_pointer
119#if __PIC__
120Ldyld__mach_header_pointer_base:
121	ldr	ip, [pc, ip]
122#endif
123	str	ip, [sp, #-4]!  // push address of mach header
124	ldr	ip, Ldyld_lazy_symbol_binding_entry_point
125#if __PIC__
126Ldyld_lazy_symbol_binding_entry_point_base:
127	ldr	pc, [pc, ip]    // jump to dyld_lazy_symbol_binding_entry_point
128#else
129	ldr	pc, [ip]
130#endif
131
132Ldyld__mach_header_pointer:
133#if __PIC__
134	.long	dyld__mach_header - (Ldyld__mach_header_pointer_base + 8)
135#else
136	.long	___dso_handle
137#endif
138Ldyld_lazy_symbol_binding_entry_point:
139#if __PIC__
140	.long	Ldyld_content_lazy_binder - (Ldyld_lazy_symbol_binding_entry_point_base + 8)
141#else
142	.long	Ldyld_content_lazy_binder
143#endif
144#endif
145
146
147
148////////////////////////////////////////////////////////////////////
149//
150// cfm_stub_binding_helper
151//
152// only needed by ppc dylibs which support CFM clients
153//
154////////////////////////////////////////////////////////////////////
155#if __ppc__ && CFM_GLUE
156	.text
157	.align 2
158	.private_extern     cfm_stub_binding_helper
159cfm_stub_binding_helper:
160	mr      r11, r12 ; The TVector address is the binding pointer address.
161	b       dyld_stub_binding_helper  ; Let the normal code handle the rest.
162#endif
163
164
165
166////////////////////////////////////////////////////////////////////
167//
168// __dyld_func_lookup(const char*, void**)
169//
170// jumps into dyld via a pointer in __dyld section
171//
172////////////////////////////////////////////////////////////////////
173	.text
174	.private_extern __dyld_func_lookup
175	.align 2
176__dyld_func_lookup:
177
178#if __ppc__
179 #if __PIC__
180	mflr	r0
181	bcl     20,31,L2
182L2:	mflr    r11
183	mtlr	r0
184	addis	r11,r11,ha16(Ldyld_content_func_lookup-L2)
185	lwz     r11,lo16(Ldyld_content_func_lookup-L2)(r11)
186	mtctr	r11
187	bctr
188 #else
189	lis		r11,ha16(Ldyld_content_func_lookup)
190	lwz		r11,lo16(Ldyld_content_func_lookup)(r11)
191	mtctr	r11
192	bctr
193 #endif
194
195#elif __ppc64__
196	mflr	r0
197	bcl     20,31,L2
198L2:	mflr    r11
199	mtlr	r0
200	addis	r11,r11,ha16(Ldyld_content_func_lookup-L2)
201	ld      r11,lo16(Ldyld_content_func_lookup-L2)(r11)
202	mtctr	r11
203	bctr
204
205#elif __i386__
206 #if __PIC__
207	call	L2
208L2:	popl	%eax
209	movl    Ldyld_content_func_lookup-L2(%eax),%eax
210	jmpl    *%eax
211 #else
212	jmpl	*Ldyld_content_func_lookup
213 #endif
214
215#elif __x86_64__
216	jmp		*Ldyld_content_func_lookup(%rip)
217
218#elif __arm__
219	ldr		ip, L__dyld_func_lookup_pointer
220#if __PIC__
221L__dyld_func_lookup_pointer_base:
222	ldr		pc, [pc, ip]
223#else
224	ldr		pc, [ip]
225#endif
226L__dyld_func_lookup_pointer:
227#if __PIC__
228	.long	Ldyld_content_func_lookup - (L__dyld_func_lookup_pointer_base + 8)
229#else
230	.long	Ldyld_content_func_lookup
231#endif
232#endif
233
234
235
236#if __LP64__
237	#define		align_pointer	align	3
238	#define		pointer			quad
239#else
240	#define		align_pointer	align	2
241	#define		pointer			long
242#endif
243
244
245
246#if __ppc64__ || ((__i386__ || __ppc__ || __arm__) && __PIC__)
247////////////////////////////////////////////////////////////////////
248//
249// dyld__mach_header
250// contains a pointer to the mach_header for this linkage unit
251// only needed for some code models
252//
253////////////////////////////////////////////////////////////////////
254	.data
255	.align_pointer
256dyld__mach_header:
257	.pointer		___dso_handle
258#endif // __x86_64__
259
260
261////////////////////////////////////////////////////////////////////
262//
263// __dyld section content
264//
265//  0:	pointer to lazy symbol binder in dyld
266//  1:  pointer to dyld_func_lookup implementation in dyld
267//
268////////////////////////////////////////////////////////////////////
269#if __ppc__
270	Ldyld_base_addr =	0x8fe00000
271#elif __ppc64__
272	Ldyld_base_addr =	0x00007fff5fc00000
273#elif __i386__
274	Ldyld_base_addr =	0x8fe00000
275#elif __x86_64__
276	Ldyld_base_addr =	0x00007fff5fc00000
277#elif __arm__
278	Ldyld_base_addr =	0x2fe00000
279#elif __arm64__
280#else
281#error unknown architecture
282#endif
283
284#if !__arm64__
285	.dyld
286	.align_pointer
287Ldyld_content_lazy_binder:
288	.pointer		Ldyld_base_addr + 0x1000
289Ldyld_content_func_lookup:
290	.pointer		Ldyld_base_addr + 0x1008
291#if CRT && !OLD_LIBSYSTEM_SUPPORT
292	.pointer		___dso_handle
293	.pointer		_NXArgc
294	.pointer		_NXArgv
295	.pointer		_environ
296	.pointer		___progname
297#endif
298#endif
299
300// This code has be written to allow dead code stripping
301	.subsections_via_symbols
302
303