]> git.saurik.com Git - apple/dyld.git/blobdiff - src/dyldStartup.s
dyld-360.22.tar.gz
[apple/dyld.git] / src / dyldStartup.s
index e1214f80e32d3337883801cbfbd1def670e3e533..71d45a3ccad603e8f3546e4790b620a23f7d85ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*
- * C runtime startup for i386 and ppc interface to the dynamic linker.
+ * C runtime startup for interface to the dynamic linker.
  * This is the same as the entry point in crt0.o with the addition of the
  * address of the mach header passed as the an extra first argument.
  *
  */
 
 
-
-       // Hack to make _offset_to_dyld_all_image_infos work
-       // Without this local symbol, assembler will error out about in subtraction expression
-       // The real _dyld_all_image_infos (non-weak) _dyld_all_image_infos is defined in dyld_gdb.o
-       // and the linker with throw this one away and use the real one instead.
-       .section __DATA,__datacoal_nt,coalesced
-       .globl _dyld_all_image_infos
-       .weak_definition _dyld_all_image_infos
-_dyld_all_image_infos: .long 0
-
-
+#include <TargetConditionals.h>
 
        .globl __dyld_start
 
 #ifdef __i386__
-       .data
-__dyld_start_static_picbase: 
-       .long   L__dyld_start_picbase
-
-
-       .text
-       .align 2
-# stable entry points into dyld
-       .globl  _stub_binding_helper
-_stub_binding_helper:
-       jmp     _stub_binding_helper_interface
-       nop
-       nop
-       nop
-       .globl  _dyld_func_lookup
-_dyld_func_lookup:
-       jmp     __Z18lookupDyldFunctionPKcPm
-       nop
-       nop
-       nop
-_offset_to_dyld_all_image_infos:
-       .long   _dyld_all_image_infos - . + 0x1010 
-       .long   0
-       # space for future stable entry points
-       .space  16
 
-       
-       
+#if !TARGET_IPHONE_SIMULATOR
        .text
        .align  4, 0x90
        .globl __dyld_start
 __dyld_start:
+       popl    %edx            # edx = mh of app
        pushl   $0              # push a zero for debugger end of frames marker
        movl    %esp,%ebp       # pointer to base of kernel frame
        andl    $-16,%esp       # force SSE alignment
+       subl    $32,%esp        # room for locals and outgoing parameters
        
-       # call dyldbootstrap::start(app_mh, argc, argv, slide)
        call    L__dyld_start_picbase
 L__dyld_start_picbase: 
        popl    %ebx            # set %ebx to runtime value of picbase
-       movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
-       subl    %eax, %ebx      # slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
-       pushl   %ebx            # param4 = slide
-       lea     12(%ebp),%ebx   
-       pushl   %ebx            # param3 = argv
-       movl    8(%ebp),%ebx    
-       pushl   %ebx            # param2 = argc
-       movl    4(%ebp),%ebx    
-       pushl   %ebx            # param1 = mh
-       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKcl        
-
-       # clean up stack and jump to result
+
+       movl    Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
+       movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
+       subl    %eax, %ebx      # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
+       addl    %ebx, %ecx      # ecx = actual load address
+       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
+       movl    %edx,(%esp)     # param1 = app_mh
+       movl    4(%ebp),%eax    
+       movl    %eax,4(%esp)    # param2 = argc
+       lea     8(%ebp),%eax    
+       movl    %eax,8(%esp)    # param3 = argv
+       movl    %ebx,12(%esp)   # param4 = slide
+       movl    %ecx,16(%esp)   # param5 = actual load address
+       lea     28(%esp),%eax
+       movl    %eax,20(%esp)   # param6 = &startGlue
+       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm   
+       movl    28(%esp),%edx
+       cmpl    $0,%edx
+       jne     Lnew
+
+       # clean up stack and jump to "start" in main executable
        movl    %ebp,%esp       # restore the unaligned stack pointer
-       addl    $8,%esp         # remove the mh argument, and debugger end
-                               #  frame marker
+       addl    $4,%esp         # remove debugger end frame marker
        movl    $0,%ebp         # restore ebp back to zero
        jmp     *%eax           # jump to the entry point
 
+       # LC_MAIN case, set up stack for call to main() 
+Lnew:  movl    4(%ebp),%ebx
+       movl    %ebx,(%esp)     # main param1 = argc
+       leal    8(%ebp),%ecx
+       movl    %ecx,4(%esp)    # main param2 = argv
+       leal    0x4(%ecx,%ebx,4),%ebx
+       movl    %ebx,8(%esp)    # main param3 = env
+Lapple:        movl    (%ebx),%ecx     # look for NULL ending env[] array
+       add     $4,%ebx
+       testl   %ecx,%ecx
+       jne     Lapple          # once found, next pointer is "apple" parameter now in %ebx
+       movl    %ebx,12(%esp)   # main param4 = apple
+       pushl   %edx            # simulate return address into _start in libdyld
+       jmp     *%eax           # jump to main(argc,argv,env,apple) with return address set to _start
+#endif 
+
+#if !TARGET_IPHONE_SIMULATOR
+       .data
+__dyld_start_static_picbase: 
+       .long   L__dyld_start_picbase
+Lmh:   .long   ___dso_handle
+#endif
+
 
-       .globl dyld_stub_binding_helper
-dyld_stub_binding_helper:
-       hlt
-L_end:
 #endif /* __i386__ */
 
 
 
 #if __x86_64__
+#if !TARGET_IPHONE_SIMULATOR
        .data
        .align 3
 __dyld_start_static: 
        .quad   __dyld_start
-
-# stable entry points into dyld
-       .text
-       .align 2
-       .globl  _stub_binding_helper
-_stub_binding_helper:
-       jmp     _stub_binding_helper_interface
-       nop
-       nop
-       nop
-       .globl  _dyld_func_lookup
-_dyld_func_lookup:
-       jmp     __Z18lookupDyldFunctionPKcPm
-       nop
-       nop
-       nop
-_offset_to_dyld_all_image_infos:
-       .long   _dyld_all_image_infos - . + 0x1010 
-       .long   0
-       # space for future stable entry points
-       .space  16
+#endif
 
 
+#if !TARGET_IPHONE_SIMULATOR
        .text
        .align 2,0x90
        .globl __dyld_start
 __dyld_start:
+       popq    %rdi            # param1 = mh of app
        pushq   $0              # push a zero for debugger end of frames marker
        movq    %rsp,%rbp       # pointer to base of kernel frame
        andq    $-16,%rsp       # force SSE alignment
+       subq    $16,%rsp        # room for local variables
        
-       # call dyldbootstrap::start(app_mh, argc, argv, slide)
-       movq    8(%rbp),%rdi    # param1 = mh into %rdi
-       movl    16(%rbp),%esi   # param2 = argc into %esi
-       leaq    24(%rbp),%rdx   # param3 = &argv[0] into %rdx
+       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
+       movl    8(%rbp),%esi    # param2 = argc into %esi
+       leaq    16(%rbp),%rdx   # param3 = &argv[0] into %rdx
        movq    __dyld_start_static(%rip), %r8
        leaq    __dyld_start(%rip), %rcx
        subq     %r8, %rcx      # param4 = slide into %rcx
-       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKcl        
-
-       # clean up stack and jump to result
+       leaq    ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
+       leaq    -8(%rbp),%r9
+       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
+       movq    -8(%rbp),%rdi
+       cmpq    $0,%rdi
+       jne     Lnew
+
+       # clean up stack and jump to "start" in main executable
        movq    %rbp,%rsp       # restore the unaligned stack pointer
-       addq    $16,%rsp        # remove the mh argument, and debugger end frame marker
+       addq    $8,%rsp         # remove the mh argument, and debugger end frame marker
        movq    $0,%rbp         # restore ebp back to zero
        jmp     *%rax           # jump to the entry point
        
+       # LC_MAIN case, set up stack for call to main() 
+Lnew:  addq    $16,%rsp        # remove local variables
+       pushq   %rdi            # simulate return address into _start in libdyld
+       movq    8(%rbp),%rdi    # main param1 = argc into %rdi
+       leaq    16(%rbp),%rsi   # main param2 = &argv[0] into %rsi
+       leaq    0x8(%rsi,%rdi,8),%rdx # main param3 = &env[0] into %rdx
+       movq    %rdx,%rcx
+Lapple: movq   (%rcx),%r8
+       add     $8,%rcx
+       testq   %r8,%r8         # look for NULL ending env[] array
+       jne     Lapple          # main param4 = apple into %rcx
+       jmp     *%rax           # jump to main(argc,argv,env,apple) with return address set to _start
+
+#endif /* TARGET_IPHONE_SIMULATOR */
 #endif /* __x86_64__ */
 
 
-#if __ppc__ || __ppc64__
-#include <architecture/ppc/mode_independent_asm.h>
-
-       .data
-       .align 2
-__dyld_start_static_picbase: 
-       .g_long   L__dyld_start_picbase
-
-#if __ppc__    
-       .set L_mh_offset,0
-       .set L_argc_offset,4
-       .set L_argv_offset,8
-#else
-       .set L_mh_offset,0
-       .set L_argc_offset,8    ; stack is 8-byte aligned and there is a 4-byte hole between argc and argv
-       .set L_argv_offset,16
-#endif
-
-       .text
-       .align 2
-; stable entry points into dyld
-       .globl  _stub_binding_helper
-_stub_binding_helper:
-       b       _stub_binding_helper_interface
-       nop 
-       .globl  _dyld_func_lookup
-_dyld_func_lookup:
-       b       __Z18lookupDyldFunctionPKcPm
-       nop 
-_offset_to_dyld_all_image_infos:
-       .long   _dyld_all_image_infos - . + 0x1010 
-       .long   0
-       # space for future stable entry points
-       .space  16
-       
-       
-       .text
-       .align 2
-__dyld_start:
-       mr      r26,r1          ; save original stack pointer into r26
-       subi    r1,r1,GPR_BYTES ; make space for linkage
-       clrrgi  r1,r1,5         ; align to 32 bytes
-       addi    r0,0,0          ; load 0 into r0
-       stg     r0,0(r1)        ; terminate initial stack frame
-       stgu    r1,-SF_MINSIZE(r1); allocate minimal stack frame
-               
-       ; call dyldbootstrap::start(app_mh, argc, argv, slide)
-       lg      r3,L_mh_offset(r26)     ; r3 = mach_header
-       lwz     r4,L_argc_offset(r26)   ; r4 = argc (int == 4 bytes)
-       addi    r5,r26,L_argv_offset    ; r5 = argv
-       bcl     20,31,L__dyld_start_picbase     
-L__dyld_start_picbase: 
-       mflr    r31             ; put address of L__dyld_start_picbase in r31
-       addis   r6,r31,ha16(__dyld_start_static_picbase-L__dyld_start_picbase)
-       lg      r6,lo16(__dyld_start_static_picbase-L__dyld_start_picbase)(r6)
-       subf    r6,r6,r31       ; r6 = slide
-       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKcl        
-       
-       ; clean up stack and jump to result
-       mtctr   r3              ; Put entry point in count register
-       mr      r12,r3          ;  also put in r12 for ABI convention.
-       addi    r1,r26,GPR_BYTES; Restore the stack pointer and remove the
-                               ;  mach_header argument.
-       bctr                    ; jump to the program's entry point
-
-       .globl dyld_stub_binding_helper
-dyld_stub_binding_helper:
-       trap
-L_end:
-#endif /* __ppc__ */
 
 #if __arm__
+       .syntax unified
        .data
        .align 2
 __dyld_start_static_picbase: 
        .long   L__dyld_start_picbase
 
-       .text
-       .align 2
-       .globl  _stub_binding_helper
-_stub_binding_helper:
-       b       _stub_binding_helper_interface
-       nop 
-       
-       .globl  _dyld_func_lookup
-_dyld_func_lookup:
-       b       _branch_to_lookupDyldFunction
-       nop
-       
-_offset_to_dyld_all_image_infos:
-       .long   _dyld_all_image_infos - . + 0x1010 
-       .long   0
-       # space for future stable entry points
-       .space  16
-    
     
+       // Hack to make ___dso_handle work
+       // Without this local symbol, assembler will error out about in subtraction expression
+       // The real ___dso_handle (non-weak) sythesized by the linker
+       // Since this one is weak, the linker will throw this one away and use the real one instead.
+       .data
+       .globl ___dso_handle
+       .weak_definition ___dso_handle
+___dso_handle: .long 0
+
        .text
        .align 2
 __dyld_start:
-       // call dyldbootstrap::start(app_mh, argc, argv, slide)         
+       mov     r8, sp          // save stack pointer
+       sub     sp, #16         // make room for outgoing parameters
+       bic     sp, sp, #15     // force 16-byte alignment
+
+       // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
 
        ldr     r3, L__dyld_start_picbase_ptr
 L__dyld_start_picbase:
@@ -307,45 +227,102 @@ L__dyld_start_picbase:
        ldr     r3, [r0, r3]    // load expected PC
        sub     r3, r0, r3      // r3 = slide
 
-       ldr     r0, [sp]        // r0 = mach_header
-       ldr     r1, [sp, #4]    // r1 = argc
-       add     r2, sp, #8      // r2 = argv
+       ldr     r0, [r8]        // r0 = mach_header
+       ldr     r1, [r8, #4]    // r1 = argc
+       add     r2, r8, #8      // r2 = argv
 
-       mov     r8, sp          // save stack pointer
-       bic     sp, sp, #7      // force 8-byte alignment
+       ldr     r4, Lmh
+L3:    add     r4, r4, pc      
+       str     r4, [sp, #0]    // [sp] = dyld_mh
+       add     r4, sp, #12
+       str     r4, [sp, #4]    // [sp+4] = &startGlue
        
-       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKcl
-       
-       // clean up stack and jump to result
+       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
+       ldr     r5, [sp, #12]
+       cmp     r5, #0
+       bne     Lnew
+       
+       // traditional case, clean up stack and jump to result
        add     sp, r8, #4      // remove the mach_header argument.
        bx      r0              // jump to the program's entry point
 
+       // LC_MAIN case, set up stack for call to main()
+Lnew:  mov     lr, r5              // simulate return address into _start in libdyld
+       mov     r5, r0              // save address of main() for later use
+       ldr     r0, [r8, #4]        // main param1 = argc
+       add     r1, r8, #8          // main param2 = argv
+       add     r2, r1, r0, lsl #2  
+       add     r2, r2, #4          // main param3 = &env[0]
+       mov     r3, r2
+Lapple:        ldr     r4, [r3]
+       add     r3, #4
+       cmp     r4, #0
+       bne     Lapple              // main param4 = apple
+       bx      r5
+
        .align 2
 L__dyld_start_picbase_ptr:
        .long   __dyld_start_static_picbase-L__dyld_start_picbase
+Lmh:   .long   ___dso_handle-L3-8
+
+#endif /* __arm__ */
+
+
+
+
+#if __arm64__
+       .data
+       .align 3
+__dso_static: 
+       .quad   ___dso_handle
 
-       
        .text
        .align 2
-_branch_to_lookupDyldFunction:
-       // arm has no "bx label" instruction, so need this island in case lookupDyldFunction() is in thumb
-       ldr ip, L2
-L1:    ldr pc, [pc, ip]
-L2:    .long   _lookupDyldFunction_ptr-8-L1
-       
-       .data
-       .align 2
-_lookupDyldFunction_ptr:
-       .long   __Z18lookupDyldFunctionPKcPm
+       .globl __dyld_start
+__dyld_start:
+       mov     x28, sp
+       and     sp, x28, #~15           // force 16-byte alignment of stack
+       mov     x0, #0
+       mov     x1, #0
+       stp     x1, x0, [sp, #-16]!     // make aligned terminating frame
+       mov     fp, sp                  // set up fp to point to terminating frame
+       sub     sp, sp, #16             // make room for local variables
+       ldr     x0, [x28]               // get app's mh into x0
+       ldr     x1, [x28, #8]           // get argc into x1 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment)
+       add     x2, x28, #16            // get argv into x2
+       adrp    x4,___dso_handle@page
+       add     x4,x4,___dso_handle@pageoff // get dyld's mh in to x4
+       adrp    x3,__dso_static@page
+       ldr     x3,[x3,__dso_static@pageoff] // get unslid start of dyld
+       sub     x3,x4,x3                // x3 now has slide of dyld
+       mov     x5,sp                   // x5 has &startGlue
        
-      
-       .text
-       .globl dyld_stub_binding_helper
-dyld_stub_binding_helper:
-       trap
+       // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
+       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
+       mov     x16,x0                  // save entry point address in x16
+       ldr     x1, [sp]
+       cmp     x1, #0
+       b.ne    Lnew
+
+       // LC_UNIXTHREAD way, clean up stack and jump to result
+       add     sp, x28, #8             // restore unaligned stack pointer without app mh
+       br      x16                     // jump to the program's entry point
+
+       // LC_MAIN case, set up stack for call to main()
+Lnew:  mov     lr, x1              // simulate return address into _start in libdyld.dylib
+       ldr     x0, [x28, #8]       // main param1 = argc
+       add     x1, x28, #16        // main param2 = argv
+       add     x2, x1, x0, lsl #3  
+       add     x2, x2, #8          // main param3 = &env[0]
+       mov     x3, x2
+Lapple:        ldr     x4, [x3]
+       add     x3, x3, #8
+       cmp     x4, #0
+       b.ne    Lapple              // main param4 = apple
+       br      x16
+
+#endif // __arm64__
 
-L_end:
-#endif /* __arm__ */
 
 /*
  * dyld calls this function to terminate a process.
@@ -356,17 +333,28 @@ L_end:
        .align 2
        .globl  _dyld_fatal_error
 _dyld_fatal_error:
-#if __ppc__ || __ppc64__ || __arm__
+#if __arm__
     trap
     nop
 #elif __x86_64__ || __i386__
     int3
     nop
+#elif __arm64__
+    brk        #3
 #else
     #error unknown architecture
 #endif
 
-    
-    
+#if __arm__
+       // work around for:  <rdar://problem/6530727> gdb-1109: notifier in dyld does not work if it is in thumb
+       .text
+       .align 2
+       .globl  _gdb_image_notifier
+       .private_extern _gdb_image_notifier
+_gdb_image_notifier:
+       bx  lr
+#endif
+
+