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