1 /* Copyright (C) 1991,92,93,94,95,96,97,2004 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, write to the Free
33 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
43 #include <sys/types.h>
49 #if !defined (__GNUC__) || __GNUC__ < 2
50 #error This file uses GNU C extensions; you must compile with GCC version 2.
53 /* The first piece of initialized data. */
55 #ifdef HAVE_WEAK_SYMBOLS
56 weak_alias (__data_start
, data_start
)
59 extern void __libc_init (int argc
, char **argv
, char **envp
) __THROW
;
60 extern int main (int argc
, char **argv
, char **envp
) __THROW
;
62 register long int sp
asm("%sp"), fp
asm("%fp");
65 static void init_shlib (void) __THROW
;
68 #ifndef NO_EXPLICIT_START
69 /* Declare _start with an explicit assembly symbol name of `start'
70 (note no leading underscore). This is the name Sun's crt0.o uses,
71 and programs are often linked with `ld -e start'. */
72 void _start (void) asm ("start");
78 /* It is important that these be declared `register'.
79 Otherwise, when compiled without optimization, they are put on the
80 stack, which loses completely after we zero the FP. */
82 register char **argv
, **envp
;
84 /* Unwind the frame built when we entered the function. */
87 /* And clear the frame pointer. */
90 /* The argument info starts after one register
91 window (64 bytes) past the SP. */
92 argc
= ((int *) sp
)[16];
93 argv
= (char **) &((int *) sp
)[17];
94 envp
= &argv
[argc
+ 1];
101 /* Allocate 24 bytes of stack space for the register save area. */
103 __libc_init (argc
, argv
, envp
);
105 exit (main (argc
, argv
, envp
));
110 /* System calls for use by the bootstrap routine.
111 These are defined here since the usual calls may be dynamically linked. */
113 int syscall (int sysno
, ...) asm ("init_syscall");
114 asm ("init_syscall:\n"
118 " sethi %hi(_errno), %g1\n"
119 " st %o0, [%g1 + %lo(_errno)]\n"
127 extern struct link_dynamic _DYNAMIC
;
132 void (*ldstart
) (int, int);
139 struct link_dynamic
*crt_dp
;
144 /* If not dynamically linked, do nothing. */
148 /* Map in the dynamic linker. */
149 so
= syscall (SYS_open
, "/usr/lib/ld.so", O_RDONLY
);
150 if (syscall (SYS_read
, so
, &soexec
, sizeof (soexec
)) != sizeof (soexec
)
151 || soexec
.a_magic
!= ZMAGIC
)
153 static const char emsg
[] = "crt0: no /usr/lib/ld.so\n";
155 syscall (SYS_write
, 2, emsg
, sizeof (emsg
) - 1);
156 syscall (SYS_exit
, 127);
158 somap
= (caddr_t
) syscall (SYS_mmap
, 0,
159 soexec
.a_text
+ soexec
.a_data
+ soexec
.a_bss
,
160 PROT_READ
| PROT_EXEC
, _MAP_NEW
| MAP_PRIVATE
,
162 sodmap
= (caddr_t
) syscall (SYS_mmap
, somap
+ soexec
.a_text
, soexec
.a_data
,
163 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
164 _MAP_NEW
| MAP_FIXED
| MAP_PRIVATE
,
166 zf
= syscall (SYS_open
, "/dev/zero", O_RDONLY
);
167 if (soexec
.a_bss
!= 0)
168 sobssmap
= (caddr_t
) syscall (SYS_mmap
,
169 somap
+ soexec
.a_text
+ soexec
.a_data
,
171 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
172 _MAP_NEW
| MAP_FIXED
| MAP_PRIVATE
,
175 /* Call the entry point of the dynamic linker. */
176 soarg
.crt_ba
= somap
;
179 soarg
.crt_dp
= &_DYNAMIC
;
180 soarg
.crt_ep
= __environ
;
181 soarg
.crt_bp
= (caddr_t
) &&retaddr
;
183 ldstart
= (__typeof (ldstart
)) (somap
+ soexec
.a_entry
);
184 (*ldstart
) (1, (char *) &soarg
- (char *) sp
);