446 lines · 9.8 KB · Text
RawDownload
1i#define	WANT_M.g/"edf.h"/d,s/->ref =/->ref.ref =/g,s/ref(p->dot)/ref(\&p->dot->ref)/g,s/ref(p->fgrp)/ref(\&p->fgrp->ref)/g,s/ref(p->pgrp)/ref(\&p->pgrp->ref)/g,s/ref(p->egrp)/ref(\&p->egrp->ref)/g,s/lock(img)/lock(\&img->ref.lk)/g,s/ref(img)/ref(\&img->ref)/g,s/return0(void\*)/return0(void *v)/g,s/(s = up->seg\[i\])/(&)/g,s;MACHP(0)->ticks;msec();g/ESEG.*= newseg/a	flushmmu();	// Needed for Plan 9 VX.,s;sleep(\&phore;sleep(\&phore.rendez;g,s;lock(\&s->sema);lock(\&s->sema.rendez.lk);g,s;wakeup(p);wakeup(\&p->rendez);g,s;lock(up->rgrp);lock(\&up->rgrp->ref.lk);g,s;ref(up->rgrp);ref(\&up->rgrp->ref);g/sysr1/ s/(ulong\*)/(uint32 *x)//Admitted/,/	yield/c		yield();./^	checkpagerefs/ c	vx32sysr1();./^sysrfork/ s/ulong/uint32//^l2be/ s/long/uint32/-1 s/ulong/uint32//^sysexec/ s/ulong/uint32/-1istatic char Echanged[] = "exec arguments changed underfoot"; ./^{/+1;/^}/-1 c	char *volatile elem, *volatile file, *ufile;	Chan *volatile tc; 	/*	 * Open the file, remembering the final element and the full name.	 */	file = nil;	elem = nil;	tc = nil;	if(waserror()){		if(file)			free(file);		if(elem)			free(elem);		if(tc)			cclose(tc);		nexterror();	} 	ufile = uvalidaddr(arg[0], 1, 0);	file = validnamedup(ufile, 1);	tc = namec(file, Aopen, OEXEC, 0);	kstrdup((char**)&elem, up->genbuf); 	/*	 * Read the header.  If it's a #!, fill in progarg[] with info and repeat.	 */	int i, n, nprogarg;	char *progarg[sizeof(Exec)/2+1];	char *prog, *p;	char line[sizeof(Exec)+1];	Exec exec; 	nprogarg = 0;	n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);	if(n < 2)		error(Ebadexec);	p = (char*)&exec;	if(p[0] == '#' && p[1] == '!'){		memmove(line, p, n);		nprogarg = shargs(line, n, progarg);		if(nprogarg == 0)			error(Ebadexec);				/* The original file becomes an extra arg after #! line */		progarg[nprogarg++] = file;				/*		 * Take the #! $0 as a file to open, and replace		 * $0 with the original path's name.		 */		prog = progarg[0];		progarg[0] = elem;		cclose(tc);		tc = nil;	/* in case namec errors out */		tc = namec(prog, Aopen, OEXEC, 0);		n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);		if(n < 2)			error(Ebadexec);	} 	/* 	 * #! has had its chance, now we need a real binary	 */	uint32 magic, entry, text, etext, data, edata, bss, ebss; 	magic = l2be(exec.magic);	if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)		error(Ebadexec); 	entry = l2be(exec.entry);	text = l2be(exec.text);	data = l2be(exec.data);	bss = l2be(exec.bss);	etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);	edata = ROUND(etext + data, BY2PG);	ebss = ROUND(etext + data + bss, BY2PG);	//iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);//iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss); 	if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)		error(Ebadexec);		/* many overflow possibilities */	if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP	|| etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP	|| etext >= USTKTOP || edata < etext || ebss < edata)		error(Ebadexec); 	/*	 * Copy argv into new stack segment temporarily mapped elsewhere.	 * Be careful: multithreaded program could be changing argv during this.	 * Pass 1: count number of arguments, string bytes.	 */	int nargv, strbytes;	uint32 argp, ssize, spage; 	strbytes = 0;	for(i=0; i<nprogarg; i++)		strbytes += strlen(progarg[i]) + 1; 	argp = arg[1];	for(nargv=0;; nargv++, argp += BY2WD){		uint32 a;		char *str; 		a = *(uint32*)uvalidaddr(argp, BY2WD, 0);		if(a == 0)			break;		str = uvalidaddr(a, 1, 0);		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;		if(nprogarg > 0 && nargv == 0)			continue;	/* going to skip argv[0] on #! */		strbytes += n;	}	if(nargv == 0)		error("exec missing argv"); 	/* 	 * Skip over argv[0] if using #!.  Waited until now so that	 * string would still be checked for validity during loop.	 */	if(nprogarg > 0){		nargv--;		arg[1] += BY2WD;	} 	ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos); 	/*	 * 8-byte align SP for those (e.g. sparc) that need it.	 * execregs() will subtract another 4 bytes for argc.	 */	if((ssize+4) & 7)		ssize += 4;	spage = (ssize+(BY2PG-1)) >> PGSHIFT; 	/*	 * Pass 2: build the stack segment, being careful not to assume	 * that the counts from pass 1 are still valid.	 */	if(spage > TSTKSIZ)		error(Enovmem); 	qlock(&up->seglock);	if(waserror()){		if(up->seg[ESEG]){			putseg(up->seg[ESEG]);			up->seg[ESEG] = nil;		}		qunlock(&up->seglock);		nexterror();	}	up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);	flushmmu();	// Needed for Plan 9 VX  XXX really? 	/*	 * Top-of-stack structure.	 */	uchar *uzero;	uzero = up->pmmu.uzero;	Tos *tos;	uint32 utos;	utos = USTKTOP - sizeof(Tos);	tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);	tos->cyclefreq = m->cyclefreq;	cycles((uvlong*)&tos->pcycles);	tos->pcycles = -tos->pcycles;	tos->kcycles = tos->pcycles;	tos->clock = 0; 	/*	 * Argument pointers and strings, together.	 */	char *bp, *ep;	uint32 *targp;	uint32 ustrp, uargp; 	ustrp = utos - ROUND(strbytes, BY2WD);	uargp = ustrp - BY2WD*((nprogarg+nargv)+1);	bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);	ep = bp + strbytes;	p = bp;	targp = (uint32*)(uzero + uargp + TSTKTOP - USTKTOP);		/* #! args are trusted */	for(i=0; i<nprogarg; i++){		n = strlen(progarg[i]) + 1;		if(n  > ep - p)			error(Echanged);		memmove(p, progarg[i], n);		p += n;		*targp++ = ustrp;		ustrp += n;	}		/* the rest are not */	argp = arg[1];	for(i=0; i<nargv; i++){		uint32 a;		char *str;				a = *(uint32*)uvalidaddr(argp, BY2WD, 0);		argp += BY2WD;				str = uvalidaddr(a, 1, 0);		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;		if(n  > ep - p)			error(Echanged);		memmove(p, str, n);		p += n;		*targp++ = ustrp;		ustrp += n;	} 	if(*(uint32*)uvalidaddr(argp, BY2WD, 0) != 0)		error(Echanged);		*targp = 0; 	/*	 * But wait, there's more: prepare an arg copy for up->args	 * using the copy we just made in the temporary segment.	 */	char *args;	int nargs; 	n = p - bp;	/* includes NUL on last arg, so must be > 0 */	if(n <= 0)	/* nprogarg+nargv > 0; checked above */		error(Egreg);	if(n > 128)		n = 128;	args = smalloc(n);	if(waserror()){		free(args);		nexterror();	}	memmove(args, bp, n);	/* find beginning of UTF character boundary to place final NUL */	while(n > 0 && (args[n-1]&0xC0) == 0x80)		n--;	args[n-1] = '\0';	nargs = n; 	/*	 * Now we're ready to commit.	 */	free(up->text);	up->text = elem;	free(up->args);	up->args = args;	up->nargs = n;	elem = nil;	poperror();	/* args */ 	/*	 * Free old memory.  Special segments maintained across exec.	 */	Segment *s;	for(i = SSEG; i <= BSEG; i++) {		putseg(up->seg[i]);		up->seg[i] = nil;	/* in case of error */	}	for(i = BSEG+1; i< NSEG; i++) {		s = up->seg[i];		if(s && (s->type&SG_CEXEC)) {			putseg(s);			up->seg[i] = nil;		}	}		/*	 * Close on exec	 */	Fgrp *f;	f = up->fgrp;	for(i=0; i<=f->maxfd; i++)		fdclose(i, CCEXEC); 	/* Text.  Shared. Attaches to cache image if possible */	/* attachimage returns a locked cache image */	Image *img;	Segment *ts;	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);	ts = img->s;	up->seg[TSEG] = ts;	ts->flushme = 1;	ts->fstart = 0;	ts->flen = sizeof(Exec)+text;	unlock(&img->ref.lk); 	/* Data. Shared. */	s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);	up->seg[DSEG] = s; 	/* Attached by hand */	incref(&img->ref);	s->image = img;	s->fstart = ts->fstart+ts->flen;	s->flen = data; 	/* BSS. Zero fill on demand */	up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT); 	/*	 * Move the stack	 */	s = up->seg[ESEG];	up->seg[ESEG] = 0;	up->seg[SSEG] = s;	qunlock(&up->seglock);	poperror();	/* seglock */ 	s->base = USTKTOP-USTKSIZE;	s->top = USTKTOP;	relocateseg(s, USTKTOP-TSTKTOP); 	/*	 *  '/' processes are higher priority (hack to make /ip more responsive).	 */	if(devtab[tc->type]->dc == L'/')		up->basepri = PriRoot;	up->priority = up->basepri;	poperror();	/* tc, elem, file */	cclose(tc);	free(file);	// elem is now up->text 	/*	 *  At this point, the mmu contains info about the old address	 *  space and needs to be flushed	 */	flushmmu();	qlock(&up->debug);	up->nnote = 0;	up->notify = 0;	up->notified = 0;	up->privatemem = 0;	procsetup(up);	qunlock(&up->debug);	if(up->hang)		up->procctl = Proc_stopme; 	return execregs(entry, USTKTOP - uargp, nprogarg+nargv);./^syssleep/s/ulong/uint32//^sysalarm/s/ulong/uint32//^sysexits/s/ulong/uint32//status/;/if(status)/ c	char *status;	char *inval = "invalid exit string";	char buf[ERRMAX]; 	if(arg[0]){./validaddr/c			status = uvalidaddr(arg[0], 1, 0);./^	}/ c	}else		status = nil;./^sys_wait/s/ulong/uint32//validaddr(arg\[0\], sizeof(OWaitmsg), 1)/ c	ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);./ow =/d/^sysawait/s/ulong/uint32//ulong n/ s/ulong/uint32/a	char *buf;./validaddr/ s/v/buf = uv//i = / s/(char\*)arg\[0\]/buf//^generrstr/ s/char \*buf/uint32 addr//^$/i	char *buf;./validaddr/ s/v/buf = uv/s/(ulong)buf/addr//^syserrstr/s/ulong/uint32//return/s/(char\*)///^sys_errstr/s/ulong/uint32//return/s/(char\*)///^sysnotify/s/ulong/uint32//validaddr/;/up->notify/c		uvalidaddr(arg[0], 1, 0);	up->notify = arg[0];	/* checked again when used */./^sysnoted/s/ulong/uint32//^syssegbrk/s/ulong/uint32//addr/s/ulong/uint32//^syssegattach/s/ulong/uint32//return/s/(char\*)arg\[1\]/uvalidaddr(arg[1], 1, 0)//^syssegdetach/s/ulong/uint32//addr/s/ulong/uint32//^syssegfree/s/ulong/uint32//from/s/ulong/uint32//^sysbrk_/s/ulong/uint32//^sysrendezvous/s/ulong/uint32//^syssemacquire/s/ulong/uint32//validaddr/ s/v/addr = uv//addr =/d/(ulong)addr/s/(ulong)addr/arg[0]//^syssemrelease/s/ulong/uint32//validaddr/ s/v/addr = uv//addr =/d/(ulong)addr/s/(ulong)addr/arg[0]/