This commit is contained in:
rsc 2004-04-19 19:30:50 +00:00
parent a84cbb2a17
commit 84114f0665
15 changed files with 3179 additions and 0 deletions

311
src/cmd/db/command.c Normal file
View file

@ -0,0 +1,311 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
char BADEQ[] = "unexpected `='";
BOOL executing;
extern char *lp;
char eqformat[ARB] = "z";
char stformat[ARB] = "zMi";
ADDR ditto;
ADDR dot;
WORD dotinc;
WORD adrval, cntval, loopcnt;
int adrflg, cntflg;
/* command decoding */
int
command(char *buf, int defcom)
{
char *reg;
char savc;
char *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(correg, reg, dot);
else
error("bad variable");
break;
case '!':
lastcom=savecom;
shell();
break;
case '$':
lastcom=savecom;
printdollar(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) {
sprint(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)
{
u32int 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 = lp;
while (lastc!=EOR)
rdc();
if ((unixpid=fork())==0) {
*lp=0;
execl("/bin/rc", "rc", "-c", argp, 0);
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();
}
}

111
src/cmd/db/defs.h Normal file
View file

@ -0,0 +1,111 @@
/*
* db - common definitions
* something of a grab-bag
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include <mach.h>
typedef long WORD;
typedef ulong ADDR;
#define HUGEINT 0x7fffffff /* enormous WORD */
#define MAXOFF 0x1000000
#define INCDIR "/usr/lib/adb"
#define DBNAME "db\n"
#define CMD_VERBS "?/=>!$: \t"
typedef int BOOL;
#define MAXPOS 80
#define MAXLIN 128
#define ARB 512
#define MAXCOM 64
#define MAXARG 32
#define LINSIZ 4096
#define MAXSYM 255
#define EOR '\n'
#define SPC ' '
#define TB '\t'
#define STDIN 0
#define STDOUT 1
#define TRUE (-1)
#define FALSE 0
/*
* run modes
*/
#define SINGLE 1
#define CONTIN 2
/*
* breakpoints
*/
#define BKPTCLR 0 /* not a real breakpoint */
#define BKPTSET 1 /* real, ready to trap */
#define BKPTSKIP 2 /* real, skip over it next time */
#define BKPTTMP 3 /* temporary; clear when it happens */
struct bkpt {
ADDR loc;
uchar save[4];
int count;
int initcnt;
int flag;
char comm[MAXCOM];
struct bkpt *nxtbkpt;
};
typedef struct bkpt BKPT;
#define BADREG (-1)
/*
* common globals
*/
extern WORD adrval;
extern vlong expv;
extern int adrflg;
extern WORD cntval;
extern int cntflg;
extern WORD loopcnt;
extern ADDR maxoff;
extern ADDR localval;
extern ADDR maxfile;
extern ADDR maxstor;
extern ADDR dot;
extern WORD dotinc;
extern int xargc;
extern BOOL wtflag;
extern char *corfil, *symfil;
extern BOOL mkfault;
extern BOOL regdirty;
extern int pid;
extern int pcsactive;
#define NNOTE 10
extern int nnote;
extern char note[NNOTE][ERRMAX];
extern int ending;
extern Fhdr *corhdr, *symhdr;
extern Map *cormap, *symmap, *dotmap;
extern Regs *correg;
extern BKPT *bkpthead;
extern int kflag;
extern int lastc, peekc;

397
src/cmd/db/expr.c Normal file
View file

@ -0,0 +1,397 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
static long dbround(long, long);
extern ADDR ditto;
vlong expv;
static WORD
ascval(void)
{
Rune r;
if (readchar() == 0)
return (0);
r = lastc;
while(quotchar()) /*discard chars to ending quote */
;
return((WORD) r);
}
/*
* read a floating point number
* the result must fit in a WORD
*/
static WORD
fpin(char *buf)
{
union {
WORD w;
float f;
} x;
x.f = atof(buf);
return (x.w);
}
WORD
defval(WORD w)
{
if (expr(0))
return (expv);
else
return (w);
}
int
expr(int a)
{ /* term | term dyadic expr | */
int rc;
WORD lhs;
rdc();
reread();
rc=term(a);
while (rc) {
lhs = expv;
switch ((int)readchar()) {
case '+':
term(a|1);
expv += lhs;
break;
case '-':
term(a|1);
expv = lhs - expv;
break;
case '#':
term(a|1);
expv = dbround(lhs,expv);
break;
case '*':
term(a|1);
expv *= lhs;
break;
case '%':
term(a|1);
if(expv != 0)
expv = lhs/expv;
else{
if(lhs)
expv = 1;
else
expv = 0;
}
break;
case '&':
term(a|1);
expv &= lhs;
break;
case '|':
term(a|1);
expv |= lhs;
break;
case ')':
if ((a&2)==0)
error("unexpected `)'");
default:
reread();
return(rc);
}
}
return(rc);
}
int
term(int a)
{ /* item | monadic item | (expr) | */
u32int u;
switch ((int)readchar()) {
case '*':
term(a|1);
if (get4(cormap, (ADDR)expv, &u) < 0)
error("%r");
expv = u;
return(1);
case '@':
term(a|1);
if (get4(symmap, (ADDR)expv, &u) < 0)
error("%r");
expv = u;
return(1);
case '-':
term(a|1);
expv = -expv;
return(1);
case '~':
term(a|1);
expv = ~expv;
return(1);
case '(':
expr(2);
if (readchar()!=')')
error("syntax error: `)' expected");
return(1);
default:
reread();
return(item(a));
}
}
int
item(int a)
{ /* name [ . local ] | number | . | ^ | <register | 'x | | */
char *base;
char savc;
ulong u;
Symbol s;
char gsym[MAXSYM], lsym[MAXSYM];
readchar();
if (isfileref()) {
readfname(gsym);
rdc(); /* skip white space */
if (lastc == ':') { /* it better be */
rdc(); /* skip white space */
if (!getnum(readchar))
error("bad number");
if (expv == 0)
expv = 1; /* file begins at line 1 */
if(file2pc(gsym, expv, &u) < 0)
error("%r");
expv = u;
return 1;
}
error("bad file location");
} else if (symchar(0)) {
readsym(gsym);
if (lastc=='.') {
readchar(); /* ugh */
if (lastc == '.') {
lsym[0] = '.';
readchar();
readsym(lsym+1);
} else if (symchar(0)) {
readsym(lsym);
} else
lsym[0] = 0;
if (localaddr(cormap, correg, gsym, lsym, &u) < 0)
error("%r");
expv = u;
}
else {
if (lookupsym(0, gsym, &s) < 0)
error("symbol not found");
if (s.loc.type != LADDR)
error("symbol not kept in memory");
expv = s.loc.addr;
}
reread();
} else if (getnum(readchar)) {
;
} else if (lastc=='.') {
readchar();
if (!symchar(0) && lastc != '.') {
expv = dot;
} else {
if (findsym(locaddr(dbrget(cormap, mach->pc)), CTEXT, &s) < 0)
error("no current function");
if (lastc == '.') {
lsym[0] = '.';
readchar();
readsym(lsym+1);
} else
readsym(lsym);
if (localaddr(cormap, correg, s.name, lsym, &u) < 0)
error("%r");
expv = u;
}
reread();
} else if (lastc=='"') {
expv=ditto;
} else if (lastc=='+') {
expv=inkdot(dotinc);
} else if (lastc=='^') {
expv=inkdot(-dotinc);
} else if (lastc=='<') {
savc=rdc();
base = regname(savc);
expv = dbrget(cormap, base);
}
else if (lastc=='\'')
expv = ascval();
else if (a)
error("address expected");
else {
reread();
return(0);
}
return(1);
}
#define MAXBASE 16
/* service routines for expression reading */
int
getnum(int (*rdf)(void))
{
char *cp;
int base, d;
BOOL fpnum;
char num[MAXLIN];
base = 0;
fpnum = FALSE;
if (lastc == '#') {
base = 16;
(*rdf)();
}
if (convdig(lastc) >= MAXBASE)
return (0);
if (lastc == '0')
switch ((*rdf)()) {
case 'x':
case 'X':
base = 16;
(*rdf)();
break;
case 't':
case 'T':
base = 10;
(*rdf)();
break;
case 'o':
case 'O':
base = 8;
(*rdf)();
break;
default:
if (base == 0)
base = 8;
break;
}
if (base == 0)
base = 10;
expv = 0;
for (cp = num, *cp = lastc; ;(*rdf)()) {
if ((d = convdig(lastc)) < base) {
expv *= base;
expv += d;
*cp++ = lastc;
}
else if (lastc == '.') {
fpnum = TRUE;
*cp++ = lastc;
} else {
reread();
break;
}
}
if (fpnum)
expv = fpin(num);
return (1);
}
void
readsym(char *isymbol)
{
char *p;
Rune r;
p = isymbol;
do {
if (p < &isymbol[MAXSYM-UTFmax-1]){
r = lastc;
p += runetochar(p, &r);
}
readchar();
} while (symchar(1));
*p = 0;
}
void
readfname(char *filename)
{
char *p;
Rune c;
/* snarf chars until un-escaped char in terminal char set */
p = filename;
do {
if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
p += runetochar(p, &c);
readchar();
} while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
*p = 0;
reread();
}
int
convdig(int c)
{
if (isdigit(c))
return(c-'0');
else if (!isxdigit(c))
return(MAXBASE);
else if (isupper(c))
return(c-'A'+10);
else
return(c-'a'+10);
}
int
symchar(int dig)
{
if (lastc=='\\') {
readchar();
return(TRUE);
}
return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
}
static long
dbround(long a, long b)
{
long w;
w = (a/b)*b;
if (a!=w)
w += b;
return(w);
}
ulong
dbrget(Map *map, char *name)
{
ulong u;
USED(map);
if(rget(correg, name, &u) < 0)
return ~(ulong)0;
return u;
}

91
src/cmd/db/fns.h Normal file
View file

@ -0,0 +1,91 @@
void acommand(int);
void attachprocess(void);
void bkput(BKPT*, int);
void bpwait(void);
int charpos(void);
void chkerr(void);
void clrinp(void);
void cmdmap(Map*);
void cmdsrc(int, Map*);
void cmdwrite(int, Map*);
int command(char*, int);
int convdig(int);
void ctrace(int);
WORD defval(WORD);
void delbp(void);
ulong dbrget(Map*, char*);
void done(void);
int dprint(char*, ...);
Map* dumbmap(int);
void endline(void);
void endpcs(void);
int eol(int);
void error(char*);
void errors(char*, char*);
void execbkpt(BKPT*, int);
char* exform(int, int, char*, Map*, int, int);
int expr(int);
/*
void fixregs(Map*);
void adjustreg(char*, ulong, long);
*/
void flush(void);
void flushbuf(void);
char* getfname(void);
void getformat(char*);
int getnum(int (*)(void));
void grab(void);
void iclose(int, int);
ADDR inkdot(long);
int isfileref(void);
int item(int);
void killpcs(void);
void kmsys(void);
void main(int, char**);
int mapimage(void);
void newline(void);
int nextchar(void);
void notes(void);
void oclose(void);
void outputinit(void);
void printc(int);
void printdollar(int);
void printesc(int);
void printlocals(Symbol*, Regs*);
void printmap(char*, Map*);
void printparams(Symbol*, Regs*);
void printpc(void);
void printregs(int);
void prints(char*);
void printsource(long);
void printsym(void);
void printsyscall(void);
int quotchar(void);
int rdc(void);
int readchar(void);
void readsym(char*);
void redirin(int, char*);
void redirout(char*);
void readfname(char *);
void reread(void);
char* regname(int);
//vlong rget(Map*, char*);
Regdesc* rname(char*);
//void rput(Map*, char*, vlong);
int runpcs(int, int);
void runrun(int);
void runstep(ulong, int);
BKPT* scanbkpt(ADDR adr);
void scanform(long, int, char*, Map*, int);
void setbp(void);
void setcor(void);
void setsym(void);
void setup(void);
void setvec(void);
void shell(void);
void startpcs(void);
void subpcs(int);
int symchar(int);
int term(int);
void ungrab(void);
int valpr(long, int);

388
src/cmd/db/format.c Normal file
View file

@ -0,0 +1,388 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
void
scanform(long icount, int prt, char *ifp, Map *map, int literal)
{
char *fp;
char c;
int fcount;
ADDR savdot;
int firstpass;
firstpass = 1;
while (icount) {
fp=ifp;
savdot=dot;
/*now loop over format*/
while (*fp) {
if (!isdigit(*fp))
fcount = 1;
else {
fcount = 0;
while (isdigit(c = *fp++)) {
fcount *= 10;
fcount += c-'0';
}
fp--;
}
if (*fp==0)
break;
fp=exform(fcount,prt,fp,map,literal,firstpass);
firstpass = 0;
}
dotinc=dot-savdot;
dot=savdot;
if (--icount)
dot=inkdot(dotinc);
}
}
char *
exform(int fcount, int prt, char *ifp, Map *map, int literal, int firstpass)
{
/* execute single format item `fcount' times
* sets `dotinc' and moves `dot'
* returns address of next format item
*/
vlong v;
WORD w;
ulong savdot;
u16int u2;
u32int u4;
u64int u8;
char *fp;
char c, modifier;
int i;
ushort sh, *sp;
uchar ch, *cp;
Symbol s;
char buf[512];
extern int printcol;
fp = 0;
while (fcount > 0) {
fp = ifp;
c = *fp;
modifier = *fp++;
if (firstpass) {
firstpass = 0;
if (!literal && (c == 'i' || c == 'I' || c == 'M')
&& (dot & (mach->pcquant-1))) {
dprint("warning: instruction not aligned");
printc('\n');
}
if (prt && modifier != 'a' && modifier != 'A') {
symoff(buf, 512, dot, CANY);
dprint("%s%c%16t", buf, map==symmap? '?':'/');
}
}
if (printcol==0 && modifier != 'a' && modifier != 'A')
dprint("\t\t");
switch(modifier) {
case SPC:
case TB:
dotinc = 0;
break;
case 't':
case 'T':
dprint("%*t", fcount);
dotinc = 0;
return(fp);
case 'a':
symoff(buf, sizeof(buf), dot, CANY);
dprint("%s%c%16t", buf, map==symmap? '?':'/');
dotinc = 0;
break;
case 'A':
dprint("%#lux%10t", dot);
dotinc = 0;
break;
case 'p':
if (get4(map, dot, &u4) < 0)
error("%r");
w = u4;
symoff(buf, sizeof(buf), w, CANY);
dprint("%s%16t", buf);
dotinc = mach->szaddr;
break;
case 'u':
case 'd':
case 'x':
case 'o':
case 'q':
if (literal)
u2 = (ushort) dot;
else if (get2(map, dot, &u2) < 0)
error("%r");
w = u2;
dotinc = 2;
if (c == 'u')
dprint("%-8lud", w);
else if (c == 'x')
dprint("%-8#lux", w);
else if (c == 'd')
dprint("%-8ld", w);
else if (c == 'o')
dprint("%-8#luo", w);
else if (c == 'q')
dprint("%-8#lo", w);
break;
case 'U':
case 'D':
case 'X':
case 'O':
case 'Q':
if (literal)
u4 = (long) dot;
else if (get4(map, dot, &u4) < 0)
error("%r");
dotinc = 4;
if (c == 'U')
dprint("%-16lud", u4);
else if (c == 'X')
dprint("%-16#lux", u4);
else if (c == 'D')
dprint("%-16ld", u4);
else if (c == 'O')
dprint("%-#16luo", u4);
else if (c == 'Q')
dprint("%-#16lo", u4);
break;
case 'Z':
case 'V':
case 'Y':
if (literal)
v = dot;
else if (get8(map, dot, &u8) < 0)
error("%r");
dotinc = 8;
if (c == 'Y')
dprint("%-20#llux", u8);
else if (c == 'V')
dprint("%-20lld", u8);
else if (c == 'Z')
dprint("%-20llud", u8);
break;
case 'B':
case 'b':
case 'c':
case 'C':
if (literal)
ch = (uchar) dot;
else if (get1(map, dot, &ch, 1) < 0)
error("%r");
if (modifier == 'C')
printesc(ch);
else if (modifier == 'B' || modifier == 'b')
dprint("%-8#lux", (long) ch);
else
printc(ch);
dotinc = 1;
break;
case 'r':
if (literal)
sh = (ushort) dot;
else if (get2(map, dot, &sh) < 0)
error("%r");
dprint("%C", sh);
dotinc = 2;
break;
case 'R':
if (literal) {
sp = (u16int*)(void*)&dot;
dprint("%C%C", sp[0], sp[1]);
endline();
dotinc = 4;
break;
}
savdot=dot;
while ((i = get2(map, dot, &u2) > 0) && u2) {
dot=inkdot(2);
dprint("%C", u2);
endline();
}
if (i < 0)
error("%r");
dotinc = dot-savdot+2;
dot=savdot;
break;
case 's':
if (literal) {
cp = (uchar*)(void*)&dot;
for (i = 0; i < 4; i++)
buf[i] = cp[i];
buf[i] = 0;
dprint("%s", buf);
endline();
dotinc = 4;
break;
}
savdot = dot;
for(;;){
i = 0;
do{
if (get1(map, dot, (uchar*)(void*)&buf[i], 1) < 0)
error("%r");
dot = inkdot(1);
i++;
}while(!fullrune(buf, i));
if(buf[0] == 0)
break;
buf[i] = 0;
dprint("%s", buf);
endline();
}
dotinc = dot-savdot+1;
dot = savdot;
break;
case 'S':
if (literal) {
cp = (uchar*) &dot;
for (i = 0; i < 4; i++)
printesc(cp[i]);
endline();
dotinc = 4;
break;
}
savdot=dot;
while ((i = get1(map, dot, &ch, 1) > 0) && ch) {
dot=inkdot(1);
printesc(ch);
endline();
}
if (i < 0)
error("%r");
dotinc = dot-savdot+1;
dot=savdot;
break;
case 'I':
case 'i':
dotinc = mach->das(map, dot, modifier, buf, sizeof(buf));
if (dotinc < 0)
error("%r");
dprint("%s\n", buf);
break;
case 'M':
dotinc = mach->hexinst(map, dot, buf, sizeof(buf));
if (dotinc < 0)
error("%r");
dprint("%s", buf);
if (*fp) {
dotinc = 0;
dprint("%48t");
} else
dprint("\n");
break;
case 'f':
/* BUG: 'f' and 'F' assume szdouble is sizeof(vlong) in the literal case */
if (literal) {
v = mach->swap8((ulong)dot);
memmove(buf, &v, mach->szfloat);
}else if (get1(map, dot, (uchar*)buf, mach->szfloat) < 0)
error("%r");
mach->ftoa32(buf, sizeof(buf), (void*) buf);
dprint("%s\n", buf);
dotinc = mach->szfloat;
break;
case 'F':
/* BUG: 'f' and 'F' assume szdouble is sizeof(vlong) in the literal case */
if (literal) {
v = mach->swap8(dot);
memmove(buf, &v, mach->szdouble);
}else if (get1(map, dot, (uchar*)buf, mach->szdouble) < 0)
error("%r");
mach->ftoa64(buf, sizeof(buf), (void*) buf);
dprint("%s\n", buf);
dotinc = mach->szdouble;
break;
case 'n':
case 'N':
printc('\n');
dotinc=0;
break;
case '"':
dotinc=0;
while (*fp != '"' && *fp)
printc(*fp++);
if (*fp)
fp++;
break;
case '^':
dot=inkdot(-dotinc*fcount);
return(fp);
case '+':
dot=inkdot((WORD)fcount);
return(fp);
case '-':
dot=inkdot(-(WORD)fcount);
return(fp);
case 'z':
if (findsym(locaddr(dot), CTEXT, &s) >= 0)
dprint("%s() ", s.name);
printsource(dot);
printc(EOR);
return fp;
default:
error("bad modifier");
}
if (map->seg[0].fd >= 0)
dot=inkdot(dotinc);
fcount--;
endline();
}
return(fp);
}
void
printesc(int c)
{
static char hex[] = "0123456789abcdef";
if (c < SPC || c >= 0177)
dprint("\\x%c%c", hex[(c&0xF0)>>4], hex[c&0xF]);
else
printc(c);
}
ADDR
inkdot(WORD incr)
{
ADDR newdot;
newdot=dot+incr;
if ((incr >= 0 && newdot < dot)
|| (incr < 0 && newdot > dot))
error("address wraparound");
return(newdot);
}

169
src/cmd/db/input.c Normal file
View file

@ -0,0 +1,169 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
Rune line[LINSIZ];
extern int infile;
Rune *lp;
int peekc,lastc = EOR;
int eof;
/* input routines */
int
eol(int c)
{
return(c==EOR || c==';');
}
int
rdc(void)
{
do {
readchar();
} while (lastc==SPC || lastc==TB);
return(lastc);
}
void
reread(void)
{
peekc = lastc;
}
void
clrinp(void)
{
flush();
lp = 0;
peekc = 0;
}
int
readrune(int fd, Rune *r)
{
char buf[UTFmax];
int i;
for(i=0; i<UTFmax && !fullrune(buf, i); i++)
if(read(fd, buf+i, 1) <= 0)
return -1;
chartorune(r, buf);
return 1;
}
int
readchar(void)
{
Rune *p;
if (eof)
lastc=0;
else if (peekc) {
lastc = peekc;
peekc = 0;
}
else {
if (lp==0) {
for (p = line; p < &line[LINSIZ-1]; p++) {
eof = readrune(infile, p) <= 0;
if (mkfault) {
eof = 0;
error(0);
}
if (eof) {
p--;
break;
}
if (*p == EOR) {
if (p <= line)
break;
if (p[-1] != '\\')
break;
p -= 2;
}
}
p[1] = 0;
lp = line;
}
if ((lastc = *lp) != 0)
lp++;
}
return(lastc);
}
int
nextchar(void)
{
if (eol(rdc())) {
reread();
return(0);
}
return(lastc);
}
int
quotchar(void)
{
if (readchar()=='\\')
return(readchar());
else if (lastc=='\'')
return(0);
else
return(lastc);
}
void
getformat(char *deformat)
{
char *fptr;
BOOL quote;
Rune r;
fptr=deformat;
quote=FALSE;
while ((quote ? readchar()!=EOR : !eol(readchar()))){
r = lastc;
fptr += runetochar(fptr, &r);
if (lastc == '"')
quote = ~quote;
}
lp--;
if (fptr!=deformat)
*fptr = '\0';
}
/*
* check if the input line if of the form:
* <filename>:<digits><verb> ...
*
* we handle this case specially because we have to look ahead
* at the token after the colon to decide if it is a file reference
* or a colon-command with a symbol name prefix.
*/
int
isfileref(void)
{
Rune *cp;
for (cp = lp-1; *cp && !strchr(CMD_VERBS, *cp); cp++)
if (*cp == '\\' && cp[1]) /* escape next char */
cp++;
if (*cp && cp > lp-1) {
while (*cp == ' ' || *cp == '\t')
cp++;
if (*cp++ == ':') {
while (*cp == ' ' || *cp == '\t')
cp++;
if (isdigit(*cp))
return 1;
}
}
return 0;
}

262
src/cmd/db/main.c Normal file
View file

@ -0,0 +1,262 @@
/*
* db - main command loop and error/interrupt handling
*/
#include "defs.h"
#include "fns.h"
int wtflag = OREAD;
BOOL kflag;
BOOL mkfault;
ADDR maxoff;
int xargc; /* bullshit */
extern BOOL executing;
extern int infile;
int exitflg;
extern int eof;
int alldigs(char*);
void fault(void*, char*);
extern char *Ipath;
jmp_buf env;
static char *errmsg;
Fhdr *symhdr, *corhdr;
void
usage(void)
{
fprint(2, "usage: db [-kw] [-m machine] [-I dir] [symfile] [pid]\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int i, omode;
char *s;
char *name;
Fhdr *hdr;
name = 0;
outputinit();
maxoff = MAXOFF;
omode = OREAD;
ARGBEGIN{
default:
usage();
case 'A':
abort();
case 'k':
kflag = 1;
break;
case 'w':
omode = ORDWR;
break;
case 'I':
s = ARGF();
if(s == 0)
dprint("missing -I argument\n");
else
Ipath = s;
break;
case 'm':
name = ARGF();
if(name == 0)
dprint("missing -m argument\n");
break;
}ARGEND
/*
* Unix and Plan 9 differ on what the right order of pid, text, and core is.
* I never remember anyway. Let's just accept them in any order.
*/
for(i=0; i<argc; i++){
if(alldigs(argv[i])){
if(pid){
dprint("already have pid %d; ignoring pid %d\n", pid, argv[i]);
continue;
}
if(corhdr){
dprint("already have core %s; ignoring pid %d\n", corfil, pid);
continue;
}
pid = atoi(argv[i]);
continue;
}
if((hdr = crackhdr(argv[i], omode)) == nil){
dprint("crackhdr %s: %r\n", argv[i]);
continue;
}
dprint("%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
if(hdr->ftype == FCORE){
if(pid){
dprint("already have pid %d; ignoring core %s\n", pid, argv[i]);
uncrackhdr(hdr);
continue;
}
if(corhdr){
dprint("already have core %s; ignoring core %s\n", corfil, argv[i]);
uncrackhdr(hdr);
continue;
}
corhdr = hdr;
corfil = argv[i];
}else{
if(symhdr){
dprint("already have text %s; ignoring text %s\n", symfil, argv[i]);
uncrackhdr(hdr);
continue;
}
symhdr = hdr;
symfil = argv[i];
}
}
if(symhdr==nil){
symfil = "a.out";
if(pid){
if((s = proctextfile(pid)) != nil){
dprint("pid %d: text %s\n", pid, s);
symfil = s;
}
}
/* XXX pull command from core */
if((symhdr = crackhdr(symfil, omode)) == nil){
dprint("crackhdr %s: %r\n", symfil);
symfil = nil;
}
}
if(!mach)
mach = machcpu;
/*
* Set up maps.
*/
symmap = allocmap();
cormap = allocmap();
if(symmap == nil || cormap == nil)
sysfatal("allocating maps: %r");
if(symhdr){
if(mapfile(symhdr, 0, symmap, nil) < 0)
dprint("mapping %s: %r\n", symfil);
mapfile(symhdr, 0, cormap, nil);
}
dotmap = dumbmap(-1);
/*
* show initial state and drop into the execution loop.
*/
notify(fault);
setsym();
if(setjmp(env) == 0){
if (pid || corhdr)
setcor(); /* could get error */
if (correg) {
dprint("%s\n", mach->exc(cormap, correg));
printpc();
}
}
setjmp(env);
if (executing)
delbp();
executing = FALSE;
for (;;) {
flushbuf();
if (errmsg) {
dprint(errmsg);
printc('\n');
errmsg = 0;
exitflg = 0;
}
if (mkfault) {
mkfault=0;
printc('\n');
prints(DBNAME);
}
clrinp();
rdc();
reread();
if (eof) {
if (infile == STDIN)
done();
iclose(-1, 0);
eof = 0;
longjmp(env, 1);
}
exitflg = 0;
command(0, 0);
reread();
if (rdc() != '\n')
error("newline expected");
}
}
int
alldigs(char *s)
{
while(*s){
if(*s<'0' || '9'<*s)
return 0;
s++;
}
return 1;
}
void
done(void)
{
if (pid)
endpcs();
exits(exitflg? "error": 0);
}
/*
* An error occurred; save the message for later printing,
* close open files, and reset to main command loop.
*/
void
error(char *n)
{
errmsg = n;
iclose(0, 1);
oclose();
flush();
delbp();
ending = 0;
longjmp(env, 1);
}
void
errors(char *m, char *n)
{
static char buf[128];
sprint(buf, "%s: %s", m, n);
error(buf);
}
/*
* An interrupt occurred;
* seek to the end of the current file
* and remember that there was a fault.
*/
void
fault(void *a, char *s)
{
USED(a);
if(strncmp(s, "interrupt", 9) == 0){
seek(infile, 0L, 2);
mkfault++;
noted(NCONT);
}
noted(NDFLT);
}

26
src/cmd/db/mkfile Normal file
View file

@ -0,0 +1,26 @@
<$PLAN9/src/mkhdr
TARG=db
OFILES=\
command.$O\
expr.$O\
format.$O\
input.$O\
main.$O\
output.$O\
pcs.$O\
runpcs.$O\
regs.$O\
trcrun.$O\
print.$O\
setup.$O\
HFILES=defs.h\
fns.h\
SHORTLIB=mach bio 9
<$PLAN9/src/mkone
CFLAGS=$CFLAGS -I../libmach2

159
src/cmd/db/output.c Normal file
View file

@ -0,0 +1,159 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
int printcol = 0;
int infile = STDIN;
int maxpos = MAXPOS;
Biobuf bstdout;
void
printc(int c)
{
dprint("%c", c);
}
/* was move to next f1-sized tab stop; now just print a tab */
int
tconv(Fmt *f)
{
return fmtstrcpy(f, "\t");
}
void
flushbuf(void)
{
if (printcol != 0)
printc(EOR);
}
void
prints(char *s)
{
dprint("%s",s);
}
void
newline(void)
{
printc(EOR);
}
#define MAXIFD 5
struct {
int fd;
int r9;
} istack[MAXIFD];
int ifiledepth;
void
iclose(int stack, int err)
{
if (err) {
if (infile) {
close(infile);
infile=STDIN;
}
while (--ifiledepth >= 0)
if (istack[ifiledepth].fd)
close(istack[ifiledepth].fd);
ifiledepth = 0;
} else if (stack == 0) {
if (infile) {
close(infile);
infile=STDIN;
}
} else if (stack > 0) {
if (ifiledepth >= MAXIFD)
error("$<< nested too deeply");
istack[ifiledepth].fd = infile;
ifiledepth++;
infile = STDIN;
} else {
if (infile) {
close(infile);
infile=STDIN;
}
if (ifiledepth > 0) {
infile = istack[--ifiledepth].fd;
}
}
}
void
oclose(void)
{
flushbuf();
Bterm(&bstdout);
Binit(&bstdout, 1, OWRITE);
}
void
redirout(char *file)
{
int fd;
if (file == 0){
oclose();
return;
}
flushbuf();
if ((fd = open(file, 1)) >= 0)
seek(fd, 0L, 2);
else if ((fd = create(file, 1, 0666)) < 0)
error("cannot create");
Bterm(&bstdout);
Binit(&bstdout, fd, OWRITE);
}
void
endline(void)
{
if (maxpos <= printcol)
newline();
}
void
flush(void)
{
Bflush(&bstdout);
}
int
dprint(char *fmt, ...)
{
int n, w;
char *p;
char buf[4096];
Rune r;
va_list arg;
if(mkfault)
return -1;
va_start(arg, fmt);
n = vseprint(buf, buf+sizeof buf, fmt, arg) - buf;
va_end(arg);
Bwrite(&bstdout, buf, n);
for(p=buf; *p; p+=w){
w = chartorune(&r, p);
if(r == '\n')
printcol = 0;
else
printcol++;
}
return n;
}
void
outputinit(void)
{
Binit(&bstdout, 1, OWRITE);
fmtinstall('t', tconv);
}

177
src/cmd/db/pcs.c Normal file
View file

@ -0,0 +1,177 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
char NOPCS[] = "no process";
/* sub process control */
void
subpcs(int modif)
{
int check;
int runmode;
int keepnote;
int n, r;
ulong line, curr;
BKPT *bk;
char *comptr;
runmode=SINGLE;
r = 0;
keepnote=0;
loopcnt=cntval;
switch (modif) {
/* delete breakpoint */
case 'd':
case 'D':
if ((bk=scanbkpt(dot)) == 0)
error("no breakpoint set");
bk->flag=BKPTCLR;
return;
/* set breakpoint */
case 'b':
case 'B':
if (bk=scanbkpt(dot))
bk->flag=BKPTCLR;
for (bk=bkpthead; bk; bk=bk->nxtbkpt)
if (bk->flag == BKPTCLR)
break;
if (bk==0) {
bk = (BKPT *)malloc(sizeof(*bk));
if (bk == 0)
error("too many breakpoints");
bk->nxtbkpt=bkpthead;
bkpthead=bk;
}
bk->loc = dot;
bk->initcnt = bk->count = cntval;
bk->flag = modif == 'b' ? BKPTSET : BKPTTMP;
check=MAXCOM-1;
comptr=bk->comm;
rdc();
reread();
do {
*comptr++ = readchar();
} while (check-- && lastc!=EOR);
*comptr=0;
if(bk->comm[0] != EOR && cntflg == FALSE)
bk->initcnt = bk->count = HUGEINT;
reread();
if (check)
return;
error("bkpt command too long");
/* exit */
case 'k' :
case 'K':
if (pid == 0)
error(NOPCS);
dprint("%d: killed", pid);
pcsactive = 1; /* force 'kill' ctl */
endpcs();
return;
/* run program */
case 'r':
case 'R':
endpcs();
setup();
runmode = CONTIN;
break;
/* single step */
case 's':
if (pid == 0) {
setup();
loopcnt--;
}
runmode=SINGLE;
keepnote=defval(1);
break;
case 'S':
if (pid == 0) {
setup();
loopcnt--;
}
keepnote=defval(1);
if(pc2line(dbrget(cormap, mach->pc), &line) < 0)
error("%r");
n = loopcnt;
dprint("%s: running\n", symfil);
flush();
for (loopcnt = 1; n > 0; loopcnt = 1) {
r = runpcs(SINGLE, keepnote);
if(pc2line(dot, &curr) < 0)
error("%r");
if (line != curr) { /* on a new line of c */
line = curr;
n--;
}
}
loopcnt = 0;
break;
/* continue with optional note */
case 'c':
case 'C':
if (pid==0)
error(NOPCS);
runmode=CONTIN;
keepnote=defval(1);
break;
case 'n': /* deal with notes */
if (pid==0)
error(NOPCS);
n=defval(-1);
if(n>=0 && n<nnote){
nnote--;
memmove(note[n], note[n+1], (nnote-n)*sizeof(note[0]));
}
notes();
return;
case 'h': /* halt the current process */
if (adrflg && adrval == 0) {
if (pid == 0)
error(NOPCS);
ungrab();
}
else {
grab();
dprint("stopped at%16t");
goto Return;
}
return;
case 'x': /* continue executing the current process */
if (pid == 0)
error(NOPCS);
ungrab();
return;
default:
error("bad `:' command");
}
if (loopcnt>0) {
dprint("%s: running\n", symfil);
flush();
r = runpcs(runmode,keepnote);
}
if (r)
dprint("breakpoint%16t");
else
dprint("stopped at%16t");
Return:
delbp();
printpc();
notes();
}

406
src/cmd/db/print.c Normal file
View file

@ -0,0 +1,406 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
extern int infile;
extern int outfile;
extern int maxpos;
/* general printing routines ($) */
char *Ipath = INCDIR;
static int tracetype;
static void printfp(Map*, int);
/*
* callback on stack trace
*/
static int
ptrace(Map *map, Regs *regs, ulong pc, ulong nextpc, Symbol *sym, int depth)
{
char buf[512];
USED(map);
if(sym){
dprint("%s(", sym->name);
printparams(sym, regs);
dprint(") ");
}else
dprint("%#lux ", pc);
printsource(pc);
dprint(" called from ");
symoff(buf, 512, nextpc, CTEXT);
dprint("%s ", buf);
/* printsource(nextpc); */
dprint("\n");
if(tracetype == 'C' && sym)
printlocals(sym, regs);
return depth<40;
}
static ulong *adrregvals;
static int
adrrw(Regs *regs, char *name, ulong *val, int isr)
{
int i;
if((i = windindex(name)) == -1)
return correg->rw(correg, name, val, isr);
if(isr){
*val = adrregvals[i];
return 0;
}
werrstr("saved registers are immutable");
return -1;
}
Regs*
adrregs(void)
{
int i;
static Regs r;
static u32int x;
if(adrregvals== nil){
adrregvals = malloc(mach->nwindreg*sizeof(adrregvals[0]));
if(adrregvals == nil)
error("%r");
}
for(i=0; i<mach->nwindreg; i++){
if(get4(cormap, adrval+4*i, &x) < 0)
error("%r");
adrregvals[i] = x;
}
r.rw = adrrw;
return &r;
}
void
printdollar(int modif)
{
int i;
u32int u4;
BKPT *bk;
Symbol s;
int stack;
char *fname;
char buf[512];
Regs *r;
if (cntflg==0)
cntval = -1;
switch (modif) {
case '<':
if (cntval == 0) {
while (readchar() != EOR)
;
reread();
break;
}
if (rdc() == '<')
stack = 1;
else {
stack = 0;
reread();
}
fname = getfname();
redirin(stack, fname);
break;
case '>':
fname = getfname();
redirout(fname);
break;
case 'a':
attachprocess();
break;
case 'k':
kmsys();
break;
case 'q':
case 'Q':
done();
case 'w':
maxpos=(adrflg?adrval:MAXPOS);
break;
case 'S':
printsym();
break;
case 's':
maxoff=(adrflg?adrval:MAXOFF);
break;
case 'm':
printmap("? map", symmap);
printmap("/ map", cormap);
break;
case 0:
case '?':
if (pid)
dprint("pid = %d\n",pid);
else
prints("no process\n");
flushbuf();
case 'r':
case 'R':
printregs(modif);
return;
case 'f':
case 'F':
printfp(cormap, modif);
return;
case 'c':
case 'C':
tracetype = modif;
if (adrflg)
r = adrregs();
else
r = correg;
if(stacktrace(cormap, correg, ptrace) <= 0)
error("no stack frame");
break;
/*print externals*/
case 'e':
for (i = 0; indexsym(i, &s)>=0; i++) {
if (s.class==CDATA)
if (s.loc.type==LADDR)
if (get4(cormap, s.loc.addr, &u4) > 0)
dprint("%s/%12t%#lux\n", s.name, (ulong)u4);
}
break;
/*print breakpoints*/
case 'b':
case 'B':
for (bk=bkpthead; bk; bk=bk->nxtbkpt)
if (bk->flag) {
symoff(buf, 512, (WORD)bk->loc, CTEXT);
dprint(buf);
if (bk->count != 1)
dprint(",%d", bk->count);
dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
}
break;
case 'M':
fname = getfname();
if (machbyname(fname) == 0)
dprint("unknown name\n");;
break;
default:
error("bad `$' command");
}
}
char *
getfname(void)
{
static char fname[ARB];
char *p;
if (rdc() == EOR) {
reread();
return (0);
}
p = fname;
do {
*p++ = lastc;
if (p >= &fname[ARB-1])
error("filename too long");
} while (rdc() != EOR);
*p = 0;
reread();
return (fname);
}
static void
printfp(Map *map, int modif)
{
Regdesc *rp;
int i;
int ret;
char buf[512];
for (i = 0, rp = mach->reglist; rp->name; rp += ret) {
ret = 1;
if (!(rp->flags&RFLT))
continue;
ret = fpformat(map, rp, buf, sizeof(buf), modif);
if (ret < 0) {
werrstr("Register %s: %r", rp->name);
error("%r");
}
/* double column print */
if (i&0x01)
dprint("%40t%-8s%-12s\n", rp->name, buf);
else
dprint("\t%-8s%-12s", rp->name, buf);
i++;
}
}
void
redirin(int stack, char *file)
{
char pfile[ARB];
if (file == 0) {
iclose(-1, 0);
return;
}
iclose(stack, 0);
if ((infile = open(file, 0)) < 0) {
strcpy(pfile, Ipath);
strcat(pfile, "/");
strcat(pfile, file);
if ((infile = open(pfile, 0)) < 0) {
infile = STDIN;
error("cannot open");
}
}
}
void
printmap(char *s, Map *map)
{
int i;
if (!map)
return;
if (map == symmap)
dprint("%s%12t`%s'\n", s, symfil==nil ? "-" : symfil);
else if (map == cormap)
dprint("%s%12t`%s'\n", s, corfil==nil ? "-" : corfil);
else
dprint("%s\n", s);
for (i = 0; i < map->nseg; i++) {
dprint("%s%8t%-16#lux %-16#lux %-16#lux %s\n", map->seg[i].name,
map->seg[i].base, map->seg[i].base+map->seg[i].size, map->seg[i].offset,
map->seg[i].file ? map->seg[i].file : "");
}
}
/*
* dump the raw symbol table
*/
void
printsym(void)
{
int i;
Symbol *sp, s;
for (i=0; indexsym(i, &s)>=0; i++){
sp = &s;
switch(sp->type) {
case 't':
case 'l':
dprint("%8#lux t %s\n", sp->loc.addr, sp->name);
break;
case 'T':
case 'L':
dprint("%8#lux T %s\n", sp->loc.addr, sp->name);
break;
case 'D':
case 'd':
case 'B':
case 'b':
case 'a':
case 'p':
case 'm':
dprint("%8#lux %c %s\n", sp->loc.addr, sp->type, sp->name);
break;
default:
break;
}
}
}
#define STRINGSZ 128
/*
* print the value of dot as file:line
*/
void
printsource(long dot)
{
char str[STRINGSZ];
if (fileline(dot, str, STRINGSZ) >= 0)
dprint("%s", str);
}
void
printpc(void)
{
char buf[512];
ulong u;
if(rget(correg, mach->pc, &u) < 0)
error("%r");
dot = u;
if(dot){
printsource((long)dot);
printc(' ');
symoff(buf, sizeof(buf), (long)dot, CTEXT);
dprint("%s/", buf);
if (mach->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
error("%r");
dprint("%16t%s\n", buf);
}
}
void
printlocals(Symbol *fn, Regs *regs)
{
int i;
u32int v;
Symbol s;
for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
if (s.class != CAUTO)
continue;
if(lget4(cormap, correg, s.loc, &v) >= 0)
dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, v);
else
dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
}
}
void
printparams(Symbol *fn, Regs *regs)
{
int i;
Symbol s;
u32int v;
int first = 0;
for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
if (s.class != CPARAM)
continue;
if (first++)
dprint(", ");
if(lget4(cormap, correg, s.loc, &v) >= 0)
dprint("%s=%#lux", s.name, v);
else
dprint("%s=?", s.name);
}
}

44
src/cmd/db/regs.c Normal file
View file

@ -0,0 +1,44 @@
/*
* code to keep track of registers
*/
#include "defs.h"
#include "fns.h"
/*
* print the registers
*/
void
printregs(int c)
{
Regdesc *rp;
int i;
ulong u;
if(correg == nil){
dprint("registers not mapped\n");
return;
}
for (i = 1, rp = mach->reglist; rp->name; rp++, i++) {
if ((rp->flags & RFLT)) {
if (c != 'R')
continue;
if (rp->format == '8' || rp->format == '3')
continue;
}
rget(correg, rp->name, &u);
if(rp->format == 'Y')
dprint("%-8s %-20#llux", rp->name, (uvlong)u);
else
dprint("%-8s %-12#lux", rp->name, (ulong)u);
if ((i % 3) == 0) {
dprint("\n");
i = 0;
}
}
if (i != 1)
dprint("\n");
dprint ("%s\n", mach->exc(cormap, correg));
printpc();
}

205
src/cmd/db/runpcs.c Normal file
View file

@ -0,0 +1,205 @@
/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
BKPT *bkpthead;
BOOL bpin;
int pid;
int nnote;
int ending;
char note[NNOTE][ERRMAX];
/* service routines for sub process control */
int
runpcs(int runmode, int keepnote)
{
int rc;
BKPT *bkpt;
ADDR x;
rc = 0;
if (adrflg)
rput(correg, mach->pc, dot);
if(rget(correg, mach->pc, &dot) < 0)
error("%r");
flush();
while (--loopcnt >= 0) {
if(loopcnt != 0)
printpc();
if (runmode == SINGLE) {
bkpt = scanbkpt(dot);
if (bkpt) {
switch(bkpt->flag){
case BKPTTMP:
bkpt->flag = BKPTCLR;
break;
case BKPTSKIP:
bkpt->flag = BKPTSET;
break;
}
}
runstep(dot, keepnote);
} else {
if(rget(correg, mach->pc, &x) < 0)
error("%r");
if ((bkpt = scanbkpt(x)) != 0) {
execbkpt(bkpt, keepnote);
keepnote = 0;
}
setbp();
runrun(keepnote);
}
keepnote = 0;
delbp();
if(rget(correg, mach->pc, &dot) < 0)
error("%r");
/* real note? */
if (nnote > 0) {
keepnote = 1;
rc = 0;
continue;
}
bkpt = scanbkpt(dot);
if(bkpt == 0){
keepnote = 0;
rc = 0;
continue;
}
/* breakpoint */
if (bkpt->flag == BKPTTMP)
bkpt->flag = BKPTCLR;
else if (bkpt->flag == BKPTSKIP) {
execbkpt(bkpt, keepnote);
keepnote = 0;
loopcnt++; /* we didn't really stop */
continue;
}
else {
bkpt->flag = BKPTSKIP;
--bkpt->count;
if ((bkpt->comm[0] == EOR || command(bkpt->comm, ':') != 0)
&& bkpt->count != 0) {
execbkpt(bkpt, keepnote);
keepnote = 0;
loopcnt++;
continue;
}
bkpt->count = bkpt->initcnt;
}
rc = 1;
}
return(rc);
}
/*
* finish the process off;
* kill if still running
*/
void
endpcs(void)
{
BKPT *bk;
if(ending)
return;
ending = 1;
if (pid) {
if(pcsactive){
killpcs();
pcsactive = 0;
}
pid=0;
nnote=0;
for (bk=bkpthead; bk; bk = bk->nxtbkpt)
if (bk->flag == BKPTTMP)
bk->flag = BKPTCLR;
else if (bk->flag != BKPTCLR)
bk->flag = BKPTSET;
}
bpin = FALSE;
ending = 0;
}
/*
* start up the program to be debugged in a child
*/
void
setup(void)
{
nnote = 0;
startpcs();
bpin = FALSE;
pcsactive = 1;
}
/*
* skip over a breakpoint:
* remove breakpoints, then single step
* so we can put it back
*/
void
execbkpt(BKPT *bk, int keepnote)
{
runstep(bk->loc, keepnote);
bk->flag = BKPTSET;
}
/*
* find the breakpoint at adr, if any
*/
BKPT *
scanbkpt(ADDR adr)
{
BKPT *bk;
for (bk = bkpthead; bk; bk = bk->nxtbkpt)
if (bk->flag != BKPTCLR && bk->loc == adr)
break;
return(bk);
}
/*
* remove all breakpoints from the process' address space
*/
void
delbp(void)
{
BKPT *bk;
if (bpin == FALSE || pid == 0)
return;
for (bk = bkpthead; bk; bk = bk->nxtbkpt)
if (bk->flag != BKPTCLR)
bkput(bk, 0);
bpin = FALSE;
}
/*
* install all the breakpoints
*/
void
setbp(void)
{
BKPT *bk;
if (bpin == TRUE || pid == 0)
return;
for (bk = bkpthead; bk; bk = bk->nxtbkpt)
if (bk->flag != BKPTCLR)
bkput(bk, 1);
bpin = TRUE;
}

145
src/cmd/db/setup.c Normal file
View file

@ -0,0 +1,145 @@
/*
* init routines
*/
#include "defs.h"
#include "fns.h"
char *symfil;
char *corfil;
Map *symmap;
Map *cormap;
Regs *correg;
Map *dotmap;
void
setsym(void)
{
if(symhdr && syminit(symhdr) < 0)
dprint("syminit: %r\n");
/*
Symbol s;
if (mach->sbreg && lookup(0, mach->sbreg, &s) < 0)
mach->sb = s.loc.addr;
*/
}
void
setcor(void)
{
unmapproc(cormap);
unmapfile(corhdr, cormap);
free(correg);
correg = nil;
if (pid > 0) {
if (mapproc(pid, cormap, &correg) < 0)
dprint("mapproc %d: %r\n", pid);
} else {
if (corhdr) {
if (mapfile(corhdr, 0, cormap, &correg) < 0)
dprint("mapfile %s: %r\n", corfil);
} else
dprint("no core image\n");
}
kmsys();
return;
}
Map*
dumbmap(int fd)
{
Map *dumb;
Seg s;
dumb = allocmap();
memset(&s, 0, sizeof s);
s.fd = fd;
s.base = 0;
s.offset = 0;
s.size = 0xFFFFFFFF;
s.name = "data";
s.file = "<dumb>";
if(addseg(dumb, s) < 0){
freemap(dumb);
return nil;
}
if(mach == nil)
mach = machcpu;
return dumb;
}
/*
* set up maps for a direct process image (/proc)
*/
void
cmdmap(Map *map)
{
int i;
char name[MAXSYM];
rdc();
readsym(name);
i = findseg(map, name, nil);
if (i < 0) /* not found */
error("Invalid map name");
if (expr(0)) {
// if (strcmp(name, "text") == 0)
// textseg(expv, &fhdr);
map->seg[i].base = expv;
} else
error("Invalid base address");
if (expr(0))
map->seg[i].size = expv - map->seg[i].base;
else
error("Invalid end address");
if (expr(0))
map->seg[i].offset = expv;
else
error("Invalid file offset");
/*
if (rdc()=='?' && map == cormap) {
if (fcor)
close(fcor);
fcor=fsym;
corfil = symfil;
cormap = symmap;
} else if (lastc == '/' && map == symmap) {
if (fsym)
close(fsym);
fsym=fcor;
symfil=corfil;
symmap=cormap;
} else
reread();
*/
}
void
kmsys(void)
{
int i;
i = findseg(symmap, "text", symfil);
if (i >= 0) {
symmap->seg[i].base = symmap->seg[i].base&~mach->ktmask;
symmap->seg[i].size = -symmap->seg[i].base;
}
i = findseg(symmap, "data", symfil);
if (i >= 0) {
symmap->seg[i].base = symmap->seg[i].base&~mach->ktmask;
symmap->seg[i].size = -symmap->seg[i].base;
}
}
void
attachprocess(void)
{
if (!adrflg) {
dprint("used pid$a\n");
return;
}
pid = adrval;
setcor();
}

288
src/cmd/db/trcrun.c Normal file
View file

@ -0,0 +1,288 @@
/*
* functions for running the debugged process
*/
#include "defs.h"
#include "fns.h"
int child;
int msgfd = -1;
int notefd = -1;
int pcspid = -1;
int pcsactive = 0;
void
setpcs(void)
{
char buf[128];
if(pid && pid != pcspid){
if(msgfd >= 0){
close(msgfd);
msgfd = -1;
}
if(notefd >= 0){
close(notefd);
notefd = -1;
}
pcspid = -1;
sprint(buf, "/proc/%d/ctl", pid);
msgfd = open(buf, OWRITE);
if(msgfd < 0)
error("can't open control file");
sprint(buf, "/proc/%d/note", pid);
notefd = open(buf, ORDWR);
if(notefd < 0)
error("can't open note file");
pcspid = pid;
}
}
void
msgpcs(char *msg)
{
char err[ERRMAX];
setpcs();
if(write(msgfd, msg, strlen(msg)) < 0 && !ending){
errstr(err, sizeof err);
if(strcmp(err, "interrupted") != 0)
endpcs();
errors("can't write control file", err);
}
}
/*
* empty the note buffer and toss pending breakpoint notes
*/
void
unloadnote(void)
{
char err[ERRMAX];
setpcs();
for(; nnote<NNOTE; nnote++){
switch(read(notefd, note[nnote], sizeof note[nnote])){
case -1:
errstr(err, sizeof err);
if(strcmp(err, "interrupted") != 0)
endpcs();
errors("can't read note file", err);
case 0:
return;
}
note[nnote][ERRMAX-1] = '\0';
if(strncmp(note[nnote], "sys: breakpoint", 15) == 0)
--nnote;
}
}
/*
* reload the note buffer
*/
void
loadnote(void)
{
int i;
char err[ERRMAX];
setpcs();
for(i=0; i<nnote; i++){
if(write(notefd, note[i], strlen(note[i])) < 0){
errstr(err, sizeof err);
if(strcmp(err, "interrupted") != 0)
endpcs();
errors("can't write note file", err);
}
}
nnote = 0;
}
void
notes(void)
{
int n;
if(nnote == 0)
return;
dprint("notes:\n");
for(n=0; n<nnote; n++)
dprint("%d:\t%s\n", n, note[n]);
}
void
killpcs(void)
{
msgpcs("kill");
}
void
grab(void)
{
flush();
msgpcs("stop");
bpwait();
}
void
ungrab(void)
{
msgpcs("start");
}
void
doexec(void)
{
char *argl[MAXARG];
char args[LINSIZ];
char *p;
char **ap;
char *thisarg;
ap = argl;
p = args;
*ap++ = symfil;
for (rdc(); lastc != EOR;) {
thisarg = p;
if (lastc == '<' || lastc == '>') {
*p++ = lastc;
rdc();
}
while (lastc != EOR && lastc != SPC && lastc != TB) {
*p++ = lastc;
readchar();
}
if (lastc == SPC || lastc == TB)
rdc();
*p++ = 0;
if (*thisarg == '<') {
close(0);
if (open(&thisarg[1], OREAD) < 0) {
print("%s: cannot open\n", &thisarg[1]);
_exits(0);
}
}
else if (*thisarg == '>') {
close(1);
if (create(&thisarg[1], OWRITE, 0666) < 0) {
print("%s: cannot create\n", &thisarg[1]);
_exits(0);
}
}
else
*ap++ = thisarg;
}
*ap = 0;
exec(symfil, argl);
perror(symfil);
}
char procname[100];
void
startpcs(void)
{
if ((pid = fork()) == 0) {
pid = getpid();
msgpcs("hang");
doexec();
exits(0);
}
if (pid == -1)
error("can't fork");
child++;
sprint(procname, "/proc/%d/mem", pid);
corfil = procname;
msgpcs("waitstop");
bpwait();
if (adrflg)
rput(correg, mach->pc, adrval);
while (rdc() != EOR)
;
reread();
}
void
runstep(ulong loc, int keepnote)
{
int nfoll;
ulong foll[3];
BKPT bkpt[3];
int i;
if(mach->foll == 0){
dprint("stepping unimplemented; assuming not a branch\n");
nfoll = 1;
foll[0] = loc+mach->pcquant;
}else {
nfoll = mach->foll(cormap, correg, loc, foll);
if (nfoll < 0)
error("%r");
}
memset(bkpt, 0, sizeof bkpt);
for(i=0; i<nfoll; i++){
if(foll[i] == loc)
error("can't single step: next instruction is dot");
bkpt[i].loc = foll[i];
bkput(&bkpt[i], 1);
}
runrun(keepnote);
for(i=0; i<nfoll; i++)
bkput(&bkpt[i], 0);
}
void
bpwait(void)
{
setcor();
unloadnote();
}
void
runrun(int keepnote)
{
int on;
on = nnote;
unloadnote();
if(on != nnote){
notes();
error("not running: new notes pending");
}
if(keepnote)
loadnote();
else
nnote = 0;
flush();
msgpcs("startstop");
bpwait();
}
void
bkput(BKPT *bp, int install)
{
char buf[256];
ulong loc;
int ret;
errstr(buf, sizeof buf);
/*
if(mach->bpfix)
loc = (*mach->bpfix)(bp->loc);
else
*/
loc = bp->loc;
if(install){
ret = get1(cormap, loc, bp->save, mach->bpsize);
if (ret > 0)
ret = put1(cormap, loc, mach->bpinst, mach->bpsize);
}else
ret = put1(cormap, loc, bp->save, mach->bpsize);
if(ret < 0){
sprint(buf, "can't set breakpoint at %#llux: %r", bp->loc);
print(buf);
read(0, buf, 100);
}
}