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