141009Swilliam /*- 241009Swilliam * Copyright (c) 1990 The Regents of the University of California. 341009Swilliam * All rights reserved. 441009Swilliam * 541009Swilliam * This code is derived from software contributed to Berkeley by 641009Swilliam * William Jolitz. 741009Swilliam * 841009Swilliam * %sccs.include.redist.c% 941009Swilliam */ 1041009Swilliam 1141009Swilliam #ifndef lint 12*41918Swilliam static char sccsid[] = "@(#)crt0.c 5.2 (Berkeley) 05/14/90"; 1341009Swilliam #endif /* not lint */ 1441009Swilliam 1541009Swilliam /* 1641009Swilliam * C start up routine. 1741009Swilliam * Robert Henry, UCB, 20 Oct 81 1841009Swilliam * 19*41918Swilliam * We make the following (true) assumption: 20*41918Swilliam * 1) The only register variable that we can trust is ebp, 2141009Swilliam * which points to the base of the kernel calling frame. 2241009Swilliam */ 2341009Swilliam 2441009Swilliam char **environ = (char **)0; 2541009Swilliam static int fd; 2641009Swilliam 2741009Swilliam asm("#define _start start"); 2841009Swilliam asm("#define _eprol eprol"); 2941009Swilliam asm(" .text"); 30*41918Swilliam asm(" .long 0xc000c000"); 3141009Swilliam extern unsigned char etext; 3241009Swilliam extern unsigned char eprol; 3341009Swilliam start() 3441009Swilliam { 3541009Swilliam struct kframe { 3641009Swilliam int kargc; 3741009Swilliam char *kargv[1]; /* size depends on kargc */ 3841009Swilliam char kargstr[1]; /* size varies */ 3941009Swilliam char kenvstr[1]; /* size varies */ 4041009Swilliam }; 4141009Swilliam /* 4241009Swilliam * ALL REGISTER VARIABLES!!! 4341009Swilliam */ 4441009Swilliam register struct kframe *kfp; /* r10 */ 4541009Swilliam register char **targv; 4641009Swilliam register char **argv; 4741009Swilliam extern int errno; 4841009Swilliam 4941009Swilliam #ifdef lint 5041009Swilliam kfp = 0; 5141009Swilliam initcode = initcode = 0; 5241009Swilliam #else not lint 5341009Swilliam asm(" lea 4(%ebp),%ebx"); /* catch it quick */ 5441009Swilliam #endif not lint 5541009Swilliam for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 5641009Swilliam /* void */ ; 5741009Swilliam if (targv >= (char **)(*argv)) 5841009Swilliam --targv; 5941009Swilliam environ = targv; 6041009Swilliam asm("eprol:"); 6141009Swilliam 6241009Swilliam #ifdef paranoid 6341009Swilliam /* 6441009Swilliam * The standard I/O library assumes that file descriptors 0, 1, and 2 6541009Swilliam * are open. If one of these descriptors is closed prior to the start 6641009Swilliam * of the process, I/O gets very confused. To avoid this problem, we 6741009Swilliam * insure that the first three file descriptors are open before calling 6841009Swilliam * main(). Normally this is undefined, as it adds two unnecessary 6941009Swilliam * system calls. 7041009Swilliam */ 7141009Swilliam do { 7241009Swilliam fd = open("/dev/null", 2); 7341009Swilliam } while (fd >= 0 && fd < 3); 7441009Swilliam close(fd); 7541009Swilliam #endif paranoid 7641009Swilliam 7741009Swilliam #ifdef MCRT0 7841009Swilliam monstartup(&eprol, &etext); 7941009Swilliam #endif MCRT0 8041009Swilliam errno = 0; 8141009Swilliam exit(main(kfp->kargc, argv, environ)); 8241009Swilliam } 8341009Swilliam asm("#undef _start"); 8441009Swilliam asm("#undef _eprol"); 8541009Swilliam 8641009Swilliam #ifdef MCRT0 8741009Swilliam /*ARGSUSED*/ 8841009Swilliam exit(code) 8941009Swilliam register int code; /* r11 */ 9041009Swilliam { 9141009Swilliam monitor(0); 9241009Swilliam _cleanup(); 9341009Swilliam asm(" pushl 8(bp)") ; 9441009Swilliam asm(" movl $1,%eax"); 9541009Swilliam asm(" .byte 0x9a; .long 0; .word 0"); 9641009Swilliam } 9741009Swilliam #endif MCRT0 9841009Swilliam 9941009Swilliam #ifdef CRT0 10041009Swilliam /* 10141009Swilliam * null mcount and moncontrol, 10241009Swilliam * just in case some routine is compiled for profiling 10341009Swilliam */ 10441009Swilliam moncontrol(val) 10541009Swilliam int val; 10641009Swilliam { 10741009Swilliam 10841009Swilliam } 10941009Swilliam asm(" .globl mcount"); 11041009Swilliam asm("mcount: ret"); 11141009Swilliam #endif CRT0 112