1/* 2 * Copyright (c) 1999-2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.1 (the "License"). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include <Availability.h> 26 27#if __ppc__ && __DYNAMIC__ 28// 29// Force stub section next to __text section to minimize chance that 30// a bl to a stub will be out of range. 31// 32 .text 33 .symbol_stub 34 .picsymbol_stub 35#endif 36 37/* 38 * C runtime startup for ppc, ppc64, i386, x86_64 39 * 40 * Kernel sets up stack frame to look like: 41 * 42 * : 43 * | STRING AREA | 44 * +-------------+ 45 * | 0 | 46 * +-------------+ 47 * | exec_path | extra "apple" parameters start after NULL terminating env array 48 * +-------------+ 49 * | 0 | 50 * +-------------+ 51 * | env[n] | 52 * +-------------+ 53 * : 54 * : 55 * +-------------+ 56 * | env[0] | 57 * +-------------+ 58 * | 0 | 59 * +-------------+ 60 * | arg[argc-1] | 61 * +-------------+ 62 * : 63 * : 64 * +-------------+ 65 * | arg[0] | 66 * +-------------+ 67 * | argc | argc is always 4 bytes long, even in 64-bit architectures 68 * +-------------+ <- sp 69 * 70 * Where arg[i] and env[i] point into the STRING AREA 71 */ 72 73 .text 74 .globl start 75 .align 2 76 77#if __ppc__ 78start: mr r26,r1 ; save original stack pointer into r26 79 subi r1,r1,4 ; make space for linkage 80 clrrwi r1,r1,5 ; align to 32 bytes (good enough for 32- and 64-bit APIs) 81 li r0,0 ; load 0 into r0 82 stw r0,0(r1) ; terminate initial stack frame 83 stwu r1,-64(r1) ; allocate minimal stack frame 84 lwz r3,0(r26) ; get argc into r3 85 addi r4,r26,4 ; get argv into r4 86 addi r27,r3,1 ; calculate argc + 1 into r27 87 slwi r27,r27,2 ; calculate (argc + 1) * sizeof(char *) into r27 88 add r5,r4,r27 ; get address of env[0] into r5 89#if OLD_LIBSYSTEM_SUPPORT 90 bl __start ; 24-bt branch to __start. ld64 will make a branch island if needed 91 trap ; should never return 92#else 93 mr r6,r5 94Lapple: lwz r0,0(r6) ; look for NULL ending env[] array 95 addi r6,r6,4 96 cmpwi r0,0 97 bne Lapple ; once found, next pointer is "apple" parameter now in r6 98 bl _main 99 b _exit ; pass result from main() to exit() 100#endif 101#endif // __ppc__ 102 103 104#if __ppc64__ 105start: mr r26,r1 ; save original stack pointer into r26 106 subi r1,r1,8 ; make space for linkage 107 clrrdi r1,r1,5 ; align to 32 bytes (good enough for 32- and 64-bit APIs) 108 li r0,0 ; load 0 into r0 109 std r0,0(r1) ; terminate initial stack frame 110 stdu r1,-128(r1) ; allocate minimal stack frame 111 lwz r3,0(r26) ; get argc into r3 112 addi r4,r26,8 ; get argv into r4 113 addi r27,r3,1 ; calculate argc + 1 into r27 114 sldi r27,r27,3 ; calculate (argc + 1) * sizeof(char *) into r27 115 add r5,r4,r27 ; get address of env[0] into r5 116#if OLD_LIBSYSTEM_SUPPORT 117 bl __start ; 24-bt branch to __start. ld64 will make a branch island if needed 118 trap ; should never return 119#else 120 mr r6,r5 121Lapple: ld r0,0(r6) ; look for NULL ending env[] array 122 addi r6,r6,8 123 cmpdi r0,0 124 bne Lapple ; once found, next pointer is "apple" parameter now in r6 125 bl _main 126 b _exit ; pass result from main() to exit() 127#endif 128#endif // __ppc64__ 129 130 131#if __i386__ 132start: pushl $0 # push a zero for debugger end of frames marker 133 movl %esp,%ebp # pointer to base of kernel frame 134 andl $-16,%esp # force SSE alignment 135 subl $16,%esp # room for new argc, argv, & envp, SSE aligned 136 movl 4(%ebp),%ebx # pickup argc in %ebx 137 movl %ebx,0(%esp) # argc to reserved stack word 138 lea 8(%ebp),%ecx # addr of arg[0], argv, into %ecx 139 movl %ecx,4(%esp) # argv to reserved stack word 140 addl $1,%ebx # argc + 1 for zero word 141 sall $2,%ebx # * sizeof(char *) 142 addl %ecx,%ebx # addr of env[0], envp, into %ebx 143 movl %ebx,8(%esp) # envp to reserved stack word 144#if OLD_LIBSYSTEM_SUPPORT 145 call __start # call _start(argc, argv, envp) 146 hlt # should never return 147#else 148Lapple: movl (%ebx),%eax # look for NULL ending env[] array 149 add $4,%ebx 150 testl %eax,%eax 151 jne Lapple # once found, next pointer is "apple" parameter now in %ebx 152 movl %ebx,12(%esp) # apple to reserved stack word 153 call _main 154 movl %eax, 0(%esp) # pass result from main() to exit() 155 call _exit # need to use call to keep stack aligned 156 hlt 157#endif 158#endif // __i386__ 159 160 161 162#if __x86_64__ 163start: pushq $0 # push a zero for debugger end of frames marker 164 movq %rsp,%rbp # pointer to base of kernel frame 165 andq $-16,%rsp # force SSE alignment 166 movq 8(%rbp),%rdi # put argc in %rdi 167 leaq 16(%rbp),%rsi # addr of arg[0], argv, into %rsi 168 movl %edi,%edx # copy argc into %rdx 169 addl $1,%edx # argc + 1 for zero word 170 sall $3,%edx # * sizeof(char *) 171 addq %rsi,%rdx # addr of env[0], envp, into %rdx 172#if OLD_LIBSYSTEM_SUPPORT 173 call __start # call _start(argc, argv, envp) 174 hlt # should never return 175#else 176 movq %rdx,%rcx 177 jmp Lapple2 178Lapple: add $8,%rcx 179Lapple2:cmpq $0,(%rcx) # look for NULL ending env[] array 180 jne Lapple 181 add $8,%rcx # once found, next pointer is "apple" parameter now in %rcx 182 call _main 183 movl %eax,%edi # pass result from main() to exit() 184 call _exit # need to use call to keep stack aligned 185 hlt 186#endif 187#endif // __x86_64__ 188 189#ifdef __arm__ 190start: 191 ldr r0, [sp] // get argc into r0 192 add r1, sp, #4 // get argv into r1 193 add r4, r0, #1 // calculate argc + 1 into r4 194 add r2, r1, r4, lsl #2 // get address of env[0] into r2 195 bic sp, sp, #7 // force eight-byte alignment 196#if OLD_LIBSYSTEM_SUPPORT 197 bl __start 198 .long 0xe1200070 // should never return 199#else 200 mov r3, r2 201Lapple: 202 ldr r4, [r3], #4 // look for NULL ending env[] array 203 cmp r4, #0 204 bne Lapple 205 // "apple" param now in r3 206#if __STATIC__ || ((__IPHONE_OS_VERSION_MIN_REQUIRED >= 30100) && !__ARM_ARCH_4T__) 207 bl _main 208 b _exit 209#else 210// use -mlong-branch style call sites so that main executable can be >32MB 211 ldr ip, L4 212L2: add ip, pc, ip 213 ldr ip, [ip, #0] 214#if __ARM_ARCH_4T__ 215 mov lr, pc // blx not supported, so simulate it in two steps 216 bx ip 217#else 218 blx ip // call main() 219#endif 220 221 ldr ip, L5 222L3: add ip, pc, ip 223 ldr ip, [ip, #0] 224 bx ip // jmp exit() 225 226L4: .long L_main$non_lazy_ptr-(L2+8) 227L5: .long L_exit$non_lazy_ptr-(L3+8) 228 229 .non_lazy_symbol_pointer 230L_main$non_lazy_ptr: 231 .indirect_symbol _main 232 .long 0 233L_exit$non_lazy_ptr: 234 .indirect_symbol _exit 235 .long 0 236#endif 237 238 239#endif 240#endif /* __arm__ */ 241 242 243#if __arm64__ 244 245start: 246 mov x5, sp 247 ldr x0, [x5] ; get argc into x0 (kernel passes 32-bit int argc as 64-bits on stack to keep alignment) 248 add x1, x5, #8 ; get argv into x1 249 add x4, x0, #1 ; argc + 1 250 add x2, x1, x4, lsl #3 ; &env[0] = (argc+1)*8 251 and sp, x5, #~15 ; force 16-byte alignment of stack 252 mov x3, x2 253L1: ldr x4, [x3], #8 254 cmp x4, #0 ; look for NULL ending env[] array 255 b.ne L1 256 bl _main ; main(x0=argc, x1=argv, x2=envp, x3=apple) 257 b _exit 258 259#endif /* __arm64__ */ 260 261 262// This code has be written to allow dead code stripping 263 .subsections_via_symbols 264