Charles.Forsyth20060303644188019 years agoHistory
1510 lines · 25.8 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"#include	<interp.h>#include	<isa.h>#include	"runt.h" /* * Enable the heap device for environments that allow debugging => * Must be 1 for a production environment. */int	SECURE = 0; enum{	Qdir,	Qctl,	Qdbgctl,	Qheap,	Qns,	Qnsgrp,	Qpgrp,	Qstack,	Qstatus,	Qtext,	Qwait,	Qfd,	Qexception,}; /* * must be in same order as enum */Dirtab progdir[] ={	"ctl",		{Qctl},		0,			0200,	"dbgctl",	{Qdbgctl},	0,			0600,	"heap",		{Qheap},	0,			0600,	"ns",		{Qns},		0,			0400,	"nsgrp",	{Qnsgrp},	0,			0444,	"pgrp",		{Qpgrp},	0,			0444,	"stack",	{Qstack},	0,			0400,	"status",	{Qstatus},	0,			0444,	"text",		{Qtext},	0,			0000,	"wait",		{Qwait},	0,			0400,	"fd",		{Qfd},		0,			0400,	"exception",	{Qexception},	0,	0400,}; enum{	CMkill,	CMkillgrp,	CMrestricted,	CMexceptions,	CMprivate}; staticCmdtab progcmd[] = {	CMkill,	"kill",	1,	CMkillgrp,	"killgrp",	1,	CMrestricted, "restricted", 1,	CMexceptions, "exceptions", 2,	CMprivate, "private",	1,}; enum{	CDstep,	CDtoret,	CDcont,	CDstart,	CDstop,	CDunstop,	CDmaim,	CDbpt}; staticCmdtab progdbgcmd[] = {	CDstep,	"step",	0,	/* known below to be first, to cope with stepN */	CDtoret,	"toret",	1,	CDcont,	"cont",	1,	CDstart,	"start",	1,	CDstop,	"stop",	1,	CDunstop,	"unstop",	1,	CDmaim,	"maim",	1,	CDbpt,	"bpt",	4,}; typedef struct Heapqry Heapqry;struct Heapqry{	char	fmt;	ulong	addr;	ulong	module;	int	count;}; typedef struct Bpt	Bpt; struct Bpt{	Bpt	*next;	int	pc;	char	*file;	char	path[1];}; typedef struct Progctl Progctl;struct Progctl{	Rendez	r;	int	ref;	Proc	*debugger;	/* waiting for dbgxec */	char	*msg;		/* reply from dbgxec */	int	step;		/* instructions to try */	int	stop;		/* stop running the program */	Bpt*	bpts;		/* active breakpoints */	Queue*	q;		/* status queue */}; #define	QSHIFT		4		/* location in qid of pid */#define	QID(q)		(((ulong)(q).path&0x0000000F)>>0)#define QPID(pid)	(((pid)<<QSHIFT))#define	PID(q)		((q).vers)#define PATH(q)		((ulong)(q).path&~((1<<QSHIFT)-1)) static char *progstate[] =			/* must correspond to include/interp.h */{	"alt",				/* blocked in alt instruction */	"send",				/* waiting to send */	"recv",				/* waiting to recv */	"debug",			/* debugged */	"ready",			/* ready to be scheduled */	"release",			/* interpreter released */	"exiting",			/* exit because of kill or error */	"broken",			/* thread crashed */}; static	void	dbgstep(Progctl*, Prog*, int);static	void	dbgstart(Prog*);static	void	freebpts(Bpt*);static	Bpt*	delbpt(Bpt*, char*, int);static	Bpt*	setbpt(Bpt*, char*, int);static	void	mntscan(Mntwalk*, Pgrp*);extern	Type	*Trdchan;extern	Type	*Twrchan;extern	Module*	modules;static  char 	Emisalign[] = "misaligned address"; static intproggen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp){	Qid qid;	Prog *p;	char *e;	Osenv *o;	ulong pid, path, perm, len; 	if(s == DEVDOTDOT){		mkqid(&qid, Qdir, 0, QTDIR);		devdir(c, qid, "#p", 0, eve, DMDIR|0555, dp);		return 1;	} 	if((ulong)c->qid.path == Qdir) {		if(name != nil){			/* ignore s and use name to find pid */			pid = strtoul(name, &e, 0);			if(pid == 0 || *e != '\0')				return -1;			acquire();			p = progpid(pid);			if(p == nil){				release();				return -1;			}		}else{			acquire();			p = progn(s);			if(p == nil) {				release();				return -1;			}			pid = p->pid;		}		o = p->osenv;		sprint(up->genbuf, "%lud", pid);		if(name != nil && strcmp(name, up->genbuf) != 0){			release();			return -1;		}		mkqid(&qid, pid<<QSHIFT, pid, QTDIR);		devdir(c, qid, up->genbuf, 0, o->user, DMDIR|0555, dp);		release();		return 1;	} 	if(s >= nelem(progdir))		return -1;	tab = &progdir[s];	path = PATH(c->qid); 	acquire();	p = progpid(PID(c->qid));	if(p == nil) {		release();		return -1;	} 	o = p->osenv; 	perm = tab->perm;	if((perm & 7) == 0)		perm = (perm|(perm>>3)|(perm>>6)) & o->pgrp->progmode; 	len = tab->length;	mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);	devdir(c, qid, tab->name, len, o->user, perm, dp);	release();	return 1;} static Chan*progattach(char *spec){	return devattach('p', spec);} static Walkqid*progwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, 0, 0, proggen);} static intprogstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, 0, 0, proggen);} static Chan*progopen(Chan *c, int omode){	Prog *p;	Osenv *o;	Progctl *ctl;	int perm; 	if(c->qid.type & QTDIR)		return devopen(c, omode, 0, 0, proggen); 	acquire();	if (waserror()) {		release();		nexterror();	}	p = progpid(PID(c->qid));	if(p == nil)		error(Ethread); 	o = p->osenv;	perm = progdir[QID(c->qid)-1].perm;	if((perm & 7) == 0)		perm = (perm|(perm>>3)|(perm>>6)) & o->pgrp->progmode;	devpermcheck(o->user, perm, omode);	omode = openmode(omode); 	switch(QID(c->qid)){	default:		error(Egreg);	case Qnsgrp:	case Qpgrp:	case Qtext:	case Qstatus:	case Qstack:	case Qctl:	case Qfd:	case Qexception:		break;	case Qwait:		c->aux = qopen(1024, Qmsg, nil, nil);		if(c->aux == nil)			error(Enomem);		o->childq = c->aux;		break;	case Qns:		c->aux = malloc(sizeof(Mntwalk));		if(c->aux == nil)			error(Enomem);		break;	case Qheap:		if(SECURE || o->pgrp->privatemem || omode != ORDWR)			error(Eperm);		c->aux = malloc(sizeof(Heapqry));		if(c->aux == nil)			error(Enomem);		break;	case Qdbgctl:		if(SECURE || o->pgrp->privatemem || omode != ORDWR)			error(Eperm);		ctl = malloc(sizeof(Progctl));		if(ctl == nil)			error(Enomem);		ctl->q = qopen(1024, Qmsg, nil, nil);		if(ctl->q == nil) {			free(ctl);			error(Enomem);		}		ctl->bpts = nil;		ctl->ref = 1;		c->aux = ctl;		break;	}	if(p->state != Pexiting)		c->qid.vers = p->pid; 	poperror();	release();	c->offset = 0;	c->mode = omode;	c->flag |= COPEN;	return c;} static intprogwstat(Chan *c, uchar *db, int n){	Dir d;	Prog *p;	char *u;	Osenv *o; 	if(c->qid.type&QTDIR)		error(Eperm);	acquire();	p = progpid(PID(c->qid));	if(p == nil) {		release();		error(Ethread);	} 	u = up->env->user;	o = p->osenv;	if(strcmp(u, o->user) != 0 && strcmp(u, eve) != 0) {		release();		error(Eperm);	} 	n = convM2D(db, n, &d, nil);	if(n == 0){		release();		error(Eshortstat);	}	if(d.mode != ~0UL)		o->pgrp->progmode = d.mode&0777;	release();	return n;} static voidclosedbgctl(Progctl *ctl, Prog *p){	Osenv *o; 	if(ctl->ref-- > 1)		return;	freebpts(ctl->bpts);	if(p != nil){		o = p->osenv;		if(o->debug == ctl){			o->debug = nil;			p->xec = xec;		}	}	qfree(ctl->q);	free(ctl);} static voidprogclose(Chan *c){	int i;	Prog *f;	Osenv *o;	Progctl *ctl; 	switch(QID(c->qid)) {	case Qns:	case Qheap:		free(c->aux);		break;	case Qdbgctl:		if((c->flag & COPEN) == 0)			return;		ctl = c->aux;		acquire();		closedbgctl(ctl, progpid(PID(c->qid)));		release();		break;	case Qwait:		acquire();		i = 0;		for(;;) {			f = progn(i++);			if(f == nil)				break;			o = f->osenv;			if(o->waitq == c->aux)				o->waitq = nil;			if(o->childq == c->aux)				o->childq = nil;		}		release();		qfree(c->aux);	}} static intprogsize(Prog *p){	int size;	Frame *f;	uchar *fp;	Modlink *m; 	m = p->R.M;	size = 0;	if(m->MP != H)		size += hmsize(D2H(m->MP));	if(m->prog != nil)		size += msize(m->prog); 	fp = p->R.FP;	while(fp != nil) {		f = (Frame*)fp;		fp = f->fp;		if(f->mr != nil) {			if(f->mr->MP != H)				size += hmsize(D2H(f->mr->MP));			if(f->mr->prog != nil)				size += msize(f->mr->prog);		}		if(f->t == nil)			size += msize(SEXTYPE(f));	}	return size/1024;} static longprogoffset(long offset, char *va, int *np){	if(offset > 0) {		offset -= *np;		if(offset < 0) {			memmove(va, va+*np+offset, -offset);			*np = -offset;		}		else			*np = 0;	}	return offset;} static intprogqidwidth(Chan *c){	char buf[32]; 	return sprint(buf, "%lud", c->qid.vers);} intprogfdprint(Chan *c, int fd, int w, char *s, int ns){	int n; 	if(w == 0)		w = progqidwidth(c);	n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",		fd,		&"r w rw"[(c->mode&3)<<1],		devtab[c->type]->dc, c->dev,		c->qid.path, w, c->qid.vers, c->qid.type,		c->iounit, c->offset, c->name->s);	return n;} static intprogfds(Osenv *o, char *va, int count, long offset){	Fgrp *f;	Chan *c;	int n, i, w, ww; 

Lines 1–500 of 1510.