]> git.saurik.com Git - apple/dyld.git/blob - src/dyldStartup.s
dyld-195.6.tar.gz
[apple/dyld.git] / src / dyldStartup.s
1 /*
2 * Copyright (c) 1999-2008 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 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
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 pushl $0 # push a zero for debugger end of frames marker
115 movl %esp,%ebp # pointer to base of kernel frame
116 andl $-16,%esp # force SSE alignment
117
118 # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
119 subl $12,%esp
120 call L__dyld_start_picbase
121 L__dyld_start_picbase:
122 popl %ebx # set %ebx to runtime value of picbase
123 movl Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
124 movl __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
125 subl %eax, %ebx # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
126 addl %ebx, %ecx # ecx = actual load address
127 pushl %ecx # param5 = actual load address
128 pushl %ebx # param4 = slide
129 lea 12(%ebp),%ebx
130 pushl %ebx # param3 = argv
131 movl 8(%ebp),%ebx
132 pushl %ebx # param2 = argc
133 movl 4(%ebp),%ebx
134 pushl %ebx # param1 = mh
135 call __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_
136
137 # clean up stack and jump to result
138 movl %ebp,%esp # restore the unaligned stack pointer
139 addl $8,%esp # remove the mh argument, and debugger end
140 # frame marker
141 movl $0,%ebp # restore ebp back to zero
142 jmp *%eax # jump to the entry point
143
144
145 .globl dyld_stub_binding_helper
146 dyld_stub_binding_helper:
147 hlt
148 L_end:
149 #endif /* __i386__ */
150
151
152
153 #if __x86_64__
154 .data
155 .align 3
156 __dyld_start_static:
157 .quad __dyld_start
158
159 # stable entry points into dyld
160 .text
161 .align 2
162 .globl _stub_binding_helper
163 _stub_binding_helper:
164 jmp _stub_binding_helper_interface
165 nop
166 nop
167 nop
168 .globl _dyld_func_lookup
169 _dyld_func_lookup:
170 jmp __Z18lookupDyldFunctionPKcPm
171 nop
172 nop
173 nop
174 _offset_to_dyld_all_image_infos:
175 .long _dyld_all_image_infos - . + 0x1010
176 .long 0
177 # space for future stable entry points
178 .space 16
179
180
181 .text
182 .align 2,0x90
183 .globl __dyld_start
184 __dyld_start:
185 pushq $0 # push a zero for debugger end of frames marker
186 movq %rsp,%rbp # pointer to base of kernel frame
187 andq $-16,%rsp # force SSE alignment
188
189 # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
190 movq 8(%rbp),%rdi # param1 = mh into %rdi
191 movl 16(%rbp),%esi # param2 = argc into %esi
192 leaq 24(%rbp),%rdx # param3 = &argv[0] into %rdx
193 movq __dyld_start_static(%rip), %r8
194 leaq __dyld_start(%rip), %rcx
195 subq %r8, %rcx # param4 = slide into %rcx
196 leaq ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
197 call __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_
198
199 # clean up stack and jump to result
200 movq %rbp,%rsp # restore the unaligned stack pointer
201 addq $16,%rsp # remove the mh argument, and debugger end frame marker
202 movq $0,%rbp # restore ebp back to zero
203 jmp *%rax # jump to the entry point
204
205 #endif /* __x86_64__ */
206
207
208 #if __ppc__ || __ppc64__
209 #include <architecture/ppc/mode_independent_asm.h>
210
211 .data
212 .align 2
213 __dyld_start_static_picbase:
214 .g_long L__dyld_start_picbase
215 Lmh: .g_long ___dso_handle
216
217 #if __ppc__
218 .set L_mh_offset,0
219 .set L_argc_offset,4
220 .set L_argv_offset,8
221 #else
222 .set L_mh_offset,0
223 .set L_argc_offset,8 ; stack is 8-byte aligned and there is a 4-byte hole between argc and argv
224 .set L_argv_offset,16
225 #endif
226
227 .text
228 .align 2
229 ; stable entry points into dyld
230 .globl _stub_binding_helper
231 _stub_binding_helper:
232 b _stub_binding_helper_interface
233 nop
234 .globl _dyld_func_lookup
235 _dyld_func_lookup:
236 b __Z18lookupDyldFunctionPKcPm
237 nop
238 _offset_to_dyld_all_image_infos:
239 .long _dyld_all_image_infos - . + 0x1010
240 .long 0
241 # space for future stable entry points
242 .space 16
243
244
245 .text
246 .align 2
247 __dyld_start:
248 mr r26,r1 ; save original stack pointer into r26
249 subi r1,r1,GPR_BYTES ; make space for linkage
250 clrrgi r1,r1,5 ; align to 32 bytes
251 addi r0,0,0 ; load 0 into r0
252 stg r0,0(r1) ; terminate initial stack frame
253 stgu r1,-SF_MINSIZE(r1); allocate minimal stack frame
254
255 # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
256 lg r3,L_mh_offset(r26) ; r3 = mach_header
257 lwz r4,L_argc_offset(r26) ; r4 = argc (int == 4 bytes)
258 addi r5,r26,L_argv_offset ; r5 = argv
259 bcl 20,31,L__dyld_start_picbase
260 L__dyld_start_picbase:
261 mflr r31 ; put address of L__dyld_start_picbase in r31
262 addis r6,r31,ha16(__dyld_start_static_picbase-L__dyld_start_picbase)
263 lg r6,lo16(__dyld_start_static_picbase-L__dyld_start_picbase)(r6)
264 subf r6,r6,r31 ; r6 = slide
265 addis r7,r31,ha16(Lmh-L__dyld_start_picbase)
266 lg r7,lo16(Lmh-L__dyld_start_picbase)(r7)
267 add r7,r6,r7 ; r7 = dyld_mh
268 bl __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_
269
270 ; clean up stack and jump to result
271 mtctr r3 ; Put entry point in count register
272 mr r12,r3 ; also put in r12 for ABI convention.
273 addi r1,r26,GPR_BYTES; Restore the stack pointer and remove the
274 ; mach_header argument.
275 bctr ; jump to the program's entry point
276
277 .globl dyld_stub_binding_helper
278 dyld_stub_binding_helper:
279 trap
280 L_end:
281 #endif /* __ppc__ */
282
283 #if __arm__
284 .data
285 .align 2
286 __dyld_start_static_picbase:
287 .long L__dyld_start_picbase
288
289 .text
290 .align 2
291 .globl _stub_binding_helper
292 _stub_binding_helper:
293 b _stub_binding_helper_interface
294 nop
295
296 .globl _dyld_func_lookup
297 _dyld_func_lookup:
298 b _branch_to_lookupDyldFunction
299 nop
300
301 _offset_to_dyld_all_image_infos:
302 .long _dyld_all_image_infos - . + 0x1010
303 .long 0
304 # space for future stable entry points
305 .space 16
306
307
308 // Hack to make ___dso_handle work
309 // Without this local symbol, assembler will error out about in subtraction expression
310 // The real ___dso_handle (non-weak) sythesized by the linker
311 // Since this one is weak, the linker will throw this one away and use the real one instead.
312 .data
313 .globl ___dso_handle
314 .weak_definition ___dso_handle
315 ___dso_handle: .long 0
316
317 .text
318 .align 2
319 __dyld_start:
320 mov r8, sp // save stack pointer
321 sub sp, #8 // make room for outgoing dyld_mh parameter
322 bic sp, sp, #7 // force 8-byte alignment
323
324 // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
325
326 ldr r3, L__dyld_start_picbase_ptr
327 L__dyld_start_picbase:
328 sub r0, pc, #8 // load actual PC
329 ldr r3, [r0, r3] // load expected PC
330 sub r3, r0, r3 // r3 = slide
331
332 ldr r0, [r8] // r0 = mach_header
333 ldr r1, [r8, #4] // r1 = argc
334 add r2, r8, #8 // r2 = argv
335
336 ldr r4, Lmh
337 L3: add r4, r4, pc // r4 = dyld_mh
338 str r4, [sp, #0]
339
340 bl __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_
341
342 // clean up stack and jump to result
343 add sp, r8, #4 // remove the mach_header argument.
344 bx r0 // jump to the program's entry point
345
346
347 .align 2
348 L__dyld_start_picbase_ptr:
349 .long __dyld_start_static_picbase-L__dyld_start_picbase
350 Lmh: .long ___dso_handle-L3-8
351
352 .text
353 .align 2
354 _branch_to_lookupDyldFunction:
355 // arm has no "bx label" instruction, so need this island in case lookupDyldFunction() is in thumb
356 ldr ip, L2
357 L1: ldr pc, [pc, ip]
358 L2: .long _lookupDyldFunction_ptr-8-L1
359
360 .data
361 .align 2
362 _lookupDyldFunction_ptr:
363 .long __Z18lookupDyldFunctionPKcPm
364
365
366 .text
367 .globl dyld_stub_binding_helper
368 dyld_stub_binding_helper:
369 trap
370
371 L_end:
372 #endif /* __arm__ */
373
374 /*
375 * dyld calls this function to terminate a process.
376 * It has a label so that CrashReporter can distinguish this
377 * termination from a random crash. rdar://problem/4764143
378 */
379 .text
380 .align 2
381 .globl _dyld_fatal_error
382 _dyld_fatal_error:
383 #if __ppc__ || __ppc64__ || __arm__
384 trap
385 nop
386 #elif __x86_64__ || __i386__
387 int3
388 nop
389 #else
390 #error unknown architecture
391 #endif
392
393 #if __arm__
394 // work around for: <rdar://problem/6530727> gdb-1109: notifier in dyld does not work if it is in thumb
395 .text
396 .align 2
397 .globl _gdb_image_notifier
398 .private_extern _gdb_image_notifier
399 _gdb_image_notifier:
400 bx lr
401 #endif
402
403
404
405