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);