1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
27 #include <sys/types.h>
33 #if !defined (__GNUC__) || __GNUC__ < 2
34 #error This file uses GNU C extensions; you must compile with GCC version 2.
37 /* The first piece of initialized data. */
39 #ifdef HAVE_WEAK_SYMBOLS
40 weak_alias (__data_start
, data_start
)
45 #ifdef HAVE_WEAK_SYMBOLS
46 weak_alias (__environ
, environ
)
49 #define __environ environ
54 extern void EXFUN(__libc_init
, (int argc
, char **argv
, char **envp
));
55 extern int EXFUN(main
, (int argc
, char **argv
, char **envp
));
57 register long int sp
asm("%sp"), fp
asm("%fp");
60 static void EXFUN(init_shlib
, (NOARGS
));
63 #ifndef NO_EXPLICIT_START
64 /* Declare _start with an explicit assembly symbol name of `start'
65 (note no leading underscore). This is the name Sun's crt0.o uses,
66 and programs are often linked with `ld -e start'. */
67 void _start (void) asm ("start");
73 /* It is important that these be declared `register'.
74 Otherwise, when compiled without optimization, they are put on the
75 stack, which loses completely after we zero the FP. */
77 register char **argv
, **envp
;
79 /* Unwind the frame built when we entered the function. */
82 /* And clear the frame pointer. */
85 /* The argument info starts after one register
86 window (64 bytes) past the SP. */
87 argc
= ((int *) sp
)[16];
88 argv
= (char **) &((int *) sp
)[17];
89 envp
= &argv
[argc
+ 1];
96 /* Allocate 24 bytes of stack space for the register save area. */
98 __libc_init (argc
, argv
, envp
);
100 exit (main (argc
, argv
, envp
));
105 /* System calls for use by the bootstrap routine.
106 These are defined here since the usual calls may be dynamically linked. */
108 int syscall (int sysno
, ...) asm ("init_syscall");
109 asm ("init_syscall:\n"
113 " sethi %hi(_errno), %g1\n"
114 " st %o0, [%g1 + %lo(_errno)]\n"
120 DEFUN_VOID(init_shlib
)
122 extern struct link_dynamic _DYNAMIC
;
127 void (*ldstart
) (int, int);
134 struct link_dynamic
*crt_dp
;
139 /* If not dynamically linked, do nothing. */
143 /* Map in the dynamic linker. */
144 so
= syscall (SYS_open
, "/usr/lib/ld.so", O_RDONLY
);
145 if (syscall (SYS_read
, so
, &soexec
, sizeof (soexec
)) != sizeof (soexec
)
146 || soexec
.a_magic
!= ZMAGIC
)
148 static CONST
char emsg
[] = "crt0: no /usr/lib/ld.so\n";
150 syscall (SYS_write
, 2, emsg
, sizeof (emsg
) - 1);
151 syscall (SYS_exit
, 127);
153 somap
= (caddr_t
) syscall (SYS_mmap
, 0,
154 soexec
.a_text
+ soexec
.a_data
+ soexec
.a_bss
,
155 PROT_READ
| PROT_EXEC
, _MAP_NEW
| MAP_PRIVATE
,
157 sodmap
= (caddr_t
) syscall (SYS_mmap
, somap
+ soexec
.a_text
, soexec
.a_data
,
158 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
159 _MAP_NEW
| MAP_FIXED
| MAP_PRIVATE
,
161 zf
= syscall (SYS_open
, "/dev/zero", O_RDONLY
);
162 if (soexec
.a_bss
!= 0)
163 sobssmap
= (caddr_t
) syscall (SYS_mmap
,
164 somap
+ soexec
.a_text
+ soexec
.a_data
,
166 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
167 _MAP_NEW
| MAP_FIXED
| MAP_PRIVATE
,
170 /* Call the entry point of the dynamic linker. */
171 soarg
.crt_ba
= somap
;
174 soarg
.crt_dp
= &_DYNAMIC
;
175 soarg
.crt_ep
= __environ
;
176 soarg
.crt_bp
= (caddr_t
) &&retaddr
;
178 ldstart
= (__typeof (ldstart
)) (somap
+ soexec
.a_entry
);
179 (*ldstart
) (1, (char *) &soarg
- (char *) sp
);