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