forsyth20121205-174063a80cc13 years agoHistory
1000 lines · 16.8 KB · C
RawDownload
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "ureg.h"#include "../port/error.h"#include	"rdbg.h" #include	<kernel.h>#include	<interp.h> /* *	The following should be set in the config file to override *	the defaults. */int	dbgstart;char	*dbgdata;char	*dbgctl;char	*dbgctlstart;char	*dbgctlstop;char	*dbgctlflush; //// Error messages sent to the remote debugger//static	uchar	Ereset[9] = { 'r', 'e', 's', 'e', 't' };static	uchar	Ecount[9] = { 'c', 'o', 'u', 'n', 't' };static	uchar	Eunk[9] = { 'u', 'n', 'k' };static	uchar	Einval[9] = { 'i', 'n', 'v', 'a', 'l' };static	uchar	Ebadpid[9] = {'p', 'i', 'd'};static	uchar	Eunsup[9] = { 'u', 'n', 's', 'u', 'p' };static	uchar	Enotstop[9] = { 'n', 'o', 't', 's', 't', 'o', 'p' }; //// Error messages raised via call to error()//static	char	Erunning[] = "Not allowed while debugger is running";static	char	Enumarg[] = "Not enough args";static	char	Ebadcmd[] = "Unknown command"; static	int	PROCREG;static	struct {	Rendez;	Bkpt *b;} brk; static	Queue	*logq; int	dbgchat = 0; typedef struct Debugger Debugger;struct Debugger {	RWlock;	int	running;	char	data[PRINTSIZE];	char	ctl[PRINTSIZE];	char	ctlstart[PRINTSIZE];	char	ctlstop[PRINTSIZE];	char	ctlflush[PRINTSIZE];}; static Debugger debugger = {	.data=		"#t/eia0",	.ctl=		"#t/eia0ctl",	.ctlstart=	"b19200",	.ctlstop=	"h",	.ctlflush=	"f",}; enum {	BkptStackSize=	256,}; typedef struct SkipArg SkipArg;struct SkipArg{	Bkpt *b;	Proc *p;}; Bkpt	*breakpoints;void	freecondlist(BkptCond *l); static intgetbreaks(ulong addr, Bkpt **a, int nb){	Bkpt *b;	int n; 	n = 0;	for(b = breakpoints; b != nil; b = b->next){		if(b->addr == addr){			a[n++] = b;			if(n == nb)				break;		}	}	return n;} Bkpt*newbreak(int id, ulong addr, BkptCond *conds, void(*handler)(Bkpt*), void *aux){	Bkpt *b; 	b = malloc(sizeof(*b));	if(b == nil)		error(Enomem); 	b->id = id;	b->conditions = conds;	b->addr = addr;	b->handler = handler;	b->aux = aux;	b->next = nil; 	return b;} voidfreebreak(Bkpt *b){	freecondlist(b->conditions);	free(b);} BkptCond*newcondition(uchar cmd, ulong val){	BkptCond *c; 	c = mallocz(sizeof(*c), 0);	if(c == nil)		error(Enomem); 	c->op = cmd;	c->val = val;	c->next = nil; 	return c;} voidfreecondlist(BkptCond *l){	BkptCond *next; 	while(l != nil){		next = l->next;		free(l);		l = next;	}}  voidbreakset(Bkpt *b){	Bkpt *e[1]; 	if(getbreaks(b->addr, e, 1) != 0){		b->instr = e[0]->instr;	} else {		b->instr = machinstr(b->addr);		machbreakset(b->addr);	} 	b->next = breakpoints;	breakpoints = b;} voidbreakrestore(Bkpt *b){	b->next = breakpoints;	breakpoints = b;	machbreakset(b->addr);} Bkpt*breakclear(int id){	Bkpt *b, *e, *p; 	for(b=breakpoints, p=nil; b != nil && b->id != id; p = b, b = b->next)		; 	if(b != nil){		if(p == nil)			breakpoints = b->next;		else			p->next = b->next; 		if(getbreaks(b->addr, &e, 1) == 0)			machbreakclear(b->addr, b->instr);	} 	return b;} voidbreaknotify(Bkpt *b, Proc *p){	p->dbgstop = 1;		// stop running this process.	b->handler(b);} intbreakmatch(BkptCond *cond, Ureg *ur, Proc *p){	ulong a, b;	int pos;	ulong s[BkptStackSize]; 	memset(s, 0, sizeof(s));	pos = 0; 	for(;cond != nil; cond = cond->next){		switch(cond->op){		default:			panic("breakmatch: unknown operator %c", cond->op);			break;		case 'k':			if(p == nil || p->pid != cond->val)				return 0;			s[pos++] = 1;			break;		case 'b':			if(ur->pc != cond->val)				return 0;			s[pos++] = 1;			break;		case 'p': s[pos++] = cond->val; break;		case '*': a = *(ulong*)s[--pos]; s[pos++] = a; break;		case '&': a = s[--pos]; b = s[--pos]; s[pos++] = a & b; break;		case '=': a = s[--pos]; b = s[--pos]; s[pos++] = a == b; break;		case '!': a = s[--pos]; b = s[--pos]; s[pos++] = a != b; break;		case 'a': a = s[--pos]; b = s[--pos]; s[pos++] = a && b; break;		case 'o': a = s[--pos]; b = s[--pos]; s[pos++] = a || b; break;		}	} 	if(pos && s[pos-1])		return 1;	return 0;} voidbreakinit(void){	machbreakinit();} static voiddbglog(char *fmt, ...){	int n;	va_list arg;	char buf[PRINTSIZE]; 	va_start(arg, fmt);	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;	va_end(arg);	qwrite(logq, buf, n);} static intget(int dbgfd, uchar *b){	int i;	uchar c; 	if(kread(dbgfd, &c, 1) < 0)		error(Eio);	for(i=0; i<9; i++){		if(kread(dbgfd, b++, 1) < 0)			error(Eio);	}	return c;} static voidmesg(int dbgfd, int m, uchar *buf){	int i;	uchar c; 	c = m;	if(kwrite(dbgfd, &c, 1) < 0)		error(Eio);	for(i=0; i<9; i++){		if(kwrite(dbgfd, buf+i, 1) < 0)			error(Eio);	}} static ulongdbglong(uchar *s){	return (s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]<<0);} static Proc *dbgproc(ulong pid, int dbgok){	int i;	Proc *p; 	if(!dbgok && pid == up->pid)		return 0;	p = proctab(0);	for(i = 0; i < conf.nproc; i++){		if(p->pid == pid)			return p;		p++;	}	return 0;} static void*addr(uchar *s){	ulong a;	Proc *p;	static Ureg ureg; 	a = ((s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]<<0));	if(a < sizeof(Ureg)){		p = dbgproc(PROCREG, 0);		if(p == 0){			dbglog("dbg: invalid pid\n");			return 0;		}		if(p->dbgreg){			/* in trap(), registers are all on stack */			memmove(&ureg, p->dbgreg, sizeof(ureg));		}		else {			/* not in trap, only pc and sp are available */			memset(&ureg, 0, sizeof(ureg));			ureg.sp = p->sched.sp;			ureg.pc = p->sched.pc;		}		return (uchar*)&ureg+a;	}	return (void*)a;}  static voiddumpcmd(uchar cmd, uchar *min){	char *s;	int n; 	switch(cmd){	case Terr:		s = "Terr"; break;	case Tmget:		s = "Tmget"; break;	case Tmput:		s = "Tmput"; break;	case Tspid:		s = "Tspid"; break;	case Tproc:		s = "Tproc"; break;	case Tstatus:		s = "Tstatus"; break;	case Trnote:		s = "Trnote"; break;	case Tstartstop:	s = "Tstartstop"; break;	case Twaitstop:		s = "Twaitstop"; break;	case Tstart:		s = "Tstart"; break;	case Tstop:		s = "Tstop"; break;	case Tkill:		s = "Tkill"; break;	case Tcondbreak:	s = "Tcondbreak"; break;	default:		s = "<Unknown>"; break;	}	dbglog("%s: [%2.2ux]: ", s, cmd);	for(n = 0; n < 9; n++)		dbglog("%2.2ux", min[n]);	dbglog("\n");} static intbrkpending(void *a){	Proc *p; 	p = a;	if(brk.b != nil) return 1; 	p->dbgstop = 0;			/* atomic */	if(p->state == Stopped)		ready(p); 	return 0;} static voidgotbreak(Bkpt *b){	Bkpt *cur, *prev; 	b->link = nil; 	for(prev = nil, cur = brk.b; cur != nil; prev = cur, cur = cur->link)		;	if(prev == nil)		brk.b = b;	else		prev->link = b; 	wakeup(&brk);} static intstartstop(Proc *p){	int id;	int s;	Bkpt *b; 	sleep(&brk, brkpending, p); 	s = splhi();	b = brk.b;	brk.b = b->link;	splx(s); 	id = b->id; 	return id;} static intcondbreak(char cmd, ulong val){	BkptCond *c;	static BkptCond *head = nil;	static BkptCond *tail = nil;	static Proc *p = nil;	static int id = -1;	int s; 	if(waserror()){		dbglog(up->env->errstr);		freecondlist(head);		head = tail = nil;		p = nil;		id = -1;		return 0;	} 	switch(cmd){	case 'b': case 'p':	case '*': case '&': case '=':	case '!': case 'a': case 'o':		break;	case 'n':		id = val;		poperror();		return 1;	case 'k':		p = dbgproc(val, 0);		if(p == nil)			error("k: unknown pid");		break;	case 'd': {		Bkpt *b; 		s = splhi();		b = breakclear(val);		if(b != nil){			Bkpt *cur, *prev; 			prev = nil;			cur = brk.b;			while(cur != nil){				if(cur->id == b->id){					if(prev == nil)						brk.b = cur->link;					else						prev->link = cur->link;					break;				}				cur = cur->link;			}			freebreak(b);		}		splx(s);		poperror();		return 1;		}	default:		dbglog("condbreak(): unknown op %c %lux\n", cmd, val);		error("unknown op");	} 	c = newcondition(cmd, val); 	 //	 // the 'b' command comes last, (so we know we have reached the end	 // of the condition list), but it should be the first thing	 // checked, so put it at the head.	 //

Lines 1–500 of 1000.