418 lines · 7.0 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include <bio.h>#include <mach.h>#include <ctype.h>#include "dat.h"#include "fns.h" #pragma pack ontypedef struct Tos Tos;struct Tos {	struct			/* Per process profiling */	{		ulong	pp;	/* known to be 0(ptr) */		ulong	next;	/* known to be 4(ptr) */		ulong	last;		ulong	first;		ulong	pid;		ulong	what;	} prof;	uvlong	cyclefreq;	/* cycle clock frequency if there is one, 0 otherwise */	vlong	kcycles;	/* cycles spent in kernel */	vlong	pcycles;	/* cycles spent in process (kernel + user) */	ulong	pid;		/* might as well put the pid here */	ulong	clock;	/* top of stack is here */};#pragma pack off Process plist;Lock plistlock; voidinitproc(void){	P = emallocz(sizeof(Process));	P->pid = getpid();	P->fd = newfd();	incref(&nproc);	plist.prev = P;	plist.next = P;	P->prev = &plist;	P->next = &plist;	if(vfp)		resetvfp();	else		resetfpa();} voidaddproc(Process *p){	lock(&plistlock);	p->prev = plist.prev;	p->next = &plist;	plist.prev->next = p;	plist.prev = p;	unlock(&plistlock);} voidremproc(Process *p){	lock(&plistlock);	p->prev->next = p->next;	p->next->prev = p->prev;	unlock(&plistlock);} Process *findproc(int pid){	Process *p; 	lock(&plistlock);	for(p = plist.next; p != &plist; p = p->next)		if(p->pid == pid)			break;	unlock(&plistlock);	if(p != &plist)		return p;	return nil;} static voidcopyname(char *file){	char *p;		p = strrchr(file, '/');	if(p == nil)		p = file;	else		p++;	strncpy(P->name, p, NAMEMAX); 	if(P->path != nil && decref(P->path) == 0)		free(P->path);	P->path = emallocz(sizeof(Ref) + strlen(file)+1);	incref(P->path);	strcpy((char*)(P->path + 1), file);} static voidinitstack(int argc, char **argv){	ulong tos, sp, ap, size, i, len;		tos = (mach->utop & ~7) - sizeof(Tos) * 2;	sp = tos;		size = 8;	for(i = 0; i < argc; i++)		size += strlen(argv[i]) + 5;		sp -= size;	sp &= ~7;	P->R[0] = tos;	P->R[1] = mach->utop - 4;	P->R[13] = sp;		*(ulong *) vaddrnol(sp, 4) = argc;	sp += 4;	ap = sp + (argc + 1) * 4;	for(i = 0; i < argc; i++) {		*(ulong *) vaddrnol(sp, 4) = ap;		sp += 4;		len = strlen(argv[i]) + 1;		memcpy(vaddrnol(ap, len), argv[i], len);		ap += len;	}	*(ulong *) vaddrnol(sp, 4) = 0;	inittos();} voidinittos(void){	ulong tos; 	tos = (mach->utop & ~7) - sizeof(Tos) * 2;	((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid;} static intloadscript(int fd, char *file, int argc, char **argv){	char buf[513], *p, **q, **nargv;	int rc, nargc, i;		seek(fd, 0, 0);	rc = readn(fd, buf, 512);	if(rc <= 0)		goto invalid;	close(fd);	buf[rc] = 0;	p = strchr(buf, '\n');	if(p == nil)		goto invalid;	*p = 0;	while(isspace(*--p))		*p = 0;	nargc = 0;	p = buf + 2;	while(*p) {		while(*p && isspace(*p))			p++;		nargc++;		while(*p && !isspace(*p))			p++;	}	if(nargc == 0)		goto invalid;	nargv = emallocz(sizeof(char *) * (nargc + argc));	q = nargv;	p = buf + 2;	while(*p) {		while(*p && isspace(*p))			p++;		*(p-1) = 0;		*q++ = p;		while(*p && !isspace(*p))			p++;	}	*q++ = file;	for(i = 1; i < argc; i++)		*q++ = argv[i];	rc = loadtext(*nargv, argc + nargc, nargv);	free(nargv);	return rc; invalid:	werrstr("exec header invalid");	return -1;} intloadtext(char *file, int argc, char **argv){	int fd;	Fhdr fp;	Segment *text, *data, *bss;	char buf[2];		fd = open(file, OREAD);	if(fd < 0) return -1;	if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')		return loadscript(fd, file, argc, argv);	seek(fd, 0, 0);	if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) {		werrstr("exec header invalid");		return -1;	}	copyname(file);	P->notehandler = P->innote = P->notein = P->noteout = 0;	freesegs();	memset(P->R, 0, sizeof(P->R));	P->CPSR = 0;	text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);	data = newseg(fp.dataddr, fp.datsz, SEGDATA);	bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);	newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);	seek(fd, fp.txtoff - fp.hdrsz, 0);	if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)		sysfatal("%r");	seek(fd, fp.datoff, 0);	if(readn(fd, data->data, fp.datsz) < fp.datsz)		sysfatal("%r");	memset(bss->data, 0, bss->size);	P->R[15] = fp.entry;	if(havesymbols && syminit(fd, &fp) < 0)		fprint(2, "initializing symbol table: %r\n");	close(fd);	fdclear(P->fd);	initstack(argc, argv);	if(vfp)		resetvfp();	else		resetfpa();	return 0;} voidcherrstr(char *str, ...){	va_list va;		va_start(va, str);	vsnprint(P->errbuf, ERRMAX, str, va);	va_end(va);} u32intnoteerr(u32int x, u32int y){	if(((int)x) >= ((int)y))		return x;	rerrstr(P->errbuf, ERRMAX);	return x;} Fd *newfd(void){	Fd *fd;		fd = emallocz(sizeof(*fd));	incref(fd);	return fd;} Fd *copyfd(Fd *old){	Fd *new;		rlock(old);	new = newfd();	if(old->nfds > 0) {		new->nfds = old->nfds;		new->fds = emalloc(old->nfds);		memcpy(new->fds, old->fds, old->nfds);	}	runlock(old);	return new;} voidfddecref(Fd *fd){	if(decref(fd) == 0) {		free(fd->fds);		free(fd);	}} intiscexec(Fd *fd, int n){	int r; 	r = 0;	rlock(fd);	if(n / 8 < fd->nfds)		r = (fd->fds[n / 8] & (1 << (n % 8))) != 0;	runlock(fd);	return r;} voidsetcexec(Fd *fd, int n, int status){	int old; 	wlock(fd);	if(n / 8 >= fd->nfds) {		if(status == 0) {			wunlock(fd);			return;		}		old = fd->nfds;		fd->nfds = (n / 8) + 1;		fd->fds = erealloc(fd->fds, fd->nfds);		memset(fd->fds + old, 0, fd->nfds - old);	}	if(status == 0)		fd->fds[n / 8] &= ~(1 << (n % 8));	else		fd->fds[n / 8] |= (1 << (n % 8));	wunlock(fd);} voidfdclear(Fd *fd){	int i, j, k; 	wlock(fd);	if(fd->nfds == 0) {		wunlock(fd);		return;	}	for(i = 0; i < fd->nfds; i++) {		j = fd->fds[i];		for(k = 0; k < 8; k++)			if(j & (1<<k))				close(8 * i + k);	}	free(fd->fds);	fd->nfds = 0;	fd->fds = nil;	wunlock(fd);} /* call this from a notehandler if you don't want the front to fall off */voidaddnote(char *msg){	int new;		new = P->notein + 1;	if((new - P->noteout) % NNOTE == 0)		return; 	strncpy(P->notes[P->notein % NNOTE], msg, ERRMAX - 1);	P->notein = new;} /* the following code is not for the weak of heart */voiddonote(char *msg, ulong type){	int rc;	u32int *ureg, *sp, uregp, msgp;	char *msgb; 	if(P->notehandler == 0)		exits(msg); 	clrex();	uregp = P->R[13] - 18 * 4;	ureg = vaddrnol(uregp, 18 * 4);	memcpy(ureg, P->R, 15 * 4);	ureg[15] = type;	ureg[16] = P->CPSR;	ureg[17] = P->R[15];	P->R[13] = uregp;	msgp = P->R[13] -= ERRMAX;	msgb = vaddrnol(msgp, ERRMAX);	strncpy(msgb, msg, ERRMAX);	P->R[13] -= 3 * 4;	sp = vaddrnol(P->R[13], 3 * 4);	sp[0] = 0;	sp[2] = msgp;	P->R[0] = uregp;	P->R[15] = P->notehandler;	P->innote = 1;	switch(rc = setjmp(P->notejmp) - 1) {	case -1:		for(;;) {			if(ultraverbose)				dump();			step();		}	case NDFLT:		exits(msg);	case NCONT:		break;	default:		sysfatal("unhandled noted argument %d", rc);	}	P->innote = 0;	ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */	memcpy(P->R, ureg, 15 * 4);	P->CPSR = ureg[16];	P->R[15] = ureg[17];}