/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.1 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* C runtime startup for m68k, i386 and ppc 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.
*
* Kernel sets up stack frame to look like:
*
* | STRING AREA |
* +-------------+
#if defined(__MACH30__) && (defined(__ppc__) || defined(__i386__))
* +-------------+
* | 0 | In MacOS X PR2 Beaker2E the path passed to exec() is
* +-------------+ passed on the stack just after the trailing 0 of the
* | exec_path | the envp[] array as a pointer to a string. See the
* +-------------+ code at the end of pickup_environment_variables().
#endif
* +-------------+
* | 0 |
* +-------------+
* | env[n] |
* +-------------+
* :
* :
* +-------------+
* | env[0] |
* +-------------+
* | 0 |
* +-------------+
* | arg[argc-1] |
* +-------------+
* :
* :
* +-------------+
* | arg[0] |
* +-------------+
* | argc |
* +-------------+
* sp-> | mh | address of where the a.out's file offset 0 is in memory
* +-------------+
*
* Where arg[i] and env[i] point into the STRING AREA
*/
#ifdef m68k
.text
.even
L_start:
.stabs "dyld_start.s",100,0,0,L_start
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.globl __dyld_start
__dyld_start:
lea pc@(-2),a1 | Set d1 to the difference between where we
movel a1,d1 | started executing at and __dyld_start to know
subl #__dyld_start,d1| if the kernel slid this code.
movl sp,a0 | pointer to base of kernel frame
subw #16,sp | room for new mh, argc, argv, & envp
movl a0@+,sp@ | mh to reserved stack word and a0 to pt to argc
movl a0@+,d0 | pickup argc and bump a0 to pt to arg[0]
movl d0,sp@(4) | argc to reserved stack word
movl a0,sp@(8) | argv to reserved stack word
addql #1,d0 | argc + 1 for zero word
asll #2,d0 | * sizeof(char *)
addl d0,a0 | addr of env[0]
movl a0,sp@(12) | envp to reserved stack word
cmpl #0,d1 | If this code was slid we have to relocate
beq 1f | ourself before we get going.
movel d1,sp@-
bsr __dyld_reloc | _dyld_reloc(slide_amount)
addw #4,sp
1:
bsr _mach_init | call mach_init() so we can make mach calls
bsr __dyld_init | _dyld_init(mh, argc, argv, envp)
movl d0,a0 | put entry point in a0
addw #20,sp | deallocate room for new mh, argc, argv, & envp
| and remove the mh argument
jmp a0@ | jump to the entry point
.globl dyld_stub_binding_helper
dyld_stub_binding_helper:
trapt.l #0xfeadface
.stabs "",100,0,0,L_end
L_end:
#endif /* m68k */
#ifdef __i386__
.text
.align 4, 0x90
L_start:
.stabs "dyld_start.s",100,0,0,L_start
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.globl __dyld_start
__dyld_start:
call L1 # Set %eax to the difference between
L1: popl %eax # where we started executing at and
subl $L1-__dyld_start,%eax # __dyld_start to know if the kernel
subl $__dyld_start,%eax # slid this code.
pushl $0 # push a zero for debugger end of frames marker
movl %esp,%ebp # pointer to base of kernel frame
subl $16,%esp # room for new mh, argc, argv, & envp
movl 4(%ebp),%ebx # pickup mh in %ebx
movl %ebx,0(%esp) # mh to reserved stack word
movl 8(%ebp),%ebx # pickup argc in %ebx
movl %ebx,4(%esp) # argc to reserved stack word
lea 12(%ebp),%ecx # addr of arg[0], argv, into %ecx
movl %ecx,8(%esp) # argv to reserved stack word
addl $1,%ebx # argc + 1 for zero word
sall $2,%ebx # * sizeof(char *)
addl %ecx,%ebx # addr of env[0], envp, into %ebx
movl %ebx,12(%esp) # envp to reserved stack word
cmpl $0,%eax # If this code was slid we have to relocate
je 1f # ourself before we get going.
pushl %eax
call __dyld_reloc # _dyld_reloc(slide_amount)
addl $4,%esp
1:
call _mach_init # call mach_init() so we can make mach calls
call __dyld_init # _dyld_init(mh, argc, argv, envp)
addl $24,%esp # deallocate room for new mh, argc, argv, & envp
# and remove the mh argument, and debugger end
# frame marker
movl $0,%ebp # restore ebp back to zero
jmp %eax # jump to the entry point
.globl dyld_stub_binding_helper
dyld_stub_binding_helper:
hlt
.stabs "",100,0,0,L_end
L_end:
#endif /* __i386__ */
#ifdef __ppc__
.text
.align 2
L_start:
.stabs "dyld_start.s",100,0,0,L_start
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.globl __dyld_start
__dyld_start:
bcl 20,31,L1 lis r12,hi16(L1) sub r11,r11,r12 mr r26,r1 subi r1,r1,64 lwz r30,0(r3) addi r28,r3,8 slwi r4,r4,2
cmpwi cr1,r11,0 mr r3,r11 L2:
bl _mach_init mr r3,r30 mr r5,r28 bl __dyld_init mr r12,r3
.globl dyld_stub_binding_helper
dyld_stub_binding_helper:
trap
.stabs "",100,0,0,L_end
L_end:
#endif /* __ppc__ */
#ifdef hppa
/*
* C runtime startup for hppa 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 (mh) passed as the an extra first argument.
*
* Kernel sets up stack frame to look like:
*
* +-------------+
* sp-> | ap | HIGH ADDRESS
* +-------------+
* | 0 | <-xxx (I don't know what this value is called
* +-------------+ but it is the first thing on the stack see
* | STRING AREA | below at the lowest address).
* +-------------+
* | 0 |
* +-------------+
* | env[n] |
* +-------------+
* :
* :
* +-------------+
* | env[0] |
* +-------------+
* | 0 |
* +-------------+
* | arg[argc-1] |
* +-------------+
* :
* :
* +-------------+
* | arg[0] |
* +-------------+
* ap-> | argc |
* +-------------+
* | mh |
* +-------------+
* | xxx | LOW ADDRESS (first word on the stack)
* +-------------+
*
* Where arg[i] and env[i] point into the STRING AREA
*
* Initial sp points to a pointer to argc. Stack then
* grows upward from sp. [Special calling convention for
* PA-RISC and other architectures which grow upward].
*/
.text
.align 2
L_start:
.stabs "dyld_start.s",100,0,0,L_start
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.globl __dyld_start
__dyld_start:
bl L1,%r26 L1: depi 0,31,2,%r26 ldo R`L1-__dyld_start(%r1),%r1 ldil L`__dyld_start,%r2 sub %r26,%r2,%r26
ldo 127(%r30),%r30
combt,=,n %r26,%r0,L2 nop
L2:
bl _mach_init,%r2
ldw -4(%r19),%r26 ldo 4(%r19),%r24 copy %r24,%r23 comib,= 0,%r20,L4 ldws,mb 4(0,%r23),%r20 comib,<>,n 0,%r20,L3
L4:
bl __dyld_init,%r2
copy %r3,%r30 .globl dyld_stub_binding_helper
dyld_stub_binding_helper:
break 0,0
.stabs "",100,0,0,L_end
L_end:
#endif /* hppa */
#ifdef sparc
/*
*
* Kernel sets up stack frame to look like:
*
* On entry the stack frame looks like:
*
* _______________________ <- USRSTACK
* | : |
* | arg and env strings |
* | : |
* |-----------------------|
* | 0 |
* |-----------------------|
* | : |
* | ptrs to env strings |
* |-----------------------|
* | 0 |
* |-----------------------|
* | : |
* | ptrs to arg strings |
* | (argc = # of wds) |
* |-----------------------|
* | argc |
* |-----------------------|
* | mh | <- new mach header arg for dyld
* |-----------------------|
* | window save area |
* | (16 wds) |
* |_______________________| <- %sp
*/
.text
.align 2
L_start:
.stabs "dyld_start.s",100,0,0,L_start
.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
.stabs "char:t2=r2;0;127;",128,0,0,0
.globl __dyld_start
__dyld_start:
! determine our location and slide code if necessary
save %sp, -96, %sp ! get ready to make calls
call L1
dec 4,%o7
L1:
sethi %hi(__dyld_start),%l0 ! get our static address
or %l0,%lo(__dyld_start),%l0
sub %o7,%l0,%l0 ! and compare with entry pc
tst %l0
bz 1f ! not slid
nop
call __dyld_reloc ! relocate ourself
mov %l0,%o0
1:
call _mach_init ! allows us to make mach calls
nop
! build arguments to dyld_init (mh, argc, argv, envp)
mov %fp,%l0
add %l0,16*4,%l0 ! skip over window save area
ld [%l0],%o0 ! 1st arg: mh ptr
ld [%l0+4],%o1 ! 2nd arg: argc
mov %l0,%o2
inc 8,%o2 ! 3rd arg: argv ptr
! now compute the envp ptr
add %o1,1,%o3 ! account for null ptr
sll %o3,2,%o3 ! adjust for ptrs
call __dyld_init ! dyld_init returns our entry point
add %o2,%o3,%o3 ! 4th arg: envp ptr
jmp %o0 ! call the entry point
restore
.globl dyld_stub_binding_helper
dyld_stub_binding_helper:
ta 9
.stabs "",100,0,0,L_end
L_end:
#endif /* sparc */