ref: cbf5d3dc340da5b96cd1282e622a3f862c5b103e
dir: /sys/src/cmd/db/command.c/
/* * * debugger * */ #include "defs.h" #include "fns.h" char BADEQ[] = "unexpected `='"; BOOL executing; extern Rune *lp; char eqformat[ARB] = "z"; char stformat[ARB] = "zMi"; ADDR ditto; ADDR dot; int dotinc; WORD adrval, cntval, loopcnt; int adrflg, cntflg; /* command decoding */ int command(Rune *buf, int defcom) { char *reg; char savc; Rune *savlp=lp; char savlc = lastc; char savpc = peekc; static char lastcom = '=', savecom = '='; if (defcom == 0) defcom = lastcom; if (buf) { if (*buf==EOR) return(FALSE); clrinp(); lp=buf; } do { adrflg=expr(0); /* first address */ if (adrflg){ dot=expv; ditto=expv; } adrval=dot; if (rdc()==',' && expr(0)) { /* count */ cntflg=TRUE; cntval=expv; } else { cntflg=FALSE; cntval=1; reread(); } if (!eol(rdc())) lastcom=lastc; /* command */ else { if (adrflg==0) dot=inkdot(dotinc); reread(); lastcom=defcom; } switch(lastcom) { case '/': case '=': case '?': savecom = lastcom; acommand(lastcom); break; case '>': lastcom = savecom; savc=rdc(); if (reg=regname(savc)) rput(cormap, reg, dot); else error("bad variable"); break; case '!': lastcom=savecom; shell(); break; case '$': lastcom=savecom; printtrace(nextchar()); break; case ':': if (!executing) { executing=TRUE; subpcs(nextchar()); executing=FALSE; lastcom=savecom; } break; case 0: prints(DBNAME); break; default: error("bad command"); } flushbuf(); } while (rdc()==';'); if (buf == 0) reread(); else { clrinp(); lp=savlp; lastc = savlc; peekc = savpc; } if(adrflg) return dot; return 1; } /* * [/?][wml] */ void acommand(int pc) { int eqcom; Map *map; char *fmt; char buf[512]; if (pc == '=') { eqcom = 1; fmt = eqformat; map = dotmap; } else { eqcom = 0; fmt = stformat; if (pc == '/') map = cormap; else map = symmap; } if (!map) { snprint(buf, sizeof(buf), "no map for %c", pc); error(buf); } switch (rdc()) { case 'm': if (eqcom) error(BADEQ); cmdmap(map); break; case 'L': case 'l': if (eqcom) error(BADEQ); cmdsrc(lastc, map); break; case 'W': case 'w': if (eqcom) error(BADEQ); cmdwrite(lastc, map); break; default: reread(); getformat(fmt); scanform(cntval, !eqcom, fmt, map, eqcom); } } void cmdsrc(int c, Map *map) { ulong w; long locval, locmsk; ADDR savdot; ushort sh; char buf[512]; int ret; if (c == 'L') dotinc = 4; else dotinc = 2; savdot=dot; expr(1); locval=expv; if (expr(0)) locmsk=expv; else locmsk = ~0; if (c == 'L') while ((ret = get4(map, dot, &w)) > 0 && (w&locmsk) != locval) dot = inkdot(dotinc); else while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval) dot = inkdot(dotinc); if (ret < 0) { dot=savdot; error("%r"); } symoff(buf, 512, dot, CANY); dprint(buf); } static char badwrite[] = "can't write process memory or text image"; void cmdwrite(int wcom, Map *map) { ADDR savdot; char *format; int pass; if (wcom == 'w') format = "x"; else format = "X"; expr(1); pass = 0; do { pass++; savdot=dot; exform(1, 1, format, map, 0, pass); dot=savdot; if (wcom == 'W') { if (put4(map, dot, expv) <= 0) error(badwrite); } else { if (put2(map, dot, expv) <= 0) error(badwrite); } savdot=dot; dprint("=%8t"); exform(1, 0, format, map, 0, pass); newline(); } while (expr(0)); dot=savdot; } /* * collect a register name; return register offset * this is not what i'd call a good division of labour */ char * regname(int regnam) { static char buf[64]; char *p; int c; p = buf; *p++ = regnam; while (isalnum(c = readchar())) { if (p >= buf+sizeof(buf)-1) error("register name too long"); *p++ = c; } *p = 0; reread(); return (buf); } /* * shell escape */ void shell(void) { int rc, unixpid; char *argp = (char*)lp; while (lastc!=EOR) rdc(); if ((unixpid=fork())==0) { *lp=0; execl("/bin/rc", "rc", "-c", argp, nil); exits("execl"); /* botch */ } else if (unixpid == -1) { error("cannot fork"); } else { mkfault = 0; while ((rc = waitpid()) != unixpid){ if(rc == -1 && mkfault){ mkfault = 0; continue; } break; } prints("!"); reread(); } }