debugger
This commit is contained in:
parent
a84cbb2a17
commit
84114f0665
15 changed files with 3179 additions and 0 deletions
311
src/cmd/db/command.c
Normal file
311
src/cmd/db/command.c
Normal 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
111
src/cmd/db/defs.h
Normal 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
397
src/cmd/db/expr.c
Normal 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
91
src/cmd/db/fns.h
Normal 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
388
src/cmd/db/format.c
Normal 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*)˙
|
||||
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*)˙
|
||||
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*) ˙
|
||||
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
169
src/cmd/db/input.c
Normal 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
262
src/cmd/db/main.c
Normal 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
26
src/cmd/db/mkfile
Normal 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
159
src/cmd/db/output.c
Normal 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
177
src/cmd/db/pcs.c
Normal 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
406
src/cmd/db/print.c
Normal 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
44
src/cmd/db/regs.c
Normal 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
205
src/cmd/db/runpcs.c
Normal 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
145
src/cmd/db/setup.c
Normal 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
288
src/cmd/db/trcrun.c
Normal 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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue