1/*
2 * Copyright (c) 1999-2011 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 * C runtime startup for interface to the dynamic linker.
25 * This is the same as the entry point in crt0.o with the addition of the
26 * address of the mach header passed as the an extra first argument.
27 *
28 * Kernel sets up stack frame to look like:
29 *
30 *	| STRING AREA |
31 *	+-------------+
32 *	|      0      |
33*	+-------------+
34 *	|  apple[n]   |
35 *	+-------------+
36 *	       :
37 *	+-------------+
38 *	|  apple[0]   |
39 *	+-------------+
40 *	|      0      |
41 *	+-------------+
42 *	|    env[n]   |
43 *	+-------------+
44 *	       :
45 *	       :
46 *	+-------------+
47 *	|    env[0]   |
48 *	+-------------+
49 *	|      0      |
50 *	+-------------+
51 *	| arg[argc-1] |
52 *	+-------------+
53 *	       :
54 *	       :
55 *	+-------------+
56 *	|    arg[0]   |
57 *	+-------------+
58 *	|     argc    |
59 *	+-------------+
60 * sp->	|      mh     | address of where the a.out's file offset 0 is in memory
61 *	+-------------+
62 *
63 *	Where arg[i] and env[i] point into the STRING AREA
64 */
65
66
67#include <TargetConditionals.h>
68
69	.globl __dyld_start
70
71#ifdef __i386__
72#if !TARGET_IPHONE_SIMULATOR
73	.data
74__dyld_start_static_picbase:
75	.long   L__dyld_start_picbase
76Lmh:	.long	___dso_handle
77#endif
78
79	.text
80	.align 2
81# stable entry points into dyld
82	.globl	_stub_binding_helper
83_stub_binding_helper:
84	jmp	_stub_binding_helper_interface
85	nop
86	nop
87	nop
88	.globl	_dyld_func_lookup
89_dyld_func_lookup:
90	jmp	__Z18lookupDyldFunctionPKcPm
91	nop
92	nop
93	nop
94
95	# space for future stable entry points
96	.space	32
97
98
99#if !TARGET_IPHONE_SIMULATOR
100	.text
101	.align	4, 0x90
102	.globl __dyld_start
103__dyld_start:
104	popl	%edx		# edx = mh of app
105	pushl	$0		# push a zero for debugger end of frames marker
106	movl	%esp,%ebp	# pointer to base of kernel frame
107	andl    $-16,%esp       # force SSE alignment
108	subl	$32,%esp	# room for locals and outgoing parameters
109
110	call    L__dyld_start_picbase
111L__dyld_start_picbase:
112	popl	%ebx		# set %ebx to runtime value of picbase
113
114   	movl	Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
115   	movl	__dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
116	subl    %eax, %ebx      # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
117	addl	%ebx, %ecx	# ecx = actual load address
118	# call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
119	movl	%edx,(%esp)	# param1 = app_mh
120	movl	4(%ebp),%eax
121	movl	%eax,4(%esp)	# param2 = argc
122	lea     8(%ebp),%eax
123	movl	%eax,8(%esp)	# param3 = argv
124	movl	%ebx,12(%esp)	# param4 = slide
125	movl	%ecx,16(%esp)	# param5 = actual load address
126	lea	28(%esp),%eax
127	movl	%eax,20(%esp)	# param6 = &startGlue
128	call	__ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
129	movl	28(%esp),%edx
130	cmpl	$0,%edx
131	jne	Lnew
132
133    	# clean up stack and jump to "start" in main executable
134	movl	%ebp,%esp	# restore the unaligned stack pointer
135	addl	$4,%esp		# remove debugger end frame marker
136	movl	$0,%ebp		# restore ebp back to zero
137	jmp	*%eax		# jump to the entry point
138
139	# LC_MAIN case, set up stack for call to main()
140Lnew:	movl	4(%ebp),%ebx
141	movl	%ebx,(%esp)	# main param1 = argc
142	leal	8(%ebp),%ecx
143	movl	%ecx,4(%esp)	# main param2 = argv
144	leal	0x4(%ecx,%ebx,4),%ebx
145	movl	%ebx,8(%esp)	# main param3 = env
146Lapple:	movl	(%ebx),%ecx	# look for NULL ending env[] array
147	add	$4,%ebx
148	testl	%ecx,%ecx
149	jne	Lapple		# once found, next pointer is "apple" parameter now in %ebx
150	movl	%ebx,12(%esp)	# main param4 = apple
151	pushl	%edx		# simulate return address into _start in libdyld
152	jmp	*%eax		# jump to main(argc,argv,env,apple) with return address set to _start
153#endif
154
155	.globl dyld_stub_binding_helper
156dyld_stub_binding_helper:
157	hlt
158L_end:
159#endif /* __i386__ */
160
161
162
163#if __x86_64__
164#if !TARGET_IPHONE_SIMULATOR
165	.data
166	.align 3
167__dyld_start_static:
168	.quad   __dyld_start
169#endif
170
171# stable entry points into dyld
172	.text
173	.align 2
174	.globl	_stub_binding_helper
175_stub_binding_helper:
176	jmp	_stub_binding_helper_interface
177	nop
178	nop
179	nop
180	.globl	_dyld_func_lookup
181_dyld_func_lookup:
182	jmp	__Z18lookupDyldFunctionPKcPm
183	nop
184	nop
185	nop
186
187	# space for future stable entry points
188	.space	24
189
190#if !TARGET_IPHONE_SIMULATOR
191	.text
192	.align 2,0x90
193	.globl __dyld_start
194__dyld_start:
195	popq	%rdi		# param1 = mh of app
196	pushq	$0		# push a zero for debugger end of frames marker
197	movq	%rsp,%rbp	# pointer to base of kernel frame
198	andq    $-16,%rsp       # force SSE alignment
199	subq	$16,%rsp	# room for local variables
200
201	# call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
202	movl	8(%rbp),%esi	# param2 = argc into %esi
203	leaq	16(%rbp),%rdx	# param3 = &argv[0] into %rdx
204	movq	__dyld_start_static(%rip), %r8
205	leaq	__dyld_start(%rip), %rcx
206	subq	 %r8, %rcx	# param4 = slide into %rcx
207	leaq	___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
208	leaq	-8(%rbp),%r9
209	call	__ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
210	movq	-8(%rbp),%rdi
211	cmpq	$0,%rdi
212	jne	Lnew
213
214    	# clean up stack and jump to "start" in main executable
215	movq	%rbp,%rsp	# restore the unaligned stack pointer
216	addq	$8,%rsp 	# remove the mh argument, and debugger end frame marker
217	movq	$0,%rbp		# restore ebp back to zero
218	jmp	*%rax		# jump to the entry point
219
220	# LC_MAIN case, set up stack for call to main()
221Lnew:	addq	$16,%rsp	# remove local variables
222	pushq	%rdi		# simulate return address into _start in libdyld
223	movq	8(%rbp),%rdi	# main param1 = argc into %rdi
224	leaq	16(%rbp),%rsi	# main param2 = &argv[0] into %rsi
225	leaq	0x8(%rsi,%rdi,8),%rdx # main param3 = &env[0] into %rdx
226 	movq	%rdx,%rcx
227Lapple: movq	(%rcx),%r8
228	add	$8,%rcx
229	testq	%r8,%r8		# look for NULL ending env[] array
230	jne	Lapple		# main param4 = apple into %rcx
231	jmp	*%rax		# jump to main(argc,argv,env,apple) with return address set to _start
232
233#endif /* TARGET_IPHONE_SIMULATOR */
234#endif /* __x86_64__ */
235
236
237
238#if __arm__
239	.syntax unified
240	.data
241	.align 2
242__dyld_start_static_picbase:
243	.long	L__dyld_start_picbase
244
245	.text
246	.align 2
247	.globl	_stub_binding_helper
248_stub_binding_helper:
249	b	_stub_binding_helper_interface
250	nop
251
252	.globl	_dyld_func_lookup
253_dyld_func_lookup:
254	b       _branch_to_lookupDyldFunction
255	nop
256
257	# space for future stable entry points
258	.space	24
259
260
261	// Hack to make ___dso_handle work
262	// Without this local symbol, assembler will error out about in subtraction expression
263	// The real ___dso_handle (non-weak) sythesized by the linker
264	// Since this one is weak, the linker will throw this one away and use the real one instead.
265	.data
266	.globl ___dso_handle
267	.weak_definition ___dso_handle
268___dso_handle:	.long 0
269
270	.text
271	.align 2
272__dyld_start:
273	mov	r8, sp		// save stack pointer
274	sub	sp, #16		// make room for outgoing parameters
275	bic     sp, sp, #7	// force 8-byte alignment
276
277	// call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
278
279	ldr	r3, L__dyld_start_picbase_ptr
280L__dyld_start_picbase:
281	sub	r0, pc, #8	// load actual PC
282	ldr	r3, [r0, r3]	// load expected PC
283	sub	r3, r0, r3	// r3 = slide
284
285	ldr	r0, [r8]	// r0 = mach_header
286	ldr	r1, [r8, #4]	// r1 = argc
287	add	r2, r8, #8	// r2 = argv
288
289	ldr	r4, Lmh
290L3:	add	r4, r4, pc
291	str	r4, [sp, #0]	// [sp] = dyld_mh
292	add	r4, sp, #12
293	str	r4, [sp, #4]	// [sp+4] = &startGlue
294
295	bl	__ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
296	ldr	r5, [sp, #12]
297	cmp	r5, #0
298	bne	Lnew
299
300	// traditional case, clean up stack and jump to result
301	add	sp, r8, #4	// remove the mach_header argument.
302	bx	r0		// jump to the program's entry point
303
304	// LC_MAIN case, set up stack for call to main()
305Lnew:	mov	lr, r5		    // simulate return address into _start in libdyld
306	mov	r5, r0		    // save address of main() for later use
307	ldr	r0, [r8, #4]	    // main param1 = argc
308	add	r1, r8, #8	    // main param2 = argv
309	add	r2, r1, r0, lsl #2
310	add	r2, r2, #4	    // main param3 = &env[0]
311	mov	r3, r2
312Lapple:	ldr	r4, [r3]
313	add	r3, #4
314	cmp	r4, #0
315	bne	Lapple		    // main param4 = apple
316	bx	r5
317
318	.align 2
319L__dyld_start_picbase_ptr:
320	.long	__dyld_start_static_picbase-L__dyld_start_picbase
321Lmh:	.long   ___dso_handle-L3-8
322
323	.text
324	.align 2
325_branch_to_lookupDyldFunction:
326	// arm has no "bx label" instruction, so need this island in case lookupDyldFunction() is in thumb
327	ldr ip, L2
328L1:	ldr pc, [pc, ip]
329L2:	.long   _lookupDyldFunction_ptr-8-L1
330
331 	.data
332	.align 2
333_lookupDyldFunction_ptr:
334	.long	__Z18lookupDyldFunctionPKcPm
335
336
337	.text
338	.globl dyld_stub_binding_helper
339dyld_stub_binding_helper:
340	trap
341
342L_end:
343#endif /* __arm__ */
344
345/*
346 * dyld calls this function to terminate a process.
347 * It has a label so that CrashReporter can distinguish this
348 * termination from a random crash.  rdar://problem/4764143
349 */
350	.text
351	.align 2
352	.globl	_dyld_fatal_error
353_dyld_fatal_error:
354#if __arm__
355    trap
356    nop
357#elif __x86_64__ || __i386__
358    int3
359    nop
360#else
361    #error unknown architecture
362#endif
363
364#if __arm__
365	// work around for:  <rdar://problem/6530727> gdb-1109: notifier in dyld does not work if it is in thumb
366 	.text
367	.align 2
368	.globl	_gdb_image_notifier
369	.private_extern _gdb_image_notifier
370_gdb_image_notifier:
371	bx  lr
372#endif
373
374
375
376
377