BSD 3 development
[unix-history] / usr / src / cmd / sdb / runpcs.c
#
/*
*
* UNIX debugger
*
*/
#include "head.h"
#include <a.out.h>
struct user u;
#include <stdio.h>
MSG NOFORK;
MSG ENDPCS;
MSG BADWAIT;
ADDR sigint;
ADDR sigqit;
/* breakpoints */
BKPTR bkpthead;
REGLIST reglist [] = {
"p1lr", P1LR,
"p1br",P1BR,
"p0lr", P0LR,
"p0br",P0BR,
"ksp",KSP,
"esp",ESP,
"ssp",SSP,
"psl", PSL,
"pc", PC,
"usp",USP,
"fp", FP,
"ap", AP,
"r11", R11,
"r10", R10,
"r9", R9,
"r8", R8,
"r7", R7,
"r6", R6,
"r5", R5,
"r4", R4,
"r3", R3,
"r2", R2,
"r1", R1,
"r0", R0,
};
CHAR lastc;
INT fcor;
INT fsym;
STRING errflg;
int errno;
INT signo;
L_INT dot;
STRING symfil;
INT wtflag;
INT pid;
INT adrflg;
L_INT loopcnt;
getsig(sig)
{ return(sig);
}
ADDR userpc = 1;
runpcs(runmode,execsig)
{
REG BKPTR bkpt;
IF adrflg THEN userpc=dot; FI
WHILE --loopcnt>=0
DO
if (debug) printf("\ncontinue %x %d\n",userpc,execsig);
IF runmode==SINGLE
THEN delbp(); /* hardware handles single-stepping */
ELSE /* continuing from a breakpoint is hard */
IF bkpt=scanbkpt(userpc)
THEN execbkpt(bkpt,execsig); execsig=0;
FI
setbp();
FI
ptrace(runmode,pid,userpc,execsig);
bpwait(); chkerr(); execsig=0; delbp(); readregs();
loop1: IF (signo==0) ANDF (bkpt=scanbkpt(userpc))
THEN /* stopped by BPT instruction */
if (debug) printf("\n BPT code; '%s'%o'%o'%d",
bkpt->comm,bkpt->comm[0],EOR,bkpt->flag);
dot=bkpt->loc;
IF bkpt->comm[0] != EOR
THEN acommand(bkpt->comm);
FI
IF bkpt->flag==BKPTEXEC
ORF ((bkpt->flag=BKPTEXEC)
ANDF bkpt->comm[0]!=EOR)
THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++;
goto loop1;
ELSE bkpt->count=bkpt->initcnt;
FI
ELSE execsig=signo;
if (execsig) break;
FI
OD
if (debug) printf("Returning from runpcs\n");
}
#define BPOUT 0
#define BPIN 1
INT bpstate = BPOUT;
endpcs()
{
REG BKPTR bkptr;
if (debug) printf("Entering endpcs with pid=%d\n");
IF pid
THEN ptrace(EXIT,pid,0,0); pid=0; userpc=1;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN bkptr->flag=BKPTSET;
FI
OD
FI
bpstate=BPOUT;
}
#ifdef VFORK
nullsig()
{
}
#endif
setup()
{
close(fsym); fsym = -1;
#ifdef VFORK
IF (pid = vfork()) == 0
#else
IF (pid = fork()) == 0
#endif
THEN ptrace(SETTRC,0,0,0);
signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
#ifdef VFORK
signal(SIGTRC,nullsig);
#endif
if (debug) printf("About to doexec pid=%d\n",pid);
#ifdef UCBVAX
doexec(); _exit(0);
#else
doexec(); exit(0);
#endif
ELIF pid == -1
THEN error(NOFORK);
ELSE bpwait(); readregs();
if (debug) printf("About to open symfil = %s\n", symfil);
fsym=open(symfil,wtflag);
IF errflg
THEN printf("%s: cannot execute\n",symfil);
if (debug) printf("%d %s\n", errflg, errflg);
endpcs();
FI
FI
bpstate=BPOUT;
}
execbkpt(bkptr,execsig)
BKPTR bkptr;
{
if (debug) printf("exbkpt: %d\n",bkptr->count);
delbp();
ptrace(SINGLE,pid,bkptr->loc,execsig);
bkptr->flag=BKPTSET;
bpwait(); chkerr(); readregs();
}
extern STRING environ;
doexec()
{
char *argl[MAXARG], args[LINSIZ];
register char c, redchar, *argsp, **arglp, *filnam;
arglp = argl;
argsp = args;
*arglp++ = symfil;
c = ' ';
do {
while (eqany(c, " \t")) {
c = rdc();
}
if (eqany(c, "<>")) {
redchar = c;
do {
c = rdc();
} while (eqany(c, " \t"));
filnam = argsp;
do {
*argsp++ = c;
c = rdc();
} while (!eqany(c, " <>\t\n"));
*argsp++ = '\0';
if (redchar == '<') {
close(0);
if (open(filnam,0) < 0) {
printf("%s: cannot open\n",filnam);
#ifdef UCBVAX
_exit(0);
#else
exit(0);
#endif
}
} else {
close(1);
if (creat(filnam,0666) < 0) {
printf("%s: cannot create\n",filnam);
#ifdef UCBVAX
_exit(0);
#else
exit(0);
#endif
}
}
} else if (c != '\n') {
*arglp++ = argsp;
do {
*argsp++ = c;
c = rdc();
} while(!eqany(c, " <>\t\n"));
*argsp++ = '\0';
}
} while (c != '\n');
*arglp = (char *) 0;
if (debug) {
char **dap;
printf("About to exect(%s, %d, %d)\n",symfil,argl,environ);
for (dap = argl; *dap; dap++) {
printf("%s, ", *dap);
}
}
exect(symfil, argl, environ);
perror("Returned from exect");
}
BKPTR scanbkpt(adr)
ADDR adr;
{
REG BKPTR bkptr;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag ANDF bkptr->loc==adr
THEN break;
FI
OD
return(bkptr);
}
delbp()
{
REG ADDR a;
REG BKPTR bkptr;
IF bpstate!=BPOUT
THEN
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN a=bkptr->loc;
ptrace(WIUSER,pid,a,
(bkptr->ins&0xFF)|(ptrace(RIUSER,pid,a,0)&~0xFF));
FI
OD
bpstate=BPOUT;
FI
}
setbp()
{
REG ADDR a;
REG BKPTR bkptr;
IF bpstate!=BPIN
THEN
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 | (bkptr->ins&~0xFF));
IF errno
THEN error("cannot set breakpoint: ");
printf("%s:%d @ %d\n", adrtoprocp(dot)->pname,
adrtolineno(dot), dot);
FI
FI
OD
bpstate=BPIN;
FI
}
bpwait()
{
REG ADDR w;
ADDR stat;
signal(SIGINT, 1);
if (debug) printf("Waiting for pid %d\n",pid);
WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE
if (debug) printf("Ending wait\n");
if (debug) printf("w = %d; pid = %d; stat = %o;\n", w,pid,stat);
signal(SIGINT,sigint);
IF w == -1
THEN pid=0;
errflg=BADWAIT;
ELIF (stat & 0177) != 0177
THEN IF signo = stat&0177
THEN sigprint();
FI
IF stat&0200
THEN error(" - core dumped");
close(fcor);
setcor();
FI
pid=0;
errflg=ENDPCS;
ELSE signo = stat>>8;
if (debug) printf("PC = %d, dbsubn = %d\n",
ptrace(RUREGS, pid, PC, 0), extaddr("_dbsubn"));
IF signo!=SIGTRC ANDF
ptrace(RUREGS, pid, PC, 0) != extaddr("_dbsubn")
THEN sigprint();
ELSE signo=0;
FI
FI
}
readregs()
{
/*get REG values from pcs*/
REG i;
FOR i=24; --i>=0;
DO *(ADDR *)(((ADDR)&u)+reglist[i].roffs) =
ptrace(RUREGS, pid, reglist[i].roffs, 0);
OD
userpc= *(ADDR *)(((ADDR)&u)+PC);
}
char
readchar() {
lastc = *argsp++;
if (lastc == '\0') lastc = '\n';
return(lastc);
}
char
rdc()
{
register char c;
c = *argsp++;
return(c == '\0' ? '\n' : c);
}