|
|
researchv10 Norman
static char sccsid[] = "@(#)runpcs.c 4.1 10/9/80";
#
/*
*
* UNIX debugger
* process control routines for sdb
* this is a hack on top of a hack on top of a hack
*
*/
#include "head.h"
#include <a.out.h>
#include <stab.h>
struct user u;
#include <stdio.h>
#include <sys/pioctl.h>
#include <sys/proc.h>
#include "base.h"
#ifndef SIGTRAP
#define SIGTRAP SIGTRC
#endif
MSG NOFORK;
MSG ENDPCS;
MSG BADWAIT;
ADDR sigint;
ADDR sigqit;
ADDR userpc;
/* breakpoints */
BKPTR bkpthead;
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);
}
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
setrun(runmode,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->flag=BKPTSET; 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;
endpcs()
{
REG BKPTR bkptr;
if (debug) printf("Entering endpcs with pid=%d\n");
IF pid
THEN killpcs(); pid=0; userpc=1;
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN bkptr->flag=BKPTSET;
FI
OD
FI
bpstate=BPOUT;
}
setup()
{
int fd;
long tsigs = ~0;
fd = openproc(getpid());
if (ioctl(fd, PIOCSEXEC, 0) < 0) {
close(fd);
error("no process ioctl");
}
close(fsym);
fsym = -1;
IF (pid = fork()) == 0
THEN close(fd);
signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
if (debug) printf("About to doexec pid=%d\n",pid);
doexec(); _exit(0);
ELIF pid == -1
THEN error(NOFORK);
ELSE ioctl(fd, PIOCREXEC, 0);
close(fd);
datmap.ufd = fcor = openproc(pid);
ioctl(fcor, PIOCSMASK, &tsigs);
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();
setrun(SINGLE,bkptr->loc,execsig);
bkptr->flag=BKPTSET;
bpwait(); chkerr(); readregs();
}
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);
fflush(stdout);
_exit(0);
}
} else {
close(1);
if (creat(filnam,0666) < 0) {
printf("%s: cannot create\n",filnam);
fflush(stdout);
_exit(0);
}
}
} 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 execv(%s, %d)\n",symfil,argl);
for (dap = argl; *dap; dap++) {
printf("%s, ", *dap);
}
}
execv(symfil, argl);
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;
prwrite(a, &bkptr->ins, 1);
FI
OD
bpstate=BPOUT;
FI
}
setbp()
{
REG ADDR a;
REG BKPTR bkptr;
char bpt = BPT;
IF bpstate!=BPIN
THEN
FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
DO IF bkptr->flag
THEN a = bkptr->loc;
prread(a, &bkptr->ins, 1);
prwrite(a, &bpt, 1);
IF errflg
THEN error("cannot set breakpoint: ");
printf("%s:%d @ %d\n", adrtoprocp(dot)->pname,
adrtolineno(dot), dot);
errflg = 0;
FI
FI
OD
bpstate=BPIN;
FI
}
#define WSLEEP 10
bpwait()
{
register int w;
struct proc p;
int pc;
int stat;
int (*isig)();
int nulsig();
extern int errno;
isig = signal(SIGINT, SIG_IGN);
/*
* alarm stuff is just in case
*/
for (;;) {
signal(SIGALRM, nulsig);
alarm(WSLEEP);
if (ioctl(fcor, PIOCWSTOP, 0) >= 0)
errno = 0;
alarm(0);
if (errno == 0) {
signal(SIGINT, isig);
ioctl(fcor, PIOCGETPR, &p);
signo = p.p_cursig;
prread(UBASE + PC, &pc, sizeof(pc));
if (signo == SIGTRAP || signo == SIGSTOP)
signo = 0;
else if (pc == extaddr("_dbsubn"))
signo = 0;
else
sigprint();
return;
}
if (errno == ENOENT)
break;
/* still there, still running. try again. */
}
/*
* process has died; wait and report status
* should check if it's really our child
*/
signal(SIGALRM, nulsig);
alarm(WSLEEP);
while ((w = wait(&stat)) != -1 && w != pid)
;
alarm(0);
pid = 0;
signal(SIGINT, isig);
close(fcor);
pid = 0;
corfil = NULL;
errflg = ENDPCS;
if (w == -1)
errflg = BADWAIT;
else {
if ((stat & 0177) == 0177)
printf("trace status? 0%o\n", stat);
else {
if ((signo = stat & 0177) != 0)
sigprint();
if (stat & 0200) {
printf(" - core dumped");
corfil = "core";
setcor();
}
printf("\n");
}
}
}
nulsig() {}
REGLIST reglist[];
readregs()
{
/*get REG values from pcs*/
REG i;
FOR i=24; --i>=0;
DO prread(UBASE + reglist[i].roffs, (char *)&u + reglist[i].roffs, sizeof(int));
OD
userpc = *(ADDR *)((char *)&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);
}
/*
* miscellaneous /proc hooks
*/
setrun(mode, pc, sig)
{
int ps;
if (pc != 1)
prwrite(UBASE + PC, &pc, sizeof(pc));
if (mode == SINGLE) {
prread(UBASE + PSL, &ps, sizeof(ps));
ps |= TBIT;
prwrite(UBASE + PSL, &ps, sizeof(ps));
}
if (sig == 0)
ioctl(fcor, PIOCCSIG, 0);
ioctl(fcor, PIOCRUN, 0);
}
killpcs()
{
long ksig = SIGKILL;
ioctl(fcor, PIOCCSIG, 0);
ioctl(fcor, PIOCKILL, &ksig);
ioctl(fcor, PIOCRUN, 0);
/*
* assert that it's our child
*/
while (wait((int *)0) >= 0)
;
}
int
openproc(id)
int id;
{
char buf[20];
int fd;
sprintf(buf, "/proc/%d", id);
if ((fd = open(buf, 2)) < 0) {
perror("can't open process");
longjmp(env, 0);
}
return (fd);
}
prread(addr, buf, size)
char *buf;
{
lseek(fcor, (long)addr, 0);
if (read(fcor, buf, size) != size)
errflg = "can't read process";
}
prwrite(addr, buf, size)
char *buf;
{
lseek(fcor, (long)addr, 0);
if (write(fcor, buf, size) != size)
errflg = "can't read process";
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.