]> git.saurik.com Git - apple/dyld.git/blame - src/dyldStartup.s
dyld-360.21.tar.gz
[apple/dyld.git] / src / dyldStartup.s
CommitLineData
0959b6d4 1/*
832b6fce 2 * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
0959b6d4
A
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/*
832b6fce 24 * C runtime startup for interface to the dynamic linker.
0959b6d4
A
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
0959b6d4 66
2fd3f4e8 67#include <TargetConditionals.h>
39a8cd10
A
68
69 .globl __dyld_start
70
0959b6d4 71#ifdef __i386__
0959b6d4 72
2fd3f4e8 73#if !TARGET_IPHONE_SIMULATOR
0959b6d4
A
74 .text
75 .align 4, 0x90
76 .globl __dyld_start
77__dyld_start:
832b6fce 78 popl %edx # edx = mh of app
0959b6d4
A
79 pushl $0 # push a zero for debugger end of frames marker
80 movl %esp,%ebp # pointer to base of kernel frame
81 andl $-16,%esp # force SSE alignment
832b6fce 82 subl $32,%esp # room for locals and outgoing parameters
0959b6d4 83
0959b6d4
A
84 call L__dyld_start_picbase
85L__dyld_start_picbase:
86 popl %ebx # set %ebx to runtime value of picbase
832b6fce 87
412ebb8e
A
88 movl Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
89 movl __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
90 subl %eax, %ebx # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
91 addl %ebx, %ecx # ecx = actual load address
832b6fce
A
92 # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
93 movl %edx,(%esp) # param1 = app_mh
94 movl 4(%ebp),%eax
95 movl %eax,4(%esp) # param2 = argc
96 lea 8(%ebp),%eax
97 movl %eax,8(%esp) # param3 = argv
98 movl %ebx,12(%esp) # param4 = slide
99 movl %ecx,16(%esp) # param5 = actual load address
100 lea 28(%esp),%eax
101 movl %eax,20(%esp) # param6 = &startGlue
102 call __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
103 movl 28(%esp),%edx
104 cmpl $0,%edx
105 jne Lnew
106
107 # clean up stack and jump to "start" in main executable
0959b6d4 108 movl %ebp,%esp # restore the unaligned stack pointer
832b6fce 109 addl $4,%esp # remove debugger end frame marker
0959b6d4 110 movl $0,%ebp # restore ebp back to zero
bac542e6 111 jmp *%eax # jump to the entry point
0959b6d4 112
832b6fce
A
113 # LC_MAIN case, set up stack for call to main()
114Lnew: movl 4(%ebp),%ebx
115 movl %ebx,(%esp) # main param1 = argc
116 leal 8(%ebp),%ecx
117 movl %ecx,4(%esp) # main param2 = argv
118 leal 0x4(%ecx,%ebx,4),%ebx
119 movl %ebx,8(%esp) # main param3 = env
120Lapple: movl (%ebx),%ecx # look for NULL ending env[] array
121 add $4,%ebx
122 testl %ecx,%ecx
123 jne Lapple # once found, next pointer is "apple" parameter now in %ebx
124 movl %ebx,12(%esp) # main param4 = apple
125 pushl %edx # simulate return address into _start in libdyld
126 jmp *%eax # jump to main(argc,argv,env,apple) with return address set to _start
2fd3f4e8 127#endif
19894a12
A
128
129#if !TARGET_IPHONE_SIMULATOR
130 .data
131__dyld_start_static_picbase:
132 .long L__dyld_start_picbase
133Lmh: .long ___dso_handle
134#endif
135
136
0959b6d4
A
137#endif /* __i386__ */
138
3d7c199a 139
39a8cd10 140
8bc9f0af 141#if __x86_64__
2fd3f4e8 142#if !TARGET_IPHONE_SIMULATOR
8bc9f0af
A
143 .data
144 .align 3
145__dyld_start_static:
146 .quad __dyld_start
2fd3f4e8 147#endif
8bc9f0af 148
8bc9f0af 149
2fd3f4e8 150#if !TARGET_IPHONE_SIMULATOR
8bc9f0af
A
151 .text
152 .align 2,0x90
153 .globl __dyld_start
154__dyld_start:
832b6fce 155 popq %rdi # param1 = mh of app
8bc9f0af
A
156 pushq $0 # push a zero for debugger end of frames marker
157 movq %rsp,%rbp # pointer to base of kernel frame
158 andq $-16,%rsp # force SSE alignment
832b6fce 159 subq $16,%rsp # room for local variables
8bc9f0af 160
832b6fce
A
161 # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
162 movl 8(%rbp),%esi # param2 = argc into %esi
163 leaq 16(%rbp),%rdx # param3 = &argv[0] into %rdx
8bc9f0af
A
164 movq __dyld_start_static(%rip), %r8
165 leaq __dyld_start(%rip), %rcx
166 subq %r8, %rcx # param4 = slide into %rcx
412ebb8e 167 leaq ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
832b6fce
A
168 leaq -8(%rbp),%r9
169 call __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
170 movq -8(%rbp),%rdi
171 cmpq $0,%rdi
172 jne Lnew
8bc9f0af 173
832b6fce 174 # clean up stack and jump to "start" in main executable
8bc9f0af 175 movq %rbp,%rsp # restore the unaligned stack pointer
832b6fce 176 addq $8,%rsp # remove the mh argument, and debugger end frame marker
8bc9f0af
A
177 movq $0,%rbp # restore ebp back to zero
178 jmp *%rax # jump to the entry point
bac542e6 179
832b6fce
A
180 # LC_MAIN case, set up stack for call to main()
181Lnew: addq $16,%rsp # remove local variables
182 pushq %rdi # simulate return address into _start in libdyld
183 movq 8(%rbp),%rdi # main param1 = argc into %rdi
184 leaq 16(%rbp),%rsi # main param2 = &argv[0] into %rsi
185 leaq 0x8(%rsi,%rdi,8),%rdx # main param3 = &env[0] into %rdx
186 movq %rdx,%rcx
187Lapple: movq (%rcx),%r8
188 add $8,%rcx
189 testq %r8,%r8 # look for NULL ending env[] array
190 jne Lapple # main param4 = apple into %rcx
191 jmp *%rax # jump to main(argc,argv,env,apple) with return address set to _start
2fd3f4e8
A
192
193#endif /* TARGET_IPHONE_SIMULATOR */
8bc9f0af 194#endif /* __x86_64__ */
3d7c199a 195
2de2b37b 196
0959b6d4 197
39a8cd10 198#if __arm__
832b6fce 199 .syntax unified
39a8cd10
A
200 .data
201 .align 2
202__dyld_start_static_picbase:
203 .long L__dyld_start_picbase
204
39a8cd10 205
412ebb8e
A
206 // Hack to make ___dso_handle work
207 // Without this local symbol, assembler will error out about in subtraction expression
208 // The real ___dso_handle (non-weak) sythesized by the linker
209 // Since this one is weak, the linker will throw this one away and use the real one instead.
210 .data
211 .globl ___dso_handle
212 .weak_definition ___dso_handle
213___dso_handle: .long 0
214
39a8cd10
A
215 .text
216 .align 2
217__dyld_start:
412ebb8e 218 mov r8, sp // save stack pointer
832b6fce 219 sub sp, #16 // make room for outgoing parameters
df9d6cf7 220 bic sp, sp, #15 // force 16-byte alignment
412ebb8e 221
832b6fce 222 // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
39a8cd10
A
223
224 ldr r3, L__dyld_start_picbase_ptr
225L__dyld_start_picbase:
226 sub r0, pc, #8 // load actual PC
227 ldr r3, [r0, r3] // load expected PC
228 sub r3, r0, r3 // r3 = slide
229
412ebb8e
A
230 ldr r0, [r8] // r0 = mach_header
231 ldr r1, [r8, #4] // r1 = argc
232 add r2, r8, #8 // r2 = argv
39a8cd10 233
412ebb8e 234 ldr r4, Lmh
832b6fce
A
235L3: add r4, r4, pc
236 str r4, [sp, #0] // [sp] = dyld_mh
237 add r4, sp, #12
238 str r4, [sp, #4] // [sp+4] = &startGlue
39a8cd10 239
832b6fce
A
240 bl __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
241 ldr r5, [sp, #12]
242 cmp r5, #0
243 bne Lnew
244
245 // traditional case, clean up stack and jump to result
39a8cd10
A
246 add sp, r8, #4 // remove the mach_header argument.
247 bx r0 // jump to the program's entry point
248
832b6fce
A
249 // LC_MAIN case, set up stack for call to main()
250Lnew: mov lr, r5 // simulate return address into _start in libdyld
251 mov r5, r0 // save address of main() for later use
252 ldr r0, [r8, #4] // main param1 = argc
253 add r1, r8, #8 // main param2 = argv
254 add r2, r1, r0, lsl #2
255 add r2, r2, #4 // main param3 = &env[0]
256 mov r3, r2
257Lapple: ldr r4, [r3]
258 add r3, #4
259 cmp r4, #0
260 bne Lapple // main param4 = apple
261 bx r5
412ebb8e 262
39a8cd10
A
263 .align 2
264L__dyld_start_picbase_ptr:
265 .long __dyld_start_static_picbase-L__dyld_start_picbase
412ebb8e 266Lmh: .long ___dso_handle-L3-8
19894a12
A
267
268#endif /* __arm__ */
269
270
271
272
273#if __arm64__
274 .data
275 .align 3
276__dso_static:
277 .quad ___dso_handle
278
39a8cd10
A
279 .text
280 .align 2
19894a12
A
281 .globl __dyld_start
282__dyld_start:
283 mov x28, sp
284 and sp, x28, #~15 // force 16-byte alignment of stack
285 mov x0, #0
286 mov x1, #0
287 stp x1, x0, [sp, #-16]! // make aligned terminating frame
288 mov fp, sp // set up fp to point to terminating frame
289 sub sp, sp, #16 // make room for local variables
290 ldr x0, [x28] // get app's mh into x0
291 ldr x1, [x28, #8] // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
292 add x2, x28, #16 // get argv into x2
293 adrp x4,___dso_handle@page
294 add x4,x4,___dso_handle@pageoff // get dyld's mh in to x4
295 adrp x3,__dso_static@page
296 ldr x3,[x3,__dso_static@pageoff] // get unslid start of dyld
297 sub x3,x4,x3 // x3 now has slide of dyld
298 mov x5,sp // x5 has &startGlue
39a8cd10 299
19894a12
A
300 // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
301 bl __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
302 mov x16,x0 // save entry point address in x16
303 ldr x1, [sp]
304 cmp x1, #0
305 b.ne Lnew
306
307 // LC_UNIXTHREAD way, clean up stack and jump to result
308 add sp, x28, #8 // restore unaligned stack pointer without app mh
309 br x16 // jump to the program's entry point
310
311 // LC_MAIN case, set up stack for call to main()
312Lnew: mov lr, x1 // simulate return address into _start in libdyld.dylib
313 ldr x0, [x28, #8] // main param1 = argc
314 add x1, x28, #16 // main param2 = argv
315 add x2, x1, x0, lsl #3
316 add x2, x2, #8 // main param3 = &env[0]
317 mov x3, x2
318Lapple: ldr x4, [x3]
319 add x3, x3, #8
320 cmp x4, #0
321 b.ne Lapple // main param4 = apple
322 br x16
323
324#endif // __arm64__
39a8cd10 325
0959b6d4 326
bac542e6
A
327/*
328 * dyld calls this function to terminate a process.
329 * It has a label so that CrashReporter can distinguish this
330 * termination from a random crash. rdar://problem/4764143
331 */
332 .text
333 .align 2
334 .globl _dyld_fatal_error
335_dyld_fatal_error:
832b6fce 336#if __arm__
bac542e6 337 trap
39a8cd10 338 nop
bac542e6
A
339#elif __x86_64__ || __i386__
340 int3
39a8cd10 341 nop
19894a12
A
342#elif __arm64__
343 brk #3
bac542e6
A
344#else
345 #error unknown architecture
346#endif
347
412ebb8e
A
348#if __arm__
349 // work around for: <rdar://problem/6530727> gdb-1109: notifier in dyld does not work if it is in thumb
350 .text
351 .align 2
352 .globl _gdb_image_notifier
353 .private_extern _gdb_image_notifier
354_gdb_image_notifier:
355 bx lr
356#endif
357
358
bac542e6
A
359
360