Back to index

glibc  2.9
start.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991,92,93,94,95,96,97,2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    In addition to the permissions in the GNU Lesser General Public
00010    License, the Free Software Foundation gives you unlimited
00011    permission to link the compiled version of this file with other
00012    programs, and to distribute those programs without any restriction
00013    coming from the use of this file. (The GNU Lesser General Public
00014    License restrictions do apply in other respects; for example, they
00015    cover modification of the file, and distribution when not linked
00016    into another program.)
00017 
00018    Note that people who make modified versions of this file are not
00019    obligated to grant this special exception for their modified
00020    versions; it is their choice whether to do so. The GNU Lesser
00021    General Public License gives permission to release a modified
00022    version without this exception; this exception also makes it
00023    possible to release a modified version which carries forward this
00024    exception.
00025 
00026    The GNU C Library is distributed in the hope that it will be useful,
00027    but WITHOUT ANY WARRANTY; without even the implied warranty of
00028    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00029    Lesser General Public License for more details.
00030 
00031    You should have received a copy of the GNU Lesser General Public
00032    License along with the GNU C Library; if not, write to the Free
00033    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00034    02111-1307 USA.  */
00035 
00036 #include <errno.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039 #include <fcntl.h>
00040 
00041 #ifndef NO_SHLIB
00042 #include <sys/exec.h>
00043 #include <sys/types.h>
00044 #include <sys/mman.h>
00045 #include <link.h>
00046 #include <syscall.h>
00047 #endif
00048 
00049 #if !defined (__GNUC__) || __GNUC__ < 2
00050   #error This file uses GNU C extensions; you must compile with GCC version 2.
00051 #endif
00052 
00053 /* The first piece of initialized data.  */
00054 int __data_start = 0;
00055 #ifdef HAVE_WEAK_SYMBOLS
00056 weak_alias (__data_start, data_start)
00057 #endif
00058 
00059 extern void __libc_init (int argc, char **argv, char **envp) __THROW;
00060 extern int main (int argc, char **argv, char **envp) __THROW;
00061 
00062 register long int sp asm("%sp"), fp asm("%fp");
00063 
00064 #ifndef NO_SHLIB
00065 static void init_shlib (void) __THROW;
00066 #endif
00067 
00068 #ifndef NO_EXPLICIT_START
00069 /* Declare _start with an explicit assembly symbol name of `start'
00070    (note no leading underscore).  This is the name Sun's crt0.o uses,
00071    and programs are often linked with `ld -e start'.  */
00072 void _start (void) asm ("start");
00073 #endif
00074 
00075 void
00076 _start (void)
00077 {
00078   /* It is important that these be declared `register'.
00079      Otherwise, when compiled without optimization, they are put on the
00080      stack, which loses completely after we zero the FP.  */
00081   register int argc;
00082   register char **argv, **envp;
00083 
00084   /* Unwind the frame built when we entered the function.  */
00085   asm("restore");
00086 
00087   /* And clear the frame pointer.  */
00088   fp = 0;
00089 
00090   /* The argument info starts after one register
00091      window (64 bytes) past the SP.  */
00092   argc = ((int *) sp)[16];
00093   argv = (char **) &((int *) sp)[17];
00094   envp = &argv[argc + 1];
00095   __environ = envp;
00096 
00097 #ifndef NO_SHLIB
00098   init_shlib ();
00099 #endif
00100 
00101   /* Allocate 24 bytes of stack space for the register save area.  */
00102   sp -= 24;
00103   __libc_init (argc, argv, envp);
00104 
00105   exit (main (argc, argv, envp));
00106 }
00107 
00108 #ifndef NO_SHLIB
00109 
00110 /* System calls for use by the bootstrap routine.
00111    These are defined here since the usual calls may be dynamically linked.  */
00112 
00113 int syscall (int sysno, ...) asm ("init_syscall");
00114 asm ("init_syscall:\n"
00115      " clr %g1\n"
00116      " ta 0\n"
00117      " bcc 1f\n"
00118      " sethi %hi(_errno), %g1\n"
00119      " st %o0, [%g1 + %lo(_errno)]\n"
00120      " sub %g0, 1, %o0\n"
00121      "1:retl\n"
00122      " nop");
00123 
00124 static void
00125 init_shlib ()
00126 {
00127   extern struct link_dynamic _DYNAMIC;
00128   int so, zf;
00129   caddr_t somap;
00130   caddr_t sodmap;
00131   caddr_t sobssmap;
00132   void (*ldstart) (int, int);
00133   struct exec soexec;
00134   struct
00135     {
00136       caddr_t crt_ba;
00137       int crt_dzfd;
00138       int crt_ldfd;
00139       struct link_dynamic *crt_dp;
00140       char **crt_ep;
00141       caddr_t crt_bp;
00142     } soarg;
00143 
00144   /* If not dynamically linked, do nothing.  */
00145   if (&_DYNAMIC == 0)
00146     return;
00147 
00148   /* Map in the dynamic linker.  */
00149   so = syscall (SYS_open, "/usr/lib/ld.so", O_RDONLY);
00150   if (syscall (SYS_read, so, &soexec, sizeof (soexec)) != sizeof (soexec)
00151       || soexec.a_magic != ZMAGIC)
00152     {
00153       static const char emsg[] = "crt0: no /usr/lib/ld.so\n";
00154 
00155       syscall (SYS_write, 2, emsg, sizeof (emsg) - 1);
00156       syscall (SYS_exit, 127);
00157     }
00158   somap = (caddr_t) syscall (SYS_mmap, 0,
00159                           soexec.a_text + soexec.a_data + soexec.a_bss,
00160                           PROT_READ | PROT_EXEC, _MAP_NEW | MAP_PRIVATE,
00161                           so, 0);
00162   sodmap = (caddr_t) syscall (SYS_mmap, somap + soexec.a_text, soexec.a_data,
00163                            PROT_READ | PROT_WRITE | PROT_EXEC,
00164                            _MAP_NEW | MAP_FIXED | MAP_PRIVATE,
00165                            so, soexec.a_text);
00166   zf = syscall (SYS_open, "/dev/zero", O_RDONLY);
00167   if (soexec.a_bss != 0)
00168     sobssmap = (caddr_t) syscall (SYS_mmap,
00169                               somap + soexec.a_text + soexec.a_data,
00170                               soexec.a_bss,
00171                               PROT_READ | PROT_WRITE | PROT_EXEC,
00172                               _MAP_NEW | MAP_FIXED | MAP_PRIVATE,
00173                               zf, 0);
00174 
00175   /* Call the entry point of the dynamic linker.  */
00176   soarg.crt_ba = somap;
00177   soarg.crt_dzfd = zf;
00178   soarg.crt_ldfd = so;
00179   soarg.crt_dp = &_DYNAMIC;
00180   soarg.crt_ep = __environ;
00181   soarg.crt_bp = (caddr_t) &&retaddr;
00182 
00183   ldstart = (__typeof (ldstart)) (somap + soexec.a_entry);
00184   (*ldstart) (1, (char *) &soarg - (char *) sp);
00185 
00186  retaddr:
00187 }
00188 
00189 #endif