Interdata_v6/usr/source/chicago/ddt1.c
#
/*
Dynamic Debugging Tool
Bill Allen
Naval Postgraduate School
March, 1975
Revised for UNIX version 6 October, 1975
Revised for Interdata UNIX, 1977
R Miller
University of Wollongong
*/
#include "/usr/sys/param.h"
#include "/usr/sys/user.h"
#include "/usr/sys/reg.h"
extern pinstr();
int regloc[] {
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
RPC,
RPS
};
struct sfregs {
int junk[2];
float sfr[8];
};
struct lfregs {
int junk[2];
double lfr[8];
};
extern int locsr5;
char *sbrk();
char *symbuf;
int *symptr;
int fcore -1;
int fsym -1;
int wcore -1;
int wsym -1;
int fdout;
char *gargv[10];
int pid;
int coroffset;
int symoff;
char *lp;
int errflg;
int symlen;
int symct;
char symbol[8];
int symflg;
int symval;
char ssymbol[8];
int ssymflg;
int ssymval;
char line[128];
int regbuf[512];
char **uregs;
char *rtsize;
int dot;
int tdot;
int dotinc sizeof(int);
int lastcom '/';
int lastype 'i';
char *symfil "a.out";
char *corfil "core";
int callist[50];
int *callp callist;
int leffect; /* last effective address */
int headsize; /* length of file header */
int tsize; /* length of text segment */
int dsize; /* length of data segment */
int ssize; /* length of bss segment */
int gargc; /* number of arguments from shell */
int sdot; /* symbolic operand temporary dot */
int ldot;
int elastype 'o'; /* = display mode */
int signo; /* signal type */
int adrfg; /* set if this command had an address */
int status;
#define BREAK 3 /* system call breakpoint */
#define BRKLEN 20
#define CONDLEN 82
struct {
int value; /* old value of breakpoint */
int addr; /* address of breakpoint */
char cond[CONDLEN]; /* breakpoint condition */
} brktab[BRKLEN];
int brktx -1; /* breakpoint table index */
char *signals[] {
"",
"Hangup",
"Interrupt",
"Quit",
"Illegal instruction",
"Trace/BTP",
"IOT",
"EMT",
"Floating exception",
"Killed",
"Bus error",
"Memory fault",
"Bad system call",
"",
"",
"",
};
extern int tempbra[]; /* temporary breakpoint address */
extern getspsym();
extern putspsym();
extern ssval[];
extern char *ssname[];
extern initssv();
#define RUSER 1
#define RIUSER 2
#define WUSER 4
#define RUREGS 3
#define WUREGS 6
#define SETTRC 0
#define CONTIN 7
#define EXIT 8
#define SSR0 0
#define SSR1 1
#define SSR2 2
#define SSR3 3
#define SSR4 4
#define SSR5 5
#define SSR6 6
#define SSR7 7
#define SSR8 8
#define SSR9 9
#define SSR10 10
#define SSR11 11
#define SSR12 12
#define SSR13 13
#define SSR14 14
#define SSR15 15
#define SSSP 7
#define SSPC 16
#define SSPS 17
#define SS8 18
#define SS9 19
#define SSL 20
#define SSM 21
#define SSQ 22
#define SSA 23
#define SSD 24
#define SSRG 25
main(argc, argv)
char **argv;
{
int onintr();
int endit();
register cpid, rpid;
int cstatus;
gargc = argc;
if(gargc > 1)
symfil = argv[1];
if(gargc > 2)
corfil = argv[2];
if((fsym = open(symfil,0))<0) {
printf("Unable to open %s\n",symfil);
exit();
}
wsym = open(symfil,1);
if(gargc != 2) { /* try for core file */
fcore = open(corfil,0);
wcore = open(corfil,1);
}
initfsym(); /* init symbolic file sizes */
if((symbuf=sbrk(symlen+4)) == -1) { /***/
printf("Symbol table too large\n");
exit();
}
symbuf =& ~03; /* word address */
seek(fsym,symoff,0);
if(read(fsym,symbuf,symlen) != symlen)
printf("Can't read symbol table\n");
if(fcore>=0 && gargc<=3) /* have a core file */
initfcor(); /* initialize the known symbols */
if(gargc>3) /* file is not a core image */
headsize = 0;
initssv(); /* set default special symbol values */
for(dot=0; dot<BRKLEN; dot++)
brktab[dot].addr = -1; /* all breakpoints are unused */
dot = 0;
if(symlook("savr5\0\0\0"))
locsr5 = ssymval;
if(fcore>0 && gargc <= 3)
setstack();
setexit();
signal(2, onintr); /* rubout */
signal(1,endit); /* hangup (EOT) */
putchar('\n'); /* ready to go */
loop:
if (errflg) {
printf("?\t");
errflg = 0;
}
lp = line;
while ((*lp = getchar()) != '\n') {
if(lp==line && *lp=='!'){ /* call the shell */
if((cpid=fork()) == 0) {
execl("/bin/sh","sh","-t",0);
exit();
}
while((rpid=wait(&cstatus)) != cpid && rpid != -1);
printf("!\n");
goto loop;
}
if (*lp++ == '\0')
endit();
}
lp = line;
command();
goto loop;
}
command()
{
register n;
adrfg = expr();
if (errflg)
return;
n = getcnt();
if (lastcom=='$')
lastcom = '/';
if (*lp == '\n') {
lastcom = '/';
if (!adrfg)
dot =+ dotinc;
} else
lastcom = *lp++;
if (adrfg) {
ldot = dot;
dot = tdot;
}
while(n) {
scommand(n);
if (*lp != '\n') {
printf("** unrecognized command or argument\n");
return;
}
if (--n){
dot =+ dotinc;
putchar('\n');
}
}
}
scommand(n)
{
register char *p1;
register w, c;
double fw;
struct { int i[4]; };
if(lastcom == '>') { /* follow the path */
dot = leffect;
lastcom = '/';
}
switch(lastcom) {
case '/':
psym(dot); /* print address symbolically */
putchar('\t');
w = cget(dot);
ssval[SSQ] = w; /* set :q */
leffect = w; /* set default last effective address */
if(*lp != '\n')
lastype = *lp++;
switch(lastype) {
case 'o': /* word octal */
printf("%11o\t", w);
dotinc = sizeof(int);
return;
case 'x': /* word hexidecmal */
printf("%8x\t", w);
dotinc = sizeof(int);
return;
case 'd': /* word decimal */
printf("%d\t", w);
dotinc = sizeof(int);
return;
case 'l': /* word unsigned decimal */
printf("%l\t", w);
dotinc = sizeof(unsigned int);
return;
case 'f': /* floating point */
printf("%e\t", w);
dotinc = sizeof(float);
return;
case 'e': /* double precision floating point */
printf("%e\t", w);
dotinc = sizeof(double);
return;
case 'i': /* instruction in assembler format */
leffect = 0;
pinstr(); /* print instruction symbolically */
return;
case '&':
c = ssval[SSL]; /* save low symbol address */
ssval[SSL] = 0; /* use all symbols */
psym(w); /* print as symbol and offset */
ssval[SSL] = c;
if (errflg)
reset();
putchar('\t');
dotinc = sizeof(int *);
return;
case 'b': /* byte in octal */
printf("%3o\t", xch(w, dot));
dotinc = 1;
return;
case '\'': /* byte in ASCII */
printc(xch(w, dot));
dotinc = 1;
putchar('\t');
return;
case '"': /* halfword in ASCII */
printc((w>>24)&0377); /***/
printc((w>>16)&0377);
dotinc = 2;
putchar('\t');
return;
case 's': /* string in ASCII */
w = dot;
while(c = xch(cget(w), w)) {
printc(c);
w++;
}
putchar('\t');
dotinc = w-dot+1;
return;
}
printf("** unrecognized display mode\n");
return;
case '=':
ssval[SSQ] = tdot; /* set :q value */
dot = ldot; /* restore dot */
lastcom = '/'; /* this was an aside */
if(*lp != '\n')
elastype = *lp++;
switch(elastype){ /* display mode */
case 'o': /* word octal */
printf("%11o\t",tdot);
return;
case 'x': /* word hexidecimal */
printf("%8x\t",tdot);
return;
case 'd': /* word decimal */
printf("%d\t",tdot);
return;
case 'l': /* word unsigned decimal */
printf("%l\t",tdot);
return;
case 'b': /* byte decimal */
printf("%3o\t",tdot&0377);
return;
case '&': /* address */
c = ssval[SSL]; /* save low symbol address */
ssval[SSL] = 0; /* use all symbols */
psym(tdot); /* print as symbol and offset */
ssval[SSL] = c;
if (errflg)
reset();
putchar('\t');
return;
case '\'': /* byte ASCII */
putchar(tdot&0377);
putchar('\t');
return;
case '"': /* word ASCII */
putchar(tdot>>8);
putchar(tdot&0377);
putchar('\t');
return;
}
printf("** unrecognized display mode\n");
return;
case '!': /* patch the file */
if(!adrfg){ /* no value to store */
printf("** no address for store\n");
return;
}
dot = ldot; /* reset dot */
if(*lp == ':'){ /* store value in special symbol */
lp++;
putspsym(tdot); /* set sp symbol to value in tdot */
return;
}
cfput(tdot); /* put tdot in file at address dot */
return;
case '$':
prtermst(); /* print termination status */
printtrace();
return;
case '?': /* display termination status */
prtermst();
return;
case '^': /* preceeding cell */
dot =- 4;
lastcom = '/'; /* display word value */
scommand(n);
return;
case ';': /* long command */
lastcom = '/'; /* display */
switch(*lp++){
case 'g': /* begin file execution */
w = 1; /* only once */
if(pid>0){ /* have a child at breakpoint */
ptrace(EXIT,pid,0,0); /* kill old child */
pid = 0;
}
if(fsym<0) {
printf("no symbolic file to execute\n");
return;
}
gargv[0] = symfil; /* first name is file name */
w = 1;
loop:
while(*lp == ' ') *lp++ = '\0';
if(*lp == '\n') {
*lp = '\0'; /* end of string */
gargv[w] = 0; /* end of argument list */
}
else {
gargv[w++] = lp; /* form argument pointers */
while(*lp != ' ' && *lp != '\n') lp++; /* skip over args */
goto loop;
}
while((pid = fork())<0);
if(pid==0){ /* child */
ptrace(SETTRC,0,0,0); /* expect trace */
signal(SIGINT,0);
signal(SIGINS,0);
execv(symfil,gargv); /* execute the file */
printf("Can't execute %s\n",symfil);
exit(); /* just in case */
}
else { /* parent */
if(fcore>=0){ /* core file open */
rmcore(); /* close core files */
}
}
w = 0;
connotb();
return;
case 'p': /* proceed from breakpoint */
if(adrfg)
w = dot; /* repetition factor */
else
w = 1;
while(w--) {
proceed();
}
return;
case 's': /* single instruction step */
lastcom = '/';
lastype = 'i';
*lp = '\n';
if(adrfg)
w = dot; /* repetition factor */
else
w = 1;
while(w--){ /* one instruction each time */
stempbpt(0); /* set temp brkpt */
restcore();
ptrace(CONTIN,pid,0,0);
bpwait();
rtempbpt();
dot = ssval[SSPC];
scommand(1); /* print the instruction */
if(w) putchar('\n');
}
return;
case '.': /* set temp bpt and continue */
if(adrfg==0) {
printf("*** no address specified\n");
return;
}
w = dot;
setbpt(w); /* set breakpoint */
proceed(); /* ;p */
clbkpt(w); /* clear breakpoint */
dot = ssval[SSPC];
return;
case '=': /* search equal */
for(dot=ssval[SS8];dot<=ssval[SS9];dot =+ 4){
if((cget(dot)&(ssval[SSM])) == tdot){
scommand(n); /* display it */
putchar('\n');
}
}
putchar('\n');
return;
case '#': /* search not equal */
for(dot=ssval[SS8];dot<=ssval[SS9];dot =+ 4){
if((cget(dot)&(ssval[SSM])) != tdot){
scommand(n); /* display it */
putchar('\n');
}
}
putchar('\n');
return;
case 'b': /* set breakpoint */
if(adrfg)
setbpt(dot);
else
printf("*** no address specfied\n");
return;
case 'c': /* clear a breakpoint */
clbkpt(dot); /* clear it or all */
return;
case 'd': /* display breakpoints */
if(brktx<0) goto dout;
for(c=0;c<=brktx;c++){
if(brktab[c].addr != -1){ /* valid breakpoint */
psym(brktab[c].addr); /* print breakpoint address */
putchar('\t');
if(brktab[c].cond[0] != '\0') /* print conditional */
printf("%s",brktab[c].cond);
else
putchar('\n');
ssval[SSQ] = brktab[c].addr; /* set :q */
}
}
dout:
putchar('\n');
return;
case 'r': /* display registers in octal and symbollically */
for(c=0;c<=SSPC;c++){
printf("%s\t%11o\t", ssname[c], ssval[c]);
psym(ssval[c]);
putchar('\n');
}
return;
case 'e': /* print floating regs */
printfregs();
return;
case 'f': /* stop */
endit();
case 'w': /* write copy of breakpointed pgm */
while(*lp==' ')
lp++;
p1 = lp;
while(*lp != '\n')
lp++;
*lp = '\0'; /* end of string */
if((fdout=creat(p1,0777))<0){
printf("**unable to open output file %s\n",line);
return;
}
if(fcore>0) {
w = (headsize+tsize+dsize+ssize+511)/512;
seek(fcore,coroffset,3);
while(w--) {
read(fcore,regbuf,512);
write(fdout,regbuf,512);
}
close(fdout);
initfcor();
putchar('\n');
*lp = '\n';
return;
}
printf("**no core file to copy\n");
return;
}
}
printf("** unrecognized command\n");
}
/*
* extract even or odd character from word returned by cget
*/
struct { char byte[]; };
xch(word, addr)
{
return(word.byte[addr & 01]);
}
rmcore()
{
close(fcore);
close(wcore);
fcore = -1;
wcore = -1;
initfsym();
}
/* test for a valid breakpoint address */
notbpt()
{
register i,j;
j=ssval[SSPC];
for(i=0;i<=brktx; i++)
if(brktab[i].addr==j)
return(0);
for(i=0; i<2; i++)
if(tempbra[i]==j)
return(0);
return(1); /* not valid */
}
bpwait()
{
extern int onintr();
register w;
int stat;
loop:
signal(SIGINT, 1);
while ((w = wait(&stat))!=pid && w != -1);
signal(SIGINT, onintr);
if (w == -1) {
ptrace(EXIT, pid, 0, 0);
pid = 0;
printf("Wait error\n");
reset();
}
if ((stat & 0377) != 0177) {
if (signo = stat&0177)
printf("%s\n", signals[signo]);
printf("Process terminated.\n");
if (pid == w) {
pid = 0;
reset();
}
goto loop;
}
signo = stat>>8;
initfmem();
/*** if (signo!=SIGTRC) { ***/
if (signo!=SIGINS || notbpt()) {
printf("%s\n", signals[signo]);
reset();
}
setstack();
}
/* set a breakpoint */
setbpt(adr)
{
register c, old;
adr =& ~01;
for(c=0;c<=brktx;c++)
if(brktab[c].addr==adr){ /* already got it */
getcond(c); /* may want to change conditional */
return;
}
for(c=0;c<=brktx;c++)
if(brktab[c].addr == -1){ /* not used */
bptstr:
/* save old value of word containing breakpoint */
dot = adr & ~03;
brktab[c].value = old = cget(dot);
brktab[c].addr = adr;
/* change half the word */
if (adr & 03)
cfput((old&0xffff0000) | BREAK);
else
cfput((BREAK<<16) | (old&0xffff));
if(errflg){
printf("**Unable to set breakpoint\n");
brktab[c].addr = -1; /* no breakpoint */
}
getcond(c); /* get breakpoint condition */
dot = ldot; /* reset dot */
return;
}
if(++brktx > BRKLEN){ /* no more breakpoints */
printf("?? too many breakpoints\n");
return;
}
c = ++brktx;
goto bptstr;
}
/* proceed from a breakpoint */
proceed()
{
if(pid<=0) {
printf("no process to continue\n");
return;
}
if(stempbpt(1)) {; /* set temporary breakpoint maybe */
restcore(); /* restore special symbol values */
ptrace(CONTIN,pid,0,0);
bpwait();
rtempbpt(); /* remove temporary breakpoints */
/*** ssval[SSPC] =+ 2; /* trapped by T bit ***/
}
restcore(); /* reset PC */
ptrace(CONTIN,pid,0,0);
connotb();
}
/* continue not from breakpoint */
connotb()
{
bpwait();
if(!condbpt()) { /* conditinal? */
proceed();
return;
}
if(notbpt()){ /* not valid breakpoint */
printf("breakpoint error %o\n",ssval[SSPC]);
endit();
}
dot = ssval[SSPC]; /* location of breakpoint */
lastcom = '/'; /* display */
lastype = 'i';
*lp = '\n';
scommand(1); /* display breakpoint instr */
}
printfregs()
{
register i;
double f;
if(pid)
for(i=2; i<18; i++)
regbuf[i] = ptrace(RUREGS,pid,4*i,0); /* read fregs */
for (i=0; i<8; i++) {
f = regbuf[0].sfr[i];
printf("fr%d %e\n", i*2, f);
}
}
getchar()
{
char lastc;
if(read(0,&lastc,1) <= 0)
return(0);
return(lastc&0177);
}
/* get the condition for this breakpoint */
getcond(aidx)
{
register idx,i;
idx=aidx; /* breakpoint table index */
if(*lp == '\n') { /* unconditional */
brktab[idx].cond[0] = '\0';
return;
}
while(*lp == 'b') lp++; /* ignore blanks */
i=0;
while(*lp!='\n' && i<CONDLEN-2)
brktab[idx].cond[i++] = *lp++; /* save condition source */
if(*lp != '\n') {
printf("***condition more than %d bytes long ignored\n",CONDLEN-2);
brktab[idx].cond[0] = '\0';
return;
}
brktab[idx].cond[i++] = '\n';
brktab[idx].cond[i++] = '\0';
}