dyld-832.7.1.tar.gz
[apple/dyld.git] / src / dyldStartup.s
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 #if __i386__ && !TARGET_OS_SIMULATOR
72         .text
73         .align  4, 0x90
74         .globl __dyld_start
75 __dyld_start:
76         popl    %edx            # edx = mh of app
77         pushl   $0              # push a zero for debugger end of frames marker
78         movl    %esp,%ebp       # pointer to base of kernel frame
79         andl    $-16,%esp       # force SSE alignment
80         subl    $32,%esp        # room for locals and outgoing parameters
81
82         call    L__dyld_start_picbase
83 L__dyld_start_picbase:
84         popl    %ebx            # set %ebx to runtime value of picbase
85
86         # call dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue)
87         subl    $L__dyld_start_picbase-__dyld_start, %ebx # ebx = &__dyld_start
88         subl    $0x1000, %ebx   # ebx = load address of dyld
89         movl    %edx,(%esp)     # param1 = app_mh
90         movl    4(%ebp),%eax
91         movl    %eax,4(%esp)    # param2 = argc
92         lea     8(%ebp),%eax
93         movl    %eax,8(%esp)    # param3 = argv
94         movl    %ebx,12(%esp)   # param4 = dyld load address
95         lea     28(%esp),%eax
96         movl    %eax,16(%esp)   # param5 = &startGlue
97         call    __ZN13dyldbootstrap5startEPKN5dyld311MachOLoadedEiPPKcS3_Pm
98         movl    28(%esp),%edx
99         cmpl    $0,%edx
100         jne     Lnew
101
102         # clean up stack and jump to "start" in main executable
103         movl    %ebp,%esp       # restore the unaligned stack pointer
104         addl    $4,%esp         # remove debugger end frame marker
105         movl    $0,%ebp         # restore ebp back to zero
106         jmp     *%eax           # jump to the entry point
107
108         # LC_MAIN case, set up stack for call to main()
109 Lnew:   movl    4(%ebp),%ebx
110         movl    %ebx,(%esp)     # main param1 = argc
111         leal    8(%ebp),%ecx
112         movl    %ecx,4(%esp)    # main param2 = argv
113         leal    0x4(%ecx,%ebx,4),%ebx
114         movl    %ebx,8(%esp)    # main param3 = env
115 Lapple: movl    (%ebx),%ecx     # look for NULL ending env[] array
116         add     $4,%ebx
117         testl   %ecx,%ecx
118         jne     Lapple          # once found, next pointer is "apple" parameter now in %ebx
119         movl    %ebx,12(%esp)   # main param4 = apple
120         pushl   %edx            # simulate return address into _start in libdyld
121         jmp     *%eax           # jump to main(argc,argv,env,apple) with return address set to _start
122
123 #endif /* __i386__  && !TARGET_OS_SIMULATOR*/
124
125
126
127 #if __x86_64__ && !TARGET_OS_SIMULATOR
128         .text
129         .align 2,0x90
130         .globl __dyld_start
131 __dyld_start:
132         popq    %rdi            # param1 = mh of app
133         pushq   $0              # push a zero for debugger end of frames marker
134         movq    %rsp,%rbp       # pointer to base of kernel frame
135         andq    $-16,%rsp       # force SSE alignment
136         subq    $16,%rsp        # room for local variables
137
138         # call dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue)
139         movl    8(%rbp),%esi    # param2 = argc into %esi
140         leaq    16(%rbp),%rdx   # param3 = &argv[0] into %rdx
141         leaq    ___dso_handle(%rip),%rcx # param4 = dyldsMachHeader into %rcx
142         leaq    -8(%rbp),%r8    # param5 = &glue into %r8
143         call    __ZN13dyldbootstrap5startEPKN5dyld311MachOLoadedEiPPKcS3_Pm
144         movq    -8(%rbp),%rdi
145         cmpq    $0,%rdi
146         jne     Lnew
147
148         # clean up stack and jump to "start" in main executable
149         movq    %rbp,%rsp       # restore the unaligned stack pointer
150         addq    $8,%rsp         # remove the mh argument, and debugger end frame marker
151         movq    $0,%rbp         # restore ebp back to zero
152         jmp     *%rax           # jump to the entry point
153
154         # LC_MAIN case, set up stack for call to main()
155 Lnew:   addq    $16,%rsp        # remove local variables
156         pushq   %rdi            # simulate return address into _start in libdyld
157         movq    8(%rbp),%rdi    # main param1 = argc into %rdi
158         leaq    16(%rbp),%rsi   # main param2 = &argv[0] into %rsi
159         leaq    0x8(%rsi,%rdi,8),%rdx # main param3 = &env[0] into %rdx
160         movq    %rdx,%rcx
161 Lapple: movq    (%rcx),%r8
162         add     $8,%rcx
163         testq   %r8,%r8         # look for NULL ending env[] array
164         jne     Lapple          # main param4 = apple into %rcx
165         jmp     *%rax           # jump to main(argc,argv,env,apple) with return address set to _start
166 #endif /* __x86_64__ && !TARGET_OS_SIMULATOR*/
167
168
169
170 #if __arm__
171         .text
172         .align 2
173 __dyld_start:
174         mov     r8, sp          // save stack pointer
175         sub     sp, #16         // make room for outgoing parameters
176         bic     sp, sp, #15     // force 16-byte alignment
177
178         // call dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue)
179         ldr     r0, [r8]        // r0 = mach_header
180         ldr     r1, [r8, #4]    // r1 = argc
181         add     r2, r8, #8      // r2 = argv
182         adr     r3, __dyld_start
183         sub     r3 ,r3, #0x1000 // r3 = dyld_mh
184         add     r4, sp, #12
185         str     r4, [sp, #0]    // [sp] = &startGlue
186
187         bl      __ZN13dyldbootstrap5startEPKN5dyld311MachOLoadedEiPPKcS3_Pm
188         ldr     r5, [sp, #12]
189         cmp     r5, #0
190         bne     Lnew
191
192         // traditional case, clean up stack and jump to result
193         add     sp, r8, #4      // remove the mach_header argument.
194         bx      r0              // jump to the program's entry point
195
196         // LC_MAIN case, set up stack for call to main()
197 Lnew:   mov     lr, r5              // simulate return address into _start in libdyld
198         mov     r5, r0              // save address of main() for later use
199         ldr     r0, [r8, #4]        // main param1 = argc
200         add     r1, r8, #8          // main param2 = argv
201         add     r2, r1, r0, lsl #2
202         add     r2, r2, #4          // main param3 = &env[0]
203         mov     r3, r2
204 Lapple: ldr     r4, [r3]
205         add     r3, #4
206         cmp     r4, #0
207         bne     Lapple              // main param4 = apple
208         bx      r5
209
210 #endif /* __arm__ */
211
212
213
214
215 #if __arm64__ && !TARGET_OS_SIMULATOR
216         .text
217         .align 2
218         .globl __dyld_start
219 __dyld_start:
220         mov     x28, sp
221         and     sp, x28, #~15           // force 16-byte alignment of stack
222         mov     x0, #0
223         mov     x1, #0
224         stp     x1, x0, [sp, #-16]!     // make aligned terminating frame
225         mov     fp, sp                  // set up fp to point to terminating frame
226         sub     sp, sp, #16             // make room for local variables
227 #if __LP64__
228         ldr     x0, [x28]               // get app's mh into x0
229         ldr     x1, [x28, #8]           // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
230         add     x2, x28, #16            // get argv into x2
231 #else
232         ldr     w0, [x28]               // get app's mh into x0
233         ldr     w1, [x28, #4]           // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
234         add     w2, w28, #8             // get argv into x2
235 #endif
236         adrp    x3,___dso_handle@page
237         add     x3,x3,___dso_handle@pageoff // get dyld's mh in to x4
238         mov     x4,sp                   // x5 has &startGlue
239
240         // call dyldbootstrap::start(app_mh, argc, argv, dyld_mh, &startGlue)
241         bl      __ZN13dyldbootstrap5startEPKN5dyld311MachOLoadedEiPPKcS3_Pm
242         mov     x16,x0                  // save entry point address in x16
243 #if __LP64__
244         ldr     x1, [sp]
245 #else
246         ldr     w1, [sp]
247 #endif
248         cmp     x1, #0
249         b.ne    Lnew
250
251         // LC_UNIXTHREAD way, clean up stack and jump to result
252 #if __LP64__
253         add     sp, x28, #8             // restore unaligned stack pointer without app mh
254 #else
255         add     sp, x28, #4             // restore unaligned stack pointer without app mh
256 #endif
257 #if __arm64e__
258         braaz   x16                     // jump to the program's entry point
259 #else
260         br      x16                     // jump to the program's entry point
261 #endif
262
263         // LC_MAIN case, set up stack for call to main()
264 Lnew:   mov     lr, x1              // simulate return address into _start in libdyld.dylib
265 #if __LP64__
266         ldr     x0, [x28, #8]       // main param1 = argc
267         add     x1, x28, #16        // main param2 = argv
268         add     x2, x1, x0, lsl #3
269         add     x2, x2, #8          // main param3 = &env[0]
270         mov     x3, x2
271 Lapple: ldr     x4, [x3]
272         add     x3, x3, #8
273 #else
274         ldr     w0, [x28, #4]       // main param1 = argc
275         add     x1, x28, #8         // main param2 = argv
276         add     x2, x1, x0, lsl #2
277         add     x2, x2, #4          // main param3 = &env[0]
278         mov     x3, x2
279 Lapple: ldr     w4, [x3]
280         add     x3, x3, #4
281 #endif
282         cmp     x4, #0
283         b.ne    Lapple              // main param4 = apple
284 #if __arm64e__
285         braaz   x16
286 #else
287         br      x16
288 #endif
289
290 #endif // __arm64__ && !TARGET_OS_SIMULATOR
291
292
293 // When iOS 10.0 simulator runs on 10.11, abort_with_payload() does not exist,
294 // so it falls back and uses dyld_fatal_error().
295 #if TARGET_OS_SIMULATOR
296         .text
297         .align 2
298         .globl  _dyld_fatal_error
299 _dyld_fatal_error:
300 #if __arm64__ || __arm64e__
301     brk #3
302 #else
303     int3
304 #endif
305     nop
306 #endif
307