dyld-655.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 #ifdef __i386__
72
73 #if !TARGET_IPHONE_SIMULATOR
74         .text
75         .align  4, 0x90
76         .globl __dyld_start
77 __dyld_start:
78         popl    %edx            # edx = mh of app
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
82         subl    $32,%esp        # room for locals and outgoing parameters
83
84         call    L__dyld_start_picbase
85 L__dyld_start_picbase:
86         popl    %ebx            # set %ebx to runtime value of picbase
87
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
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
108         movl    %ebp,%esp       # restore the unaligned stack pointer
109         addl    $4,%esp         # remove debugger end frame marker
110         movl    $0,%ebp         # restore ebp back to zero
111         jmp     *%eax           # jump to the entry point
112
113         # LC_MAIN case, set up stack for call to main()
114 Lnew:   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
120 Lapple: 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
127 #endif
128
129 #if !TARGET_IPHONE_SIMULATOR
130         .data
131 __dyld_start_static_picbase:
132         .long   L__dyld_start_picbase
133 Lmh:    .long   ___dso_handle
134 #endif
135
136
137 #endif /* __i386__ */
138
139
140
141 #if __x86_64__
142 #if !TARGET_IPHONE_SIMULATOR
143         .data
144         .align 3
145 __dyld_start_static:
146         .quad   __dyld_start
147 #endif
148
149
150 #if !TARGET_IPHONE_SIMULATOR
151         .text
152         .align 2,0x90
153         .globl __dyld_start
154 __dyld_start:
155         popq    %rdi            # param1 = mh of app
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
159         subq    $16,%rsp        # room for local variables
160
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
164         movq    __dyld_start_static(%rip), %r8
165         leaq    __dyld_start(%rip), %rcx
166         subq     %r8, %rcx      # param4 = slide into %rcx
167         leaq    ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
168         leaq    -8(%rbp),%r9
169         call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
170         movq    -8(%rbp),%rdi
171         cmpq    $0,%rdi
172         jne     Lnew
173
174         # clean up stack and jump to "start" in main executable
175         movq    %rbp,%rsp       # restore the unaligned stack pointer
176         addq    $8,%rsp         # remove the mh argument, and debugger end frame marker
177         movq    $0,%rbp         # restore ebp back to zero
178         jmp     *%rax           # jump to the entry point
179
180         # LC_MAIN case, set up stack for call to main()
181 Lnew:   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
187 Lapple: 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
192
193 #endif /* TARGET_IPHONE_SIMULATOR */
194 #endif /* __x86_64__ */
195
196
197
198 #if __arm__
199         .syntax unified
200         .data
201         .align 2
202 __dyld_start_static_picbase:
203         .long   L__dyld_start_picbase
204
205
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
215         .text
216         .align 2
217 __dyld_start:
218         mov     r8, sp          // save stack pointer
219         sub     sp, #16         // make room for outgoing parameters
220         bic     sp, sp, #15     // force 16-byte alignment
221
222         // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
223
224         ldr     r3, L__dyld_start_picbase_ptr
225 L__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
230         ldr     r0, [r8]        // r0 = mach_header
231         ldr     r1, [r8, #4]    // r1 = argc
232         add     r2, r8, #8      // r2 = argv
233
234         ldr     r4, Lmh
235 L3:     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
239
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
246         add     sp, r8, #4      // remove the mach_header argument.
247         bx      r0              // jump to the program's entry point
248
249         // LC_MAIN case, set up stack for call to main()
250 Lnew:   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
257 Lapple: ldr     r4, [r3]
258         add     r3, #4
259         cmp     r4, #0
260         bne     Lapple              // main param4 = apple
261         bx      r5
262
263         .align 2
264 L__dyld_start_picbase_ptr:
265         .long   __dyld_start_static_picbase-L__dyld_start_picbase
266 Lmh:    .long   ___dso_handle-L3-8
267
268 #endif /* __arm__ */
269
270
271
272
273 #if __arm64__
274         .data
275         .align 3
276 __dso_static:
277         .quad   ___dso_handle
278
279         .text
280         .align 2
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 #if __LP64__
291         ldr     x0, [x28]               // get app's mh into x0
292         ldr     x1, [x28, #8]           // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
293         add     x2, x28, #16            // get argv into x2
294 #else
295         ldr     w0, [x28]               // get app's mh into x0
296         ldr     w1, [x28, #4]           // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
297         add     w2, w28, #8             // get argv into x2
298 #endif
299         adrp    x4,___dso_handle@page
300         add     x4,x4,___dso_handle@pageoff // get dyld's mh in to x4
301         adrp    x3,__dso_static@page
302         ldr     x3,[x3,__dso_static@pageoff] // get unslid start of dyld
303         sub     x3,x4,x3                // x3 now has slide of dyld
304         mov     x5,sp                   // x5 has &startGlue
305
306         // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
307         bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
308         mov     x16,x0                  // save entry point address in x16
309 #if __LP64__
310         ldr     x1, [sp]
311 #else
312         ldr     w1, [sp]
313 #endif
314         cmp     x1, #0
315         b.ne    Lnew
316
317         // LC_UNIXTHREAD way, clean up stack and jump to result
318 #if __LP64__
319         add     sp, x28, #8             // restore unaligned stack pointer without app mh
320 #else
321         add     sp, x28, #4             // restore unaligned stack pointer without app mh
322 #endif
323 #if __arm64e__
324         braaz   x16                     // jump to the program's entry point
325 #else
326         br      x16                     // jump to the program's entry point
327 #endif
328
329         // LC_MAIN case, set up stack for call to main()
330 Lnew:   mov     lr, x1              // simulate return address into _start in libdyld.dylib
331 #if __LP64__
332         ldr     x0, [x28, #8]       // main param1 = argc
333         add     x1, x28, #16        // main param2 = argv
334         add     x2, x1, x0, lsl #3
335         add     x2, x2, #8          // main param3 = &env[0]
336         mov     x3, x2
337 Lapple: ldr     x4, [x3]
338         add     x3, x3, #8
339 #else
340         ldr     w0, [x28, #4]       // main param1 = argc
341         add     x1, x28, #8         // main param2 = argv
342         add     x2, x1, x0, lsl #2
343         add     x2, x2, #4          // main param3 = &env[0]
344         mov     x3, x2
345 Lapple: ldr     w4, [x3]
346         add     x3, x3, #4
347 #endif
348         cmp     x4, #0
349         b.ne    Lapple              // main param4 = apple
350 #if __arm64e__
351         braaz   x16
352 #else
353         br      x16
354 #endif
355
356 #endif // __arm64__
357
358
359 // When iOS 10.0 simulator runs on 10.11, abort_with_payload() does not exist,
360 // so it falls back and uses dyld_fatal_error().
361 #if TARGET_IPHONE_SIMULATOR
362         .text
363         .align 2
364         .globl  _dyld_fatal_error
365 _dyld_fatal_error:
366     int3
367     nop
368 #endif
369
370
371
372
373