USG_PG3/usr/source/adb/adb1.c
#
/*
*
* UNIX debugger - part 1
*
*/
#include "adb.h"
int wtflag;
int fcor;
int fsym;
long maxfile;
long maxstor;
long txtsiz;
long datsiz;
long stksiz;
INT outfile 1;
int errflg;
int exitflg;
int magic;
long symbas;
long symnum;
long localval;
int entrypt;
char isymbol[8];
int signo;
char lastc EOR;
INT eof;
char eqformat[128] "o";
char stformat[128] "o\"= \"^i";
int regbuf[512];
int *uregs;
long dot;
long ditto;
int dotinc;
int lastcom '=';
long var[36];
long locval;
long locmsk;
char *symfil "a.out";
char *corfil "core";
int pid;
long expv;
long adrval;
int adrflg;
long cntval;
int cntflg;
char printbuf[];
char *printptr;
char * errmsg[] {
"",
"bad modifier",
"bad command",
"symbol not found",
"c routine not found",
"cannot locate value",
"no breakpoint set",
"unexpected ')'",
"address expected",
"no process",
"bad variable",
"text address not found",
"data address not found",
"odd address",
"too many breakpoints",
"bad a68 frame",
"bad a68 link",
"address wrap around",
"unexpected `='",
"wait error: process disappeared!",
"process terminated",
"try again",
"syntax error",
"newline expected",
"bkpt: command too long",
"bad file format",
"not enough space for symbols",
"filename too long",
"cannot open",
};
long round(a,b) long a; long b;
{
long w;
w = (a/b)*b;
IF a>0 THEN w =+ b; FI
return(w);
}
/* error handling */
error(n)
{
errflg=n;
iclose(); oclose();
reset();
}
fault(a)
{
signal(a,fault);
printptr=printbuf;
seek(infile,0,2);
mkfault++;
}
/* set up files and initial address mappings */
int argcount;
int devmem, devswap;
main(argc, argv)
char **argv; int argc;
{
maxfile=1; maxfile =<< 24;
maxstor=1; maxstor =<< 16;
WHILE argc>1
DO IF eqstr("-w",argv[1])
THEN wtflag=2; argc--; argv++;
ELSE break;
FI
OD
IF argc>1 THEN symfil = argv[1]; FI
IF argc>2 THEN corfil = argv[2]; FI
argcount=argc;
setsym(); setcor(); setproc();
/* set up variables for user */
maxoff=MAXOFF; maxpos=MAXPOS;
var[VARB] = datmap.b1;
var[VARD] = datsiz;
var[VARE] = leng(entrypt);
var[VARM] = magic;
var[VARS] = stksiz;
var[VART] = txtsiz;
IF (sigint=signal(SIGINT,fault))==01
THEN signal(SIGINT,1);
ELSE sigint=fault;
FI
sigqit=signal(SIGQIT,1);
setexit();
IF executing THEN delbp(); FI
executing=FALSE;
LOOP flushbuf();
IF errflg
THEN printf("%s\n",errmsg[errflg]);
exitflg=errflg;
errflg=0;
ELIF mkfault
THEN mkfault=0; prints("\nadb\n");
FI
lp=0; rdc(); lp--;
IF eof
THEN IF infile
THEN iclose(); eof=0; reset();
ELSE done();
FI
ELSE exitflg=0;
FI
command(0,lastcom);
IF lp ANDF lastc!=EOR THEN error(NOEOR); FI
POOL
}
done()
{
endpcs();
exit(exitflg);
}
setsym()
{
int relflg;
INT symval, symflg; SYMSLAVE *symptr; SYMTAB *symp;
IF !eqstr("-",symfil)
THEN fsym=open(symfil,wtflag);
IF wtflag ANDF fsym<0
THEN fsym=create(symfil);
FI
IF fsym<0 ANDF argcount>1
THEN printf("cannot open `%s'\n", symfil);
FI
ELSE fsym = -1;
FI
txtmap.ufd=fsym;
IF read(fsym, regbuf, TXTHDR)==TXTHDR
THEN magic=regbuf[0];
IF magic!=0411 ANDF magic!=0410 ANDF magic!=0407 ANDF magic!=0405
THEN magic=0;
ELSE symnum=leng(regbuf[4])/12;
txtsiz=leng(regbuf[1]);
datsiz=leng(regbuf[2]);
symbas=txtsiz+datsiz;
txtmap.b1=0;
txtmap.e1=(magic==0407?symbas:txtsiz);
txtmap.f1 = TXTHDR;
txtmap.b2=(magic==0410?round(txtsiz,leng(8192)):0);
txtmap.e2=txtmap.b2+(magic==0407?symbas:datsiz);
txtmap.f2 = TXTHDR+(magic==0407?0:txtmap.e1);
entrypt=regbuf[5];
relflg=regbuf[7];
IF relflg!=1 THEN symbas =<< 1; FI
symbas =+ TXTHDR;
/* set up symvec */
freecell(symvec);
symvec=getcell(shorten((1+symnum))*sizeof *symptr);
IF (symptr=symvec)==0
THEN error(BADNAM);
FI
symset();
WHILE (symp=symget()) ANDF errflg==0
DO symval=symp->symv; symflg=symp->symf;
symptr->valslave=symval;
symptr->typslave=((symflg&070)==(symflg&040)
? ((symflg&07)>=3 ? DSYM : (symflg&07))
: NSYM
);
symptr++;
OD
symptr->typslave=ESYM;
FI
FI
IF magic==0 THEN txtmap.e1=maxfile; FI
}
setcor()
{
IF !eqstr("-",corfil)
THEN fcor=open(corfil,wtflag);
IF fcor<0 ANDF wtflag
THEN fcor=create(corfil);
FI
IF fcor<0 ANDF argcount>2
THEN printf("cannot open `%s'\n", corfil);
FI
ELSE fcor = -1;
FI
datmap.ufd=fcor;
IF read(fcor, regbuf, CORHDR)==CORHDR
ANDF (regbuf[0]&0170000)==COREMAGIC
ANDF (regbuf[1]&0170000)==COREMAGIC
THEN signo = regbuf[0].u_arg[0]&017;
txtsiz = leng(regbuf->u_tsize << 6);
datsiz = leng(regbuf->u_dsize << 6);
stksiz = leng(regbuf->u_ssize << 6);
datmap.b1=(magic==0410?round(txtsiz,leng(8192)):0);
datmap.e1=(magic==0407?txtsiz:datmap.b1)+datsiz;
datmap.f1 = CORHDR;
datmap.b2 = maxstor-stksiz;
datmap.e2 = maxstor;
datmap.f2 = CORHDR+(magic==0410?datsiz:datmap.e1);
ELSE datmap.e1 = maxfile;
FI
}
create(f)
char *f;
{ int fd;
IF (fd=creat(f,0644))>=0
THEN close(fd); return(open(f,wtflag));
ELSE return(-1);
FI
}
/* input routines */
eol(c)
char c;
{
return(c==EOR ORF c==';');
}
rdc()
{ REP readchar();
PER lastc==SP ORF lastc==TB
DONE
return(lastc);
}
readchar()
{
IF eof
THEN lastc=EOF;
ELSE IF lp==0
THEN lp=line;
REP eof = read(infile,lp,1)==0;
IF mkfault THEN error(0); FI
PER eof==0 ANDF *lp++!=EOR DONE
*lp=0; lp=line;
FI
IF lastc = *lp THEN lp++; FI
FI
return(lastc);
}
nextchar()
{
IF eol(rdc())
THEN lp--; return(0);
ELSE return(lastc);
FI
}
quotchar()
{
IF readchar()=='\\'
THEN return(readchar());
ELIF lastc=='\''
THEN return(0);
ELSE return(lastc);
FI
}
getformat(deformat)
{
register char *fptr, quote;
fptr=deformat; quote=FALSE;
WHILE (quote ? readchar()!=EOR : !eol(readchar()))
DO IF (*fptr++ = lastc)=='"'
THEN quote = ~quote;
FI
OD
lp--;
IF fptr!=deformat THEN *fptr++ = '\0'; FI
}
/* command decoding */
long inkdot(incr)
{
long newdot; newdot=dot+incr;
IF (dot NEQ newdot) >> 24 THEN error(ADRWRAP); FI
return(newdot);
}
long dekdot(decr)
{
long newdot; newdot=dot-decr;
IF (dot NEQ newdot) >> 24 THEN error(ADRWRAP); FI
return(newdot);
}
endline()
{
IF charpos()>=maxpos
THEN printf("\n");
FI
}
command(buf,defcom)
char *buf, defcom;
{
INT itype, ptype, modifier, regptr;
INT fcount;
BOOL longpr, eqcom; char wformat[1]; CHAR savc;
long *amap, *smap, w, savdot;
char *savlp; savlp=lp;
IF buf
THEN IF *buf==EOR
THEN return(FALSE);
ELSE lp=buf;
FI
FI
REP
IF adrflg=expr(0)
THEN dot=expv; ditto=dot;
FI
adrval=dot;
IF rdc()==',' ANDF expr(0)
THEN cntflg=TRUE; cntval=expv;
ELSE cntflg=FALSE; cntval=1; lp--;
FI
IF !eol(rdc())
THEN lastcom=lastc;
ELSE IF adrflg==0 THEN dot=inkdot(dotinc); FI
lp--; lastcom=defcom;
FI
switch(lastcom&STRIP) {
case '/':
itype=DSP; ptype=DSYM;
goto trystar;
case '=':
itype=NSP; ptype=ASYM;
goto trypr;
case '?':
itype=ISP; ptype=ISYM;
goto trystar;
trystar:
IF rdc()=='*' THEN lastcom =| QUOTE; ELSE lp--; FI
IF lastcom"E
THEN itype =| STAR; ptype = (DSYM+ISYM)-ptype;
FI
trypr:
longpr=FALSE; eqcom=lastcom=='=';
switch (rdc()) {
case 'm':
{/*reset map data*/
IF eqcom THEN error(BADEQ); FI
amap=(itype&DSP?&datmap:&txtmap);
smap=amap; fcount=3;
IF itype&STAR
THEN amap =+ 3;
FI
WHILE fcount-- ANDF expr(0)
DO *amap++ = expv; OD
IF rdc()=='?' THEN smap->ufd=fsym;
ELIF lastc == '/' THEN smap->ufd=fcor;
ELSE lp--;
FI
printmap("new map",smap);
}
EXITSW;
case 'L':
longpr=TRUE;
case 'l':
/*search for exp*/
IF eqcom THEN error(BADEQ); FI
dotinc=2; savdot=dot;
expr(1); locval=expv;
IF expr(0) THEN locmsk=expv; ELSE locmsk = (longpr?-1:leng(-1)); FI
LOOP w=leng(get(dot,itype));
IF longpr
THEN w=itol(w,get(inkdot(2),itype));
FI
IF errflg ORF (w&locmsk)==locval THEN break; FI
dot=inkdot(dotinc);
POOL
IF errflg
THEN dot=savdot; errflg=NOMATCH;
FI
psymoff(dot,ptype,"");
EXITSW;
case 'W':
longpr=TRUE;
case 'w':
IF eqcom THEN error(BADEQ); FI
wformat[0]=lastc; expr(1);
LOOP savdot=dot; psymoff(dot,ptype,":%16t"); exform(1,wformat,itype,ptype);
errflg=0; dot=savdot;
IF longpr
THEN put(dot,itype,expv);
FI
put((longpr?inkdot(2):dot),itype,shorten(expv));
savdot=dot;
printf("=%8t"); exform(1,wformat,itype,ptype);
IF expr(0)==0 ORF errflg THEN break; FI
POOL
dot=savdot;
EXITSW;
default:
lp--;
getformat(eqcom ? eqformat : stformat);
IF !eqcom
THEN psymoff(dot,ptype,":%16t");
FI
scanform(cntval,(eqcom?eqformat:stformat),itype,ptype,1);
}
EXITSW;
case '>':
lastcom=0; savc=rdc();
IF regptr=getreg(savc)
THEN uregs[regptr]=shorten(dot);
ptrace(WUREGS,pid,2*(512+regptr),uregs[regptr]);
ELIF (modifier=varchk(savc)) != -1
THEN var[modifier]=dot;
ELSE error(BADVAR);
FI
EXITSW;
case '!':
lastcom=0;
unix(); EXITSW;
case '$':
lastcom=0;
printtrace(nextchar()); EXITSW;
case ':':
IF !executing
THEN executing=TRUE;
subpcs(nextchar());
executing=FALSE;
lastcom=0;
FI
EXITSW;
case 0:
prints("adb");
EXITSW;
default: error(BADCOM);
}
flushbuf();
PER rdc()==';' DONE
IF buf THEN lp=savlp; ELSE lp--; FI
return(adrflg ANDF dot!=0);
}
scanform(icount,ifp,itype,ptype,init)
long int icount;
{
CHAR *fp, modifier;
INT fcount;
long savdot;
WHILE icount
DO fp=ifp;
IF init==0 ANDF findsym(shorten(dot),ptype)==0 ANDF maxoff
THEN printf("\n%.8s:%16t",symbol.symc);
FI
savdot=dot; init=0;
/*now loop over format*/
WHILE *fp ANDF errflg==0
DO IF digit(modifier = *fp)
THEN fcount=0;
WHILE digit(modifier = *fp++)
DO fcount =* 10;
fcount =+ modifier-'0';
OD
fp--;
ELSE fcount=1;
FI
IF *fp==0 THEN break; FI
fp=exform(fcount,fp,itype,ptype);
OD
dotinc=dot-savdot;
dot=savdot;
IF errflg
THEN IF icount<0
THEN errflg=0; break;
ELSE error(errflg);
FI
FI
IF --icount
THEN dot=inkdot(dotinc);
FI
IF mkfault THEN error(0); FI
OD
}
exform(fcount,ifp,itype,ptype)
INT fcount; char *ifp; int itype, ptype;
{
/* execute single format item `fcount' times
* sets `dotinc' and moves `dot'
* returns address of next format item
*/
int w;
long savdot, wx;
char *fp; char c, modifier, longpr;
double fw; struct{long sa; int sb, sc;};
WHILE fcount>0
DO fp = ifp; c = *fp;
longpr=(c>='A')&(c<='Z')|(c=='f');
IF itype==NSP ORF *fp=='a'
THEN wx=dot; w=shorten(dot);
ELSE w=get(dot,itype);
IF longpr
THEN wx=itol(w,get(inkdot(2),itype));
ELSE wx=leng(w);
FI
FI
IF c=='F'
THEN fw.sb=get(inkdot(4),itype);
fw.sc=get(inkdot(6),itype);
FI
IF errflg THEN return(fp); FI
IF mkfault THEN error(0); FI
var[0]=wx;
modifier = *fp++;
dotinc=(longpr?4:2);;
IF charpos()==0 ANDF modifier!='a' THEN printf("%16m"); FI
switch(modifier) {
case SP: case TB:
EXITSW;
case 't': case 'T':
printf("%T",fcount); return(fp);
case 'r': case 'R':
printf("%M",fcount); return(fp);
case 'a':
psymoff(dot,ptype,":%16t"); dotinc=0; EXITSW;
case 'p':
psymoff(var[0],ptype,"%16t"); EXITSW;
case 'u':
printf("%-8u",w); EXITSW;
case 'U':
printf("%-16U",wx); EXITSW;
case 'c': case 'C':
IF modifier=='C'
THEN printesc(w&LOBYTE);
ELSE printc(w&LOBYTE);
FI
dotinc=1; EXITSW;
case 'b': case 'B':
printf("%-8o", w&LOBYTE); dotinc=1; EXITSW;
case 's': case 'S':
savdot=dot; dotinc=1;
WHILE (c=get(dot,itype)&LOBYTE) ANDF errflg==0
DO dot=inkdot(1);
IF modifier == 'S'
THEN printesc(c);
ELSE printc(c);
FI
endline();
OD
dotinc=dot-savdot+1; dot=savdot; EXITSW;
case 'x':
printf("%-8x",w); EXITSW;
case 'X':
printf("%-16X", wx); EXITSW;
case 'Y':
printf("%-24Y", wx); EXITSW;
case 'q':
printf("%-8q", w); EXITSW;
case 'Q':
printf("%-16Q", wx); EXITSW;
case 'o':
case 'w':
printf("%-8o", w); EXITSW;
case 'O':
case 'W':
printf("%-16O", wx); EXITSW;
case 'i': case 'I':
dotinc=printins(0,itype,w); printc(EOR); EXITSW;
case 'd':
printf("%-8d", w); EXITSW;
case 'D':
printf("%-16D", wx); EXITSW;
case 'f':
fw = 0;
fw.sa = wx;
printf("%-16.7f", fw);
dotinc=4; EXITSW;
case 'F':
fw.sa = wx;
printf("%-32.14F", fw);
dotinc=8; EXITSW;
case 'n': case 'N':
printc('\n'); dotinc=0; EXITSW;
case '"':
dotinc=0;
WHILE *fp != '"' ANDF *fp
DO printc(*fp++); OD
IF *fp THEN fp++; FI
EXITSW;
case '^':
dot=dekdot(dotinc*fcount); return(fp);
case '+':
dot=inkdot(fcount); return(fp);
case '-':
dot=dekdot(fcount); return(fp);
default: error(BADFMT);
}
dot=inkdot(dotinc);
fcount--; endline();
OD
return(fp);
}
unix()
{
int rc, status, unixpid;
char *argp; argp=lp;
WHILE lastc!=EOR DO rdc(); OD
IF (unixpid=fork())==0
THEN signal(SIGINT,sigint); signal(SIGQIT,sigqit);
close(devmem); close(devswap);
*lp=0; execl("/bin/sh", "-sh", "-c", argp, 0);
exit(16);
ELIF unixpid == -1
THEN error(NOFORK);
ELSE signal(SIGINT,1);
WHILE (rc = wait(&status)) != unixpid ANDF rc != -1 DONE
signal(SIGINT,sigint);
prints("!"); lp--;
FI
}
printesc(c)
{
c =& STRIP;
IF c<SP ORF c>'~' ORF c=='@'
THEN printf("@%c",(c=='@' ? '@' : c^0140));
ELSE printc(c);
FI
}
/* expression reading */
expr(a)
{ /* term | term dyadic expr | */
int rc; long lhs;
rdc(); lp--; rc=term(a);
WHILE rc
DO lhs = expv;
switch (readchar()) {
case '+':
term(a|1); expv =+ lhs; EXITSW;
case '-':
term(a|1); expv = lhs - expv; EXITSW;
case '#':
term(a|1); expv = round(lhs,expv); EXITSW;
case '*':
term(a|1); expv =* lhs; EXITSW;
case '%':
term(a|1); expv = lhs/expv; EXITSW;
case '&':
term(a|1); expv =& lhs; EXITSW;
case '|':
term(a|1); expv =| lhs; EXITSW;
case ')':
IF (a&2)==0 THEN error(BADKET); FI
default:
lp--;
return(rc);
}
OD
return(rc);
}
term(a)
{ /* item | monadic item | (expr) | */
switch (readchar()) {
case '*':
term(a|1); expv=leng(chkget(expv,DSP)); return(1);
case '@':
term(a|1); expv=leng(chkget(expv,ISP)); return(1);
case '-':
term(a|1); expv = -expv; return(1);
case '~':
term(a|1); expv = ~expv; return(1);
case '(':
expr(2);
IF *lp!=')'
THEN error(BADSYN);
ELSE lp++; return(1);
FI
default:
lp--;
return(item(a));
}
}
item(a)
{ /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
INT base, d, frpt, regptr; CHAR savc; BOOL hex;
long frame;
double real;
struct symtab *symp;
hex=FALSE;
readchar();
IF symchar(0)
THEN readsym();
IF lastc=='.'
THEN frame=leng(uregs[r5])&EVEN; lastframe=0; callpc=uregs[pc];
WHILE errflg==0
DO findroutine(frame);
IF eqstr(symbol.symc,isymbol)
THEN break;
FI
lastframe=frame;
frame=leng(get(frame,DSP))&EVEN;
IF frame==0
THEN error(NOCRTN);
FI
OD
expv=frame; readchar();
IF symchar(0)
THEN readsym();
REP IF localsym(frame)==0 THEN error(BADSYM); FI
expv=localval;
PER !eqstr(symbol.symc,isymbol) DONE
FI
ELIF (symp=lookupsym(isymbol))==0 THEN error(BADSYM);
ELSE expv = leng(symp->symv);
FI
lp--;
ELIF digit(lastc) ORF (hex=TRUE, lastc=='#' ANDF hexdigit(readchar()))
THEN expv = 0;
base = (lastc == '0' ORF octal ? 8 : (hex ? 16 : 10));
WHILE (hex ? hexdigit(lastc) : digit(lastc))
DO expv =* base;
IF (d=convdig(lastc))>=base THEN error(BADSYN); FI
expv =+ d; readchar();
OD
IF lastc=='.' ANDF (base==10 ORF expv==0) ANDF !hex
THEN real=expv; frpt=0; base=10;
WHILE digit(readchar())
DO real =* base; frpt++;
real =+ lastc-'0';
OD
WHILE frpt--
DO real =/ base; OD
expv=ltor(real);
FI
lp--;
ELIF lastc=='.'
THEN expv=dot;
ELIF lastc=='"'
THEN expv=ditto;
ELIF lastc=='+'
THEN expv=inkdot(dotinc);
ELIF lastc=='^'
THEN expv=dekdot(dotinc);
ELIF lastc=='<'
THEN savc=rdc();
IF regptr=getreg(savc)
THEN expv=leng(uregs[regptr]);
ELIF (base=varchk(savc)) != -1
THEN expv=var[base];
ELSE error(BADVAR);
FI
ELIF lastc=='\''
THEN d=4; expv=0;
WHILE quotchar()
DO IF d--
THEN IF d==1 THEN expv =<<16; FI
expv =| ((d&1)?lastc:lastc<<8);
ELSE error(BADSYN);
FI
OD
ELIF a
THEN error(NOADR);
ELSE lp--; return(0);
FI
return(1);
}
/* service routines for expression reading */
readsym()
{
register char *p;
p = isymbol;
REP IF p < &isymbol[8]
THEN *p++ = lastc;
FI
readchar();
PER symchar(1) DONE
WHILE p < &isymbol[8] DO *p++ = 0; OD
}
lookupsym(symstr)
char *symstr;
{
struct symtab *symp;
symset();
WHILE symp=symget()
DO IF eqstr(symp->symc, symstr)
THEN return(symp);
FI
OD
return(0);
}
hexdigit(c)
CHAR c;
{ return((c>='0' ANDF c<='9') ORF (c>='a' ANDF c<='f'));
}
convdig(c)
CHAR c;
{
IF digit(c)
THEN return(c-'0');
ELIF hexdigit(c)
THEN return(c-'a'+10);
ELSE return(17);
FI
}
digit(c) char c; {return(c>='0' ANDF c<='9');}
letter(c) char c; {return(c>='a' ANDF c<='z' ORF c>='A' ANDF c<='Z');}
symchar(dig)
{
IF lastc=='\\' THEN readchar(); return(TRUE); FI
return( letter(lastc) ORF lastc=='_' ORF dig ANDF digit(lastc) );
}
varchk(name)
{
IF digit(name) THEN return(name-'0'); FI
IF letter(name) THEN return((name&037)-1+10); FI
return(-1);
}