dyld-46.16.tar.gz
[apple/dyld.git] / src / dyldStartup.s
1 /*
2  * Copyright (c) 1999-2005 Apple Computer, 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 i386 and ppc 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         .globl __dyld_start
67
68
69 #ifdef __i386__
70         .data
71 __dyld_start_static_picbase: 
72         .long   L__dyld_start_picbase
73
74
75         .text
76         .align 2
77 # stable entry points into dyld
78         .globl  _stub_binding_helper
79 _stub_binding_helper:
80         jmp     _stub_binding_helper_interface
81         nop
82         nop
83         nop
84         .globl  _dyld_func_lookup
85 _dyld_func_lookup:
86         jmp     __Z18lookupDyldFunctionPKcPm
87
88         .text
89         .align  4, 0x90
90         .globl __dyld_start
91 __dyld_start:
92         pushl   $0              # push a zero for debugger end of frames marker
93         movl    %esp,%ebp       # pointer to base of kernel frame
94         andl    $-16,%esp       # force SSE alignment
95         
96         # call dyldbootstrap::start(app_mh, argc, argv, slide)
97         call    L__dyld_start_picbase
98 L__dyld_start_picbase:  
99         popl    %ebx            # set %ebx to runtime value of picbase
100         movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
101         subl    %eax, %ebx      # slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
102         pushl   %ebx            # param4 = slide
103         lea     12(%ebp),%ebx   
104         pushl   %ebx            # param3 = argv
105         movl    8(%ebp),%ebx    
106         pushl   %ebx            # param2 = argc
107         movl    4(%ebp),%ebx    
108         pushl   %ebx            # param1 = mh
109         call    __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl 
110
111         # clean up stack and jump to result
112         movl    %ebp,%esp       # restore the unaligned stack pointer
113         addl    $8,%esp         # remove the mh argument, and debugger end
114                                 #  frame marker
115         movl    $0,%ebp         # restore ebp back to zero
116         jmp     %eax            # jump to the entry point
117
118
119         .globl dyld_stub_binding_helper
120 dyld_stub_binding_helper:
121         hlt
122 L_end:
123 #endif /* __i386__ */
124
125
126 #if __x86_64__
127         .data
128         .align 3
129 __dyld_start_static: 
130         .quad   __dyld_start
131
132 # stable entry points into dyld
133         .text
134         .align 2
135         .globl  _stub_binding_helper
136 _stub_binding_helper:
137         jmp     _stub_binding_helper_interface
138         nop
139         nop
140         nop
141         .globl  _dyld_func_lookup
142 _dyld_func_lookup:
143         jmp     __Z18lookupDyldFunctionPKcPm
144
145         .text
146         .align 2,0x90
147         .globl __dyld_start
148 __dyld_start:
149         pushq   $0              # push a zero for debugger end of frames marker
150         movq    %rsp,%rbp       # pointer to base of kernel frame
151         andq    $-16,%rsp       # force SSE alignment
152         
153         # call dyldbootstrap::start(app_mh, argc, argv, slide)
154         movq    8(%rbp),%rdi    # param1 = mh into %rdi
155         movl    16(%rbp),%esi   # param2 = argc into %esi
156         leaq    24(%rbp),%rdx   # param3 = &argv[0] into %rdx
157         movq    __dyld_start_static(%rip), %r8
158         leaq    __dyld_start(%rip), %rcx
159         subq     %r8, %rcx      # param4 = slide into %rcx
160         call    __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl 
161
162         # clean up stack and jump to result
163         movq    %rbp,%rsp       # restore the unaligned stack pointer
164         addq    $16,%rsp        # remove the mh argument, and debugger end frame marker
165         movq    $0,%rbp         # restore ebp back to zero
166         jmp     *%rax           # jump to the entry point
167 #endif /* __x86_64__ */
168
169
170 #if __ppc__ || __ppc64__
171 #include <architecture/ppc/mode_independent_asm.h>
172
173         .data
174         .align 2
175 __dyld_start_static_picbase: 
176         .g_long   L__dyld_start_picbase
177
178 #if __ppc__     
179         .set L_mh_offset,0
180         .set L_argc_offset,4
181         .set L_argv_offset,8
182 #else
183         .set L_mh_offset,0
184         .set L_argc_offset,8    ; stack is 8-byte aligned and there is a 4-byte hole between argc and argv
185         .set L_argv_offset,16
186 #endif
187
188         .text
189         .align 2
190 ; stable entry points into dyld
191         .globl  _stub_binding_helper
192 _stub_binding_helper:
193         b       _stub_binding_helper_interface
194         nop 
195         .globl  _dyld_func_lookup
196 _dyld_func_lookup:
197         b       __Z18lookupDyldFunctionPKcPm
198         
199         
200         
201         .text
202         .align 2
203 __dyld_start:
204         mr      r26,r1          ; save original stack pointer into r26
205         subi    r1,r1,GPR_BYTES ; make space for linkage
206         clrrgi  r1,r1,5         ; align to 32 bytes
207         addi    r0,0,0          ; load 0 into r0
208         stg     r0,0(r1)        ; terminate initial stack frame
209         stgu    r1,-SF_MINSIZE(r1); allocate minimal stack frame
210                 
211         ; call dyldbootstrap::start(app_mh, argc, argv, slide)
212         lg      r3,L_mh_offset(r26)     ; r3 = mach_header
213         lwz     r4,L_argc_offset(r26)   ; r4 = argc (int == 4 bytes)
214         addi    r5,r26,L_argv_offset    ; r5 = argv
215         bcl     20,31,L__dyld_start_picbase     
216 L__dyld_start_picbase:  
217         mflr    r31             ; put address of L__dyld_start_picbase in r31
218         addis   r6,r31,ha16(__dyld_start_static_picbase-L__dyld_start_picbase)
219         lg      r6,lo16(__dyld_start_static_picbase-L__dyld_start_picbase)(r6)
220         subf    r6,r6,r31       ; r6 = slide
221         bl      __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl 
222         
223         ; clean up stack and jump to result
224         mtctr   r3              ; Put entry point in count register
225         mr      r12,r3          ;  also put in r12 for ABI convention.
226         addi    r1,r26,GPR_BYTES; Restore the stack pointer and remove the
227                                 ;  mach_header argument.
228         bctr                    ; jump to the program's entry point
229
230         .globl dyld_stub_binding_helper
231 dyld_stub_binding_helper:
232         trap
233 L_end:
234 #endif /* __ppc__ */
235
236