USG_PG3/usr/source/adb/adb2.c
#
/*
*
* UNIX debugger part 2
*
*/
#include "../head/proc.h"
#include "adb.h"
INT outfile;
INT infile;
/* symbol management */
long symbas;
long symcnt;
long symnum;
long localval;
char symrqd -1;
SYMTAB symbuf[SYMSIZ];
SYMTAB *symnxt;
SYMTAB *symend;
/* breakpoints */
#define BKPT struct bkpt
BKPT {
int loc;
int ins;
int count;
int initcnt;
int flag;
char comm[MAXCOM];
BKPT *nxtbkpt;
} *bkpthead;
#define REGLIST struct reglist
REGLIST {
char *rname;
int roffs;
} reglist[] {
"ps", ps,
"pc", pc,
"sp", sp,
"r5", r5,
"r4", r4,
"r3", r3,
"r2", r2,
"r1", r1,
"r0", r0,
};
#define SFREGS struct sfregs
SFREGS {
int junk[2];
int fpsr;
float sfr[6];
};
#define LFREGS struct lfregs
LFREGS {
int junk[2];
int fpsr;
double lfr[6];
};
#define FROFF (&(0->fpsr))
#define FRLEN 25
#define FRMAX 6
INT frnames[] { 0, 3, 4, 5, 1, 2 };
INT fault();
long inkdot();
char lastc;
INT regbuf[512];
INT *uregs ®buf[512];
INT fcor;
INT fsym;
INT errflg;
INT errno;
INT signo;
int devswap -1;
int swapblk;
int proctab;
int devmem -1;
long dot;
long var[36];
char *symfil;
char *corfil;
int wtflag;
INT pid;
long expv;
long adrval;
INT adrflg;
long cntval;
long loopcnt;
INT cntflg;
char *signals[] {
"",
"hangup",
"interrupt",
"quit",
"illegal instruction",
"trace/BPT",
"IOT",
"EMT",
"floating exception",
"killed",
"bus error",
"memory fault",
"bad system call",
"broken pipe",
"alarm call",
"terminated",
};
/* general printing routines ($) */
printtrace(modif)
{
INT narg, i, stat, dynam, name, limit;
CHAR file[64];
INT index;
REG BKPT *bkptr;
CHAR hi, lo; INT word;
CHAR *comptr;
long argp, frame, link;
SYMTAB *symp;
IF cntflg==0 THEN cntval = -1; FI
switch (modif) {
case '<':
case '>':
{
index=0;
IF rdc()==EOR
THEN IF modif=='<'
THEN iclose();
ELSE oclose();
FI
ELSE REP file[index++]=lastc;
IF index>=63 THEN error(LONGFIL); FI
PER readchar()!=EOR DONE
file[index]=0;
IF modif=='<'
THEN infile=open(file,0);
IF infile<0
THEN infile=0; error(NOTOPEN);
FI
ELSE outfile=open(file,1);
IF outfile<0
THEN outfile=creat(file,0644);
ELSE seek(outfile,0,2);
FI
FI
FI
lp--;
}
break;
case 'o':
octal = TRUE; EXITSW;
case 'd':
octal = FALSE; EXITSW;
case 'q': case 'Q':
done();
case 'w': case 'W':
maxpos=(adrflg?adrval:MAXPOS);
EXITSW;
case 's': case 'S':
maxoff=(adrflg?adrval:MAXOFF);
EXITSW;
case 'v': case 'V':
prints("variables\n");
FOR i=0;i<=35;i++
DO IF var[i]
THEN printc((i<=9 ? '0' : 'a'-10) + i);
printf(" = %Q\n",var[i]);
FI
OD
EXITSW;
case 'm': case 'M':
printmap("text map",&txtmap);
printmap("data map",&datmap);
EXITSW;
case 0: case '?':
IF pid
THEN printf("pcs id = %d\n",pid);
ELSE prints("no process\n");
FI
printf("%s",signals[signo]); flushbuf();
case 'r': case 'R':
printregs();
return;
case 'f': case 'F':
printfregs(modif=='F');
return;
case 'c': case 'C':
frame=(adrflg?adrval:leng(uregs[r5]))&EVEN; lastframe=0; callpc=uregs[pc];
WHILE mkfault==0 ANDF errflg==0 ANDF cntval--
DO narg = findroutine(frame);
printf("%.8s(", symbol.symc);
argp = frame+4;
IF --narg >= 0
THEN printf("%o", get(argp, DSP));
FI
WHILE --narg >= 0
DO argp =+ 2;
printf(",%o", get(argp, DSP));
OD
prints(")\n");
IF modif=='C'
THEN WHILE localsym(frame)
DO word=get(localval,DSP);
printf("%8t%.8s:%10t", symbol.symc);
IF errflg THEN prints("?\n"); errflg=0; ELSE printf("%o\n",word); FI
OD
FI
lastframe=frame;
frame=leng(get(frame, DSP))&EVEN;
IF frame==0 THEN break; FI
OD
EXITSW;
/*print externals*/
case 'e': case 'E':
symset();
WHILE (symp=symget()) ANDF errflg==0 ANDF mkfault==0
DO IF (symp->symf)==043 ORF (symp->symf)==044
THEN printf("%.8s:%12t%o\n", symp->symc, get(leng(symp->symv),DSP));
FI
OD
EXITSW;
case 'a': case 'A':
frame=(adrflg ? adrval : leng(uregs[r4]));
WHILE errflg==0 ANDF cntval-- ANDF mkfault==0
DO stat=get(frame,DSP); dynam=get(frame+2,DSP); link=get(frame+4,DSP);
IF modif=='A'
THEN printf("%8O:%8t%-8o,%-8o,%-8o",frame,stat,dynam,link);
FI
IF stat==1 THEN break; FI
IF errflg THEN error(A68FRAME); FI
IF get(link-4,ISP)!=04767
THEN IF get(link-2,ISP)!=04775
THEN error(A68LINK);
ELSE /*compute entry point of routine*/
prints(" ? ");
FI
ELSE printf("%8t");
valpr(name=shorten(link)+get(link-2,ISP),ISYM);
name=get(leng(name-2),ISP);
printf("%8t\""); limit=8;
REP word=get(leng(name),DSP); name =+ 2;
lo=word&LOBYTE; hi=(word>>8)&LOBYTE;
printc(lo); printc(hi);
PER lo ANDF hi ANDF limit-- DONE
printc('"');
FI
limit=4; i=6; printf("%24targs:%8t");
WHILE limit--
DO printf("%8t%o",get(frame+i,DSP)); i =+ 2; OD
printc(EOR);
frame=leng(dynam);
OD
errflg=0;
flushbuf();
EXITSW;
/*set default c frame*/
/*print breakpoints*/
case 'b': case 'B':
printf("breakpoints\ncount%8tbkpt%24tcommand\n");
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN printf("%-8.8d",bkptr->count);
psymoff(leng(bkptr->loc),ISYM,"%24t");
comptr=bkptr->comm;
WHILE *comptr DO printc(*comptr++); OD
FI
OD
EXITSW;
default: error(BADMOD);
}
}
printmap(s,amap)
char *s; MAP *amap;
{
int file;
file=amap->ufd;
printf("%s%12t`%s'\n",s,(file<0 ? "-" : (file==fcor ? corfil : symfil)));
printf("b1 = %-16Q",amap->b1);
printf("e1 = %-16Q",amap->e1);
printf("f1 = %-16Q",amap->f1);
printf("\nb2 = %-16Q",amap->b2);
printf("e2 = %-16Q",amap->e2);
printf("f2 = %-16Q",amap->f2);
printc(EOR);
}
printfregs(longpr)
{
REG i;
double f;
printf("fpsr %o\n", regbuf[0].fpsr);
FOR i=0; i<FRMAX; i++
DO IF regbuf[0].fpsr&FD ORF longpr /* long mode */
THEN f = regbuf[0].lfr[frnames[i]];
ELSE f = regbuf[0].sfr[frnames[i]];
FI
printf("fr%-8d%-32.14f\n", i, f);
OD
}
printregs()
{
REG struct reglist *p;
int v;
FOR p=reglist; p < ®list[9]; p++
DO printf("%s%8t%o%8t", p->rname, v=uregs[p->roffs]);
valpr(v,(p->roffs==pc?ISYM:DSYM));
printc(EOR);
OD
printpc();
}
getreg(regnam)
{
REG struct reglist *p;
REG char *regptr;
char regnxt;
regnxt=readchar();
FOR p=reglist; p<®list[9]; p++
DO regptr=p->rname;
IF (regnam == *regptr++) ANDF (regnxt == *regptr)
THEN return(p->roffs);
FI
OD
lp--;
return(0);
}
printpc()
{
dot=leng(uregs[pc]);
psymoff(dot,ISYM,":%16t"); printins(0,ISP,chkget(dot,ISP));
printc(EOR);
}
/* sub process control */
subpcs(modif)
{
REG INT check; INT execsig;
REG BKPT *bkptr;
char *comptr;
execsig=0; loopcnt=cntval;
switch(modif) {
/* delete breakpoint */
case 'd': case 'D':
IF (bkptr=scanbkpt(shorten(dot)))
THEN bkptr->flag=0; return;
ELSE error(NOBKPT);
FI
/* set breakpoint */
case 'b': case 'B':
IF (bkptr=scanbkpt(shorten(dot)))
THEN bkptr->flag=0;
FI
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag == 0
THEN break;
FI
OD
IF bkptr==0
THEN IF (bkptr=getcell(sizeof *bkptr)) == -1
THEN error(EXBKPT);
ELSE bkptr->nxtbkpt=bkpthead;
bkpthead=bkptr;
FI
FI
bkptr->loc = dot;
bkptr->initcnt = bkptr->count = cntval;
bkptr->flag = BKPTSET;
check=MAXCOM-1; comptr=bkptr->comm; rdc(); lp--;
REP *comptr++ = readchar();
PER check-- ANDF lastc!=EOR DONE
*comptr=0; lp--;
IF check
THEN return;
ELSE error(LENBKPT);
FI
/* exit */
case 'k' :case 'K':
IF pid
THEN printf("%d: killed", pid); endpcs(); return;
FI
error(NOPCS);
/* run program */
case 'r': case 'R':
endpcs();
setup(); uregs[ps] =& ~TBIT;
EXITSW;
/* single step */
case 's': case 'S':
IF pid
THEN uregs[ps] =| TBIT;
execsig=getsig(signo);
ELSE setup(); loopcnt--;
FI
EXITSW;
/* continue with optional signal */
case 'c': case 'C': case 0:
IF pid==0 THEN error(NOPCS); FI
uregs[ps] =& ~TBIT;
execsig=getsig(signo);
EXITSW;
default: error(BADMOD);
}
IF loopcnt>0 ANDF runpcs(execsig)
THEN printf("breakpoint%16t");
ELSE printf("stopped at%16t");
FI
delbp();
printpc();
}
/* service routines for sub process control */
getsig(sig)
{ return(expr(0) ? shorten(expv) : sig);
}
runpcs(execsig)
{
INT rc; REG BKPT *bkpt;
IF adrflg
THEN ptrace(WUREGS,pid,USERPC,shorten(dot));
FI
ptrace(WUREGS,pid,USERPS,uregs[ps]);
setbp();
printf("%s: running\n", symfil);
WHILE (loopcnt--)>0
DO /*DEBUG printf("\ncontinue %d\n",execsig); */
ptrace(CONTIN,pid,0,execsig);
bpwait(TRUE); readregs();
/*look for bkpt*/
bkpt=scanbkpt(uregs[pc]-2);
IF bkpt
THEN /*stopped at bkpt*/
ptrace(WUREGS,pid,USERPC,uregs[pc]=bkpt->loc);
IF bkpt->flag==BKPTEXEC
ORF (bkpt->flag=BKPTEXEC, command(bkpt->comm,':')) ORF --bkpt->count
THEN execbkpt(bkpt); execsig=0; loopcnt++;
ELSE bkpt->count=bkpt->initcnt;
rc=1;
FI
ELSE rc=0; execsig=signo;
FI
OD
return(rc);
}
endpcs()
{
REG BKPT *bkptr;
IF pid
THEN ptrace(EXIT,pid,0,0); pid=0;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN bkptr->flag=BKPTSET;
FI
OD
FI
}
setup()
{
close(fsym); fsym = -1;
IF (pid = fork()) == 0
THEN ptrace(SETTRC,0,0,0);
signal(SIGINT,sigint); signal(SIGQIT,sigqit);
close(devmem); close(devswap);
doexec(); exit(0);
ELIF pid == -1
THEN error(NOFORK);
ELSE bpwait(FALSE); readregs(); lp[0]=EOR; lp[1]=0;
fsym=open(symfil,wtflag);
IF errflg
THEN printf("%s: cannot execute\n",symfil);
endpcs(); reset();
ELSE proctab=ptrace(RUREGS,pid,UPROCP,0);
FI
FI
}
execbkpt(bkptr)
BKPT *bkptr;
{ int saveps, bkptloc;
/*DEBUG printf("exbkpt: %d\n",bkptr->count); */
bkptloc = bkptr->loc;
IF ((saveps=gtrace(RUREGS, USERPS, 0))&TBIT)==0
THEN ptrace(WUREGS,pid,USERPS,saveps|TBIT);
FI
ptrace(WIUSER,pid,bkptloc,bkptr->ins);
ptrace(CONTIN,pid,0,0);
bpwait(TRUE);
ptrace(WIUSER,pid,bkptloc,BPT);
bkptr->flag=BKPTSET;
IF (saveps&TBIT)==0
THEN ptrace(WUREGS,pid,USERPS,gtrace(RUREGS,USERPS,0)&~TBIT);
FI
}
doexec()
{
char *argl[MAXARG]; char args[LINSIZ];
char *p, **ap, *filnam;
ap=argl; p=args;
*ap++=symfil;
REP IF rdc()==EOR THEN break; FI
*ap = p;
WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB DO *p++=lastc; readchar(); OD
*p++=0; filnam = *ap+1;
IF **ap=='<'
THEN close(0);
IF open(filnam,0)<0
THEN printf("%s: cannot open\n",filnam); exit(0);
FI
ELIF **ap=='>'
THEN close(1);
IF creat(filnam,0666)<0
THEN printf("%s: cannot create\n",filnam); exit(0);
FI
ELSE ap++;
FI
PER lastc!=EOR DONE
*ap++=0;
exect(symfil, argl);
}
scanbkpt(adr)
{
REG BKPT *bkptr;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag ANDF bkptr->loc==adr
THEN break;
FI
OD
return(bkptr);
}
delbp()
{ REG INT a; REG BKPT *bkptr;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN a=bkptr->loc;
ptrace(WIUSER,pid,a,bkptr->ins);
FI
OD
}
setbp()
{
REG INT a; REG BKPT *bkptr;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN a = bkptr->loc;
bkptr->ins = ptrace(RIUSER, pid, a, 0);
ptrace(WIUSER, pid, a, BPT);
IF errno
THEN prints("cannot set breakpoint: ");
psymoff(leng(bkptr->loc),ISYM,"\n");
FI
FI
OD
}
bpwait(exflg)
{
REG INT w;
INT stat;
signal(SIGINT, 1);
WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE
signal(SIGINT,sigint);
IF w == -1
THEN pid=0;
errflg=BADWAIT;
ELIF (stat & 0177) != 0177
THEN IF signo = stat&0177
THEN printf("%s", signals[signo]);
FI
IF stat&0200
THEN prints(" - core dumped");
close(fcor);
setcor();
FI
pid=0;
errflg=ENDPCS;
ELSE signo = stat>>8;
IF signo!=SIGTRC
THEN printf("%s\n", signals[signo]);
ELSE signo=0;
FI
FI
IF exflg ANDF errflg THEN reset(); FI
}
readregs()
{
/*get REG values from pcs*/
REG i;
FOR i=0; i<9; i++
DO uregs[reglist[i].roffs] =
gtrace(RUREGS, 2*(512+reglist[i].roffs), 0);
OD
/* floating point */
FOR i=FROFF; i<FRLEN+FROFF; i++
DO regbuf[i] = gtrace(RUREGS,i,0); OD
}
/* file handling and access routines */
gtrace(mode,adr,value)
{
int r;
IF mode==RUREGS
ANDF chkswap()
ANDF seek(devswap,swapblk,3) != -1
ANDF seek(devswap,adr,1) != -1
ANDF read(devswap,&r,2)==2
THEN return(r);
ELSE return(ptrace(mode,pid,adr,value));
FI
}
chkswap()
{
struct proc mproc[1];
IF devmem>=0 ANDF devswap>=0
ANDF seek(devmem, proctab, 0) != -1
ANDF read(devmem, mproc, sizeof mproc)==sizeof mproc
ANDF pid==mproc[0].p_pid
ANDF (mproc[0].p_flag&SLOAD)==0
THEN swapblk = mproc[0].p_addr;
return(TRUE);
ELSE return(FALSE);
FI
}
setproc()
{
devswap=open(DEVSWAP,0);
devmem=open(DEVMEM,0);
}
put(adr,space,value)
long adr;
{
access(WT,adr,space,value);
}
get(adr, space)
long adr;
{
return(access(RD,adr,space,0));
}
chkget(n, space)
long n;
{
REG w;
w = get(n, space);
IF errflg
THEN reset();
FI
return(w);
}
access(mode,adr,space,value)
long adr;
{
int w, w1, pmode, rd, file;
rd = mode==RD;
IF space == NSP THEN return(0); FI
IF pid /* tracing on? */
THEN IF adr&01 ANDF !rd THEN error(ODDADR); FI
pmode = (space&DSP?(rd?RDUSER:WDUSER):(rd?RIUSER:WIUSER));
w = gtrace(pmode, shorten(adr), value);
IF adr&01
THEN w1 = gtrace(pmode, shorten(adr+1), value);
w = (w>>8)&LOBYTE | (w1<<8);
FI
IF errno
THEN errflg = (space&DSP ? BADDAT : BADTXT);
FI
return(w);
FI
w = 0;
IF !chkmap(&adr,space)
THEN return(0);
FI
file=(space&DSP?datmap.ufd:txtmap.ufd);
IF longseek(file,adr)==0 ORF
(rd ? read(file,&w,2)<1 : write(file,&value,2)<1)
THEN errflg=(space&DSP?BADDAT:BADTXT);
FI
return(w);
}
chkmap(adr,space)
long *adr; int space;
{
MAP *amap;
amap=(space&DSP?&datmap:&txtmap);
IF space&STAR ORF !within(*adr,amap->b1,amap->e1)
THEN IF within(*adr,amap->b2,amap->e2)
THEN *adr =+ (amap->f2)-(amap->b2);
ELSE errflg=(space&DSP?BADDAT:BADTXT); return(0);
FI
ELSE *adr =+ (amap->f1)-(amap->b1);
FI
return(1);
}
within(adr,lbd,ubd)
long adr, lbd, ubd;
{
return(adr>=lbd && adr<ubd);
}
/* symbol table and file handling service routines */
longseek(f, a)
long a;
{
int page, offset;
offset = a&511; page = (a-offset)>>9;
/*DEBUG printf("file %d seek page %d offset %d\n",f,page,offset); */
return(seek(f,page,3) != -1 ANDF seek(f,offset,1) != -1);
}
valpr(v,idsp)
{
int d;
d = findsym(v,idsp);
IF d < maxoff
THEN printf("%.8s", symbol.symc);
IF d
THEN printf("+%o", d);
FI
FI
}
localsym(cframe)
long cframe;
{
INT symflg;
WHILE nextsym() ANDF localok
ANDF symbol.symc[0]!='~'
ANDF (symflg=symbol.symf)!=037
DO IF symflg>=2 ANDF symflg<=4
THEN localval=leng(symbol.symv);
return(TRUE);
ELIF symflg==1
THEN localval=leng(shorten(cframe)+symbol.symv);
return(TRUE);
ELIF symflg==20 ANDF lastframe
THEN localval=leng(lastframe+2*symbol.symv-10);
return(TRUE);
FI
OD
return(FALSE);
}
psymoff(v,type,s)
long v; int type; char *s;
{
int w;
w = findsym(shorten(v),type);
IF w >= maxoff
THEN printf("%Q",v);
ELSE printf("%.8s", symbol.symc);
IF w THEN printf("+%o",w); FI
FI
printf(s);
}
findsym(svalue,type)
INT svalue, type;
{
long diff, value, symval, offset; INT symtyp;
REG SYMSLAVE *symptr; SYMSLAVE *symsav;
value=leng(svalue); diff=maxoff; symsav=0;
IF type!=NSYM ANDF (symptr=symvec)
THEN WHILE diff ANDF (symtyp=symptr->typslave)!=ESYM
DO IF symtyp==type
THEN symval=leng(symptr->valslave);
IF value-symval<diff
ANDF value>=symval
THEN diff = value-symval;
symsav=symptr;
FI
FI
symptr++;
OD
IF symsav
THEN offset=leng(symsav-symvec);
symcnt=symnum-offset;
longseek(fsym, symbas+offset*12);
read(fsym,&symbol,12);
FI
FI
return(diff);
}
nextsym()
{
IF (--symcnt)<0
THEN return(FALSE);
ELSE return(longseek(fsym, symbas+(symnum-symcnt)*12)!=0 ANDF
read(fsym,&symbol,12)==12);
FI
}
/* sequential search through file */
symset()
{
symcnt = symnum;
symnxt = symbuf;
IF symrqd
THEN longseek(fsym, symbas);
symread(); symrqd=FALSE;
ELSE longseek(fsym, symbas+sizeof symbuf);
FI
}
symget()
{
REG INT rc;
IF symnxt >= symend
THEN rc=symread(); symrqd=TRUE;
ELSE rc=TRUE;
FI
IF --symcnt>0 ANDF rc==0 THEN errflg=BADFIL; FI
return( (symcnt>=0 && rc) ? symnxt++ : 0);
}
symread()
{
int symlen;
IF (symlen=read(fsym,symbuf,sizeof symbuf))>=12
THEN symnxt = symbuf;
symend = &symbuf[symlen/12];
return(TRUE);
ELSE return(FALSE);
FI
}