Remove __environ definition.
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sparc / start.c
1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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.  */
18
19 #include <ansidecl.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24
25 #ifndef NO_SHLIB
26 #include <sys/exec.h>
27 #include <sys/types.h>
28 #include <sys/mman.h>
29 #include <link.h>
30 #include <syscall.h>
31 #endif
32
33 #if !defined (__GNUC__) || __GNUC__ < 2
34   #error This file uses GNU C extensions; you must compile with GCC version 2.
35 #endif
36
37 /* The first piece of initialized data.  */
38 int __data_start = 0;
39 #ifdef HAVE_WEAK_SYMBOLS
40 weak_alias (__data_start, data_start)
41 #endif
42
43 VOLATILE int errno;
44
45 extern void EXFUN(__libc_init, (int argc, char **argv, char **envp));
46 extern int EXFUN(main, (int argc, char **argv, char **envp));
47
48 register long int sp asm("%sp"), fp asm("%fp");
49
50 #ifndef NO_SHLIB
51 static void EXFUN(init_shlib, (NOARGS));
52 #endif
53
54 #ifndef NO_EXPLICIT_START
55 /* Declare _start with an explicit assembly symbol name of `start'
56    (note no leading underscore).  This is the name Sun's crt0.o uses,
57    and programs are often linked with `ld -e start'.  */
58 void _start (void) asm ("start");
59 #endif
60
61 void
62 _start (void)
63 {
64   /* It is important that these be declared `register'.
65      Otherwise, when compiled without optimization, they are put on the
66      stack, which loses completely after we zero the FP.  */
67   register int argc;
68   register char **argv, **envp;
69
70   /* Unwind the frame built when we entered the function.  */
71   asm("restore");
72
73   /* And clear the frame pointer.  */
74   fp = 0;
75
76   /* The argument info starts after one register
77      window (64 bytes) past the SP.  */
78   argc = ((int *) sp)[16];
79   argv = (char **) &((int *) sp)[17];
80   envp = &argv[argc + 1];
81   __environ = envp;
82
83 #ifndef NO_SHLIB
84   init_shlib ();
85 #endif
86
87   /* Allocate 24 bytes of stack space for the register save area.  */
88   sp -= 24;
89   __libc_init (argc, argv, envp);
90
91   exit (main (argc, argv, envp));
92 }
93 \f
94 #ifndef NO_SHLIB
95
96 /* System calls for use by the bootstrap routine.
97    These are defined here since the usual calls may be dynamically linked.  */
98
99 int syscall (int sysno, ...) asm ("init_syscall");
100 asm ("init_syscall:\n"
101      "  clr %g1\n"
102      "  ta 0\n"
103      "  bcc 1f\n"
104      "  sethi %hi(_errno), %g1\n"
105      "  st %o0, [%g1 + %lo(_errno)]\n"
106      "  sub %g0, 1, %o0\n"
107      "1:retl\n"
108      "  nop");
109
110 static void
111 DEFUN_VOID(init_shlib)
112 {
113   extern struct link_dynamic _DYNAMIC;
114   int so, zf;
115   caddr_t somap;
116   caddr_t sodmap;
117   caddr_t sobssmap;
118   void (*ldstart) (int, int);
119   struct exec soexec;
120   struct 
121     {
122       caddr_t crt_ba;
123       int crt_dzfd;
124       int crt_ldfd;
125       struct link_dynamic *crt_dp;
126       char **crt_ep;
127       caddr_t crt_bp;
128     } soarg;
129   
130   /* If not dynamically linked, do nothing.  */
131   if (&_DYNAMIC == 0)
132     return;
133
134   /* Map in the dynamic linker.  */
135   so = syscall (SYS_open, "/usr/lib/ld.so", O_RDONLY);
136   if (syscall (SYS_read, so, &soexec, sizeof (soexec)) != sizeof (soexec)
137       || soexec.a_magic != ZMAGIC)
138     {
139       static CONST char emsg[] = "crt0: no /usr/lib/ld.so\n";
140       
141       syscall (SYS_write, 2, emsg, sizeof (emsg) - 1);
142       syscall (SYS_exit, 127);
143     }
144   somap = (caddr_t) syscall (SYS_mmap, 0,
145                              soexec.a_text + soexec.a_data + soexec.a_bss,
146                              PROT_READ | PROT_EXEC, _MAP_NEW | MAP_PRIVATE,
147                              so, 0);
148   sodmap = (caddr_t) syscall (SYS_mmap, somap + soexec.a_text, soexec.a_data,
149                               PROT_READ | PROT_WRITE | PROT_EXEC,
150                               _MAP_NEW | MAP_FIXED | MAP_PRIVATE,
151                               so, soexec.a_text);
152   zf = syscall (SYS_open, "/dev/zero", O_RDONLY);
153   if (soexec.a_bss != 0)
154     sobssmap = (caddr_t) syscall (SYS_mmap,
155                                   somap + soexec.a_text + soexec.a_data,
156                                   soexec.a_bss,
157                                   PROT_READ | PROT_WRITE | PROT_EXEC,
158                                   _MAP_NEW | MAP_FIXED | MAP_PRIVATE,
159                                   zf, 0);
160
161   /* Call the entry point of the dynamic linker.  */
162   soarg.crt_ba = somap;
163   soarg.crt_dzfd = zf;
164   soarg.crt_ldfd = so;
165   soarg.crt_dp = &_DYNAMIC;
166   soarg.crt_ep = __environ;
167   soarg.crt_bp = (caddr_t) &&retaddr;
168   
169   ldstart = (__typeof (ldstart)) (somap + soexec.a_entry);
170   (*ldstart) (1, (char *) &soarg - (char *) sp);
171
172  retaddr:
173 }
174
175 #endif