1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)crt0.c 5.4 (Berkeley) 01/18/88"; 9 #endif LIBC_SCCS and not lint 10 11 /* 12 * C start up routine. 13 * Robert Henry, UCB, 20 Oct 81 14 * 15 * We make the following (true) assumptions: 16 * 1) when the kernel calls start, it does a jump to location 2, 17 * and thus avoids the register save mask. We are NOT called 18 * with a calls! see sys1.c:setregs(). 19 * 2) The only register variable that we can trust is sp, 20 * which points to the base of the kernel calling frame. 21 * Do NOT believe the documentation in exec(2) regarding the 22 * values of fp and ap. 23 * 3) We can allocate as many register variables as we want, 24 * and don't have to save them for anybody. 25 * 4) Because of the ways that asm's work, we can't have 26 * any automatic variables allocated on the stack, because 27 * we must catch the value of sp before any automatics are 28 * allocated. 29 */ 30 31 char **environ = (char **)0; 32 static int fd; 33 34 asm("#define _start start"); 35 asm("#define _eprol eprol"); 36 extern unsigned char etext; 37 extern unsigned char eprol; 38 start() 39 { 40 struct kframe { 41 int kargc; 42 char *kargv[1]; /* size depends on kargc */ 43 char kargstr[1]; /* size varies */ 44 char kenvstr[1]; /* size varies */ 45 }; 46 /* 47 * ALL REGISTER VARIABLES!!! 48 */ 49 register int r11; /* needed for init */ 50 register struct kframe *kfp; /* r10 */ 51 register char **targv; 52 register char **argv; 53 extern int errno; 54 55 #ifdef lint 56 kfp = 0; 57 initcode = initcode = 0; 58 #else not lint 59 asm(" movl sp,r10"); /* catch it quick */ 60 #endif not lint 61 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 62 /* void */ ; 63 if (targv >= (char **)(*argv)) 64 --targv; 65 environ = targv; 66 asm("eprol:"); 67 68 #ifdef paranoid 69 /* 70 * The standard I/O library assumes that file descriptors 0, 1, and 2 71 * are open. If one of these descriptors is closed prior to the start 72 * of the process, I/O gets very confused. To avoid this problem, we 73 * insure that the first three file descriptors are open before calling 74 * main(). Normally this is undefined, as it adds two unnecessary 75 * system calls. 76 */ 77 do { 78 fd = open("/dev/null", 2); 79 } while (fd >= 0 && fd < 3); 80 close(fd); 81 #endif paranoid 82 83 #ifdef MCRT0 84 monstartup(&eprol, &etext); 85 #endif MCRT0 86 errno = 0; 87 exit(main(kfp->kargc, argv, environ)); 88 } 89 asm("#undef _start"); 90 asm("#undef _eprol"); 91 92 #ifdef MCRT0 93 /*ARGSUSED*/ 94 exit(code) 95 register int code; /* r11 */ 96 { 97 monitor(0); 98 _cleanup(); 99 _exit(code); 100 } 101 #endif MCRT0 102 103 #ifdef CRT0 104 /* 105 * null mcount and moncontrol, 106 * just in case some routine is compiled for profiling 107 */ 108 moncontrol(val) 109 int val; 110 { 111 112 } 113 asm(" .globl mcount"); 114 asm("mcount: rsb"); 115 #endif CRT0 116