147884Sbostic /*- 247884Sbostic * Copyright (c) 1982 The Regents of the University of California. 347884Sbostic * All rights reserved. 447884Sbostic * 547884Sbostic * %sccs.include.proprietary.c% 621414Sdist */ 75102Smckusick 826668Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*48971Sdonn static char sccsid[] = "@(#)crt0.c 5.6 (Berkeley) 05/03/91"; 1047884Sbostic #endif /* LIBC_SCCS and not lint */ 1121414Sdist 125102Smckusick /* 135102Smckusick * C start up routine. 145102Smckusick * Robert Henry, UCB, 20 Oct 81 155102Smckusick * 165102Smckusick * We make the following (true) assumptions: 175102Smckusick * 1) when the kernel calls start, it does a jump to location 2, 185102Smckusick * and thus avoids the register save mask. We are NOT called 195102Smckusick * with a calls! see sys1.c:setregs(). 205102Smckusick * 2) The only register variable that we can trust is sp, 215102Smckusick * which points to the base of the kernel calling frame. 225102Smckusick * Do NOT believe the documentation in exec(2) regarding the 235102Smckusick * values of fp and ap. 245102Smckusick * 3) We can allocate as many register variables as we want, 255102Smckusick * and don't have to save them for anybody. 265102Smckusick * 4) Because of the ways that asm's work, we can't have 275102Smckusick * any automatic variables allocated on the stack, because 285102Smckusick * we must catch the value of sp before any automatics are 295102Smckusick * allocated. 305102Smckusick */ 315102Smckusick 329438Smckusick char **environ = (char **)0; 3325247Smckusick static int fd; 345102Smckusick 359438Smckusick extern unsigned char etext; 36*48971Sdonn extern unsigned char eprol asm ("eprol"); 37*48971Sdonn extern start() asm("start"); 38*48971Sdonn 39*48971Sdonn /* 40*48971Sdonn * Two kluges: store sp at entry in environ, and 41*48971Sdonn * install 16 bits of 0 at location 0 (a zero register save mask). 42*48971Sdonn * These two hacks remove limits on the use of local 43*48971Sdonn * and register variables in start(). 44*48971Sdonn */ 45*48971Sdonn asm(".text; .word 0; movl sp,_environ; jbr start+2"); 46*48971Sdonn 475102Smckusick start() 485102Smckusick { 495102Smckusick struct kframe { 505102Smckusick int kargc; 515102Smckusick char *kargv[1]; /* size depends on kargc */ 525102Smckusick char kargstr[1]; /* size varies */ 535102Smckusick char kenvstr[1]; /* size varies */ 545102Smckusick }; 55*48971Sdonn register struct kframe *kfp; 565102Smckusick register char **targv; 575102Smckusick register char **argv; 5825247Smckusick extern int errno; 595102Smckusick 605102Smckusick #ifdef lint 615102Smckusick kfp = 0; 629438Smckusick initcode = initcode = 0; 635102Smckusick #else not lint 64*48971Sdonn kfp = (struct kframe *) environ; 655102Smckusick #endif not lint 665102Smckusick for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 675102Smckusick /* void */ ; 685102Smckusick if (targv >= (char **)(*argv)) 695102Smckusick --targv; 705102Smckusick environ = targv; 719438Smckusick asm("eprol:"); 7225247Smckusick 7325247Smckusick #ifdef paranoid 7425247Smckusick /* 7525247Smckusick * The standard I/O library assumes that file descriptors 0, 1, and 2 7625247Smckusick * are open. If one of these descriptors is closed prior to the start 7725247Smckusick * of the process, I/O gets very confused. To avoid this problem, we 7825247Smckusick * insure that the first three file descriptors are open before calling 7925247Smckusick * main(). Normally this is undefined, as it adds two unnecessary 8025247Smckusick * system calls. 8125247Smckusick */ 8225247Smckusick do { 8325247Smckusick fd = open("/dev/null", 2); 8425247Smckusick } while (fd >= 0 && fd < 3); 8525247Smckusick close(fd); 8625247Smckusick #endif paranoid 8725247Smckusick 889438Smckusick #ifdef MCRT0 899438Smckusick monstartup(&eprol, &etext); 909438Smckusick #endif MCRT0 9125247Smckusick errno = 0; 925102Smckusick exit(main(kfp->kargc, argv, environ)); 935102Smckusick } 945102Smckusick 959438Smckusick #ifdef MCRT0 969438Smckusick /*ARGSUSED*/ 979438Smckusick exit(code) 98*48971Sdonn register int code; 999438Smckusick { 1009438Smckusick monitor(0); 1019438Smckusick _cleanup(); 10233363Smckusick _exit(code); 1039438Smckusick } 1049438Smckusick #endif MCRT0 1059438Smckusick 1069438Smckusick #ifdef CRT0 1075102Smckusick /* 10811795Speter * null mcount and moncontrol, 10911795Speter * just in case some routine is compiled for profiling 1105102Smckusick */ 11111795Speter moncontrol(val) 11211795Speter int val; 11311795Speter { 11411795Speter 11511795Speter } 116*48971Sdonn asm(".globl mcount"); 117*48971Sdonn asm("mcount: rsb"); 1189438Smckusick #endif CRT0 119