2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sparc / start.c
bloba664189bb40921a1ba8ae80199587e0555895db5
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
24 exception.
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
34 02111-1307 USA. */
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <fcntl.h>
41 #ifndef NO_SHLIB
42 #include <sys/exec.h>
43 #include <sys/types.h>
44 #include <sys/mman.h>
45 #include <link.h>
46 #include <syscall.h>
47 #endif
49 #if !defined (__GNUC__) || __GNUC__ < 2
50 #error This file uses GNU C extensions; you must compile with GCC version 2.
51 #endif
53 /* The first piece of initialized data. */
54 int __data_start = 0;
55 #ifdef HAVE_WEAK_SYMBOLS
56 weak_alias (__data_start, data_start)
57 #endif
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");
64 #ifndef NO_SHLIB
65 static void init_shlib (void) __THROW;
66 #endif
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");
73 #endif
75 void
76 _start (void)
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. */
81 register int argc;
82 register char **argv, **envp;
84 /* Unwind the frame built when we entered the function. */
85 asm("restore");
87 /* And clear the frame pointer. */
88 fp = 0;
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];
95 __environ = envp;
97 #ifndef NO_SHLIB
98 init_shlib ();
99 #endif
101 /* Allocate 24 bytes of stack space for the register save area. */
102 sp -= 24;
103 __libc_init (argc, argv, envp);
105 exit (main (argc, argv, envp));
108 #ifndef NO_SHLIB
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"
115 " clr %g1\n"
116 " ta 0\n"
117 " bcc 1f\n"
118 " sethi %hi(_errno), %g1\n"
119 " st %o0, [%g1 + %lo(_errno)]\n"
120 " sub %g0, 1, %o0\n"
121 "1:retl\n"
122 " nop");
124 static void
125 init_shlib ()
127 extern struct link_dynamic _DYNAMIC;
128 int so, zf;
129 caddr_t somap;
130 caddr_t sodmap;
131 caddr_t sobssmap;
132 void (*ldstart) (int, int);
133 struct exec soexec;
134 struct
136 caddr_t crt_ba;
137 int crt_dzfd;
138 int crt_ldfd;
139 struct link_dynamic *crt_dp;
140 char **crt_ep;
141 caddr_t crt_bp;
142 } soarg;
144 /* If not dynamically linked, do nothing. */
145 if (&_DYNAMIC == 0)
146 return;
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,
161 so, 0);
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,
165 so, soexec.a_text);
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,
170 soexec.a_bss,
171 PROT_READ | PROT_WRITE | PROT_EXEC,
172 _MAP_NEW | MAP_FIXED | MAP_PRIVATE,
173 zf, 0);
175 /* Call the entry point of the dynamic linker. */
176 soarg.crt_ba = somap;
177 soarg.crt_dzfd = zf;
178 soarg.crt_ldfd = so;
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);
186 retaddr:
189 #endif