#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. Load more
#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 int getbreaks(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; } void freebreak(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; } void freecondlist(BkptCond *l) { BkptCond *next; while(l != nil){ next = l->next; free(l); l = next; } } void breakset(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; } void breakrestore(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; } void breaknotify(Bkpt *b, Proc *p) { p->dbgstop = 1; // stop running this process. b->handler(b); } int breakmatch(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; } void breakinit(void) { machbreakinit(); } static void dbglog(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 int get(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 void mesg(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 ulong dbglong(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 void dumpcmd(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 int brkpending(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 void gotbreak(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 int startstop(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 int condbreak(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. //