|
|
Power 6/32 Unix version 1.2b
static char sccsid[] = "@(#)pt.c 2.10";
#include <errno.h>
#include <signal.h>
#ifndef REGULUS
#include <sys/param.h>
#endif
#ifdef SUN
#define SYSTYPES 1 /* see basic.h */
#endif
#ifdef SYSIII
#define SYSTYPES 1 /* see basic.h */
#endif
#include "cdb.h"
#include "macdefs.h"
#ifdef SYSIII
#include <termio.h>
#ifdef REGULUS
/* remove the two TCxxxxx and
* add #include <sys/ioctl.h> when preporocessor is fixed
*/
#define TCGETA 1
#define TCSETAW 3
#define EINTR -1
#endif
struct termio histty, mytty;
#endif
#ifdef BSD41
#include <sgtty.h>
struct sgttyb histty, mytty;
#endif
export int vibp; /* last breakpoint hit, if any */
export uint vsig;
uint vstat, vstatHi, vstatLo;
SAR vmpSigSa[NSIG]; /* signal action array */
void Fixer();
#define cArgsMax 30
char *argvChild[cArgsMax];
#define cbArgsMax 200
export char vsbArgsChild[cbArgsMax]; /* where we store args for child */
/* N E X T A R G */
export char * NextArg(psbIn)
char **psbIn;
{
char *sbRet;
/* skip white space */
while (**psbIn == ' ' OR **psbIn == '\t')
(*psbIn)++;
if (**psbIn == chNull)
return(sbNil); /* that's all, folks! */
sbRet = *psbIn; /* set current arg pointer */
while (**psbIn != chNull
AND **psbIn != ' '
AND **psbIn != '\t')
(*psbIn)++; /* skip all non-white space characters */
**psbIn = chNull; /* overwrite the tab, space, or 0 with a 0 */
(*psbIn)++;
return(sbRet);
} /* NextArg */
/* D O A R G S */
export void DoArgs(sbProgram, sbArgs, argv, fReassign)
char *sbProgram, *sbArgs;
char **argv;
FLAGT fReassign;
{
int i;
char *sbFile, *sbArgCur;
for (i=0; i< cArgsMax; i++)
argv[i] = sbNil;
*argv++ = sbProgram; /* set the filename */
/* eat the arguments */
while ((sbArgs != sbNil)
AND (*sbArgs != chNull)) {
sbArgCur = NextArg(&sbArgs);
if (sbArgCur == sbNil)
break;
/* check for indirection */
if (!fReassign
OR ((*sbArgCur != '<') AND (*sbArgCur != '>')) ) {
*argv++ = sbArgCur; /* we just pass it on */
}
else {
/* find that file name */
sbFile = sbArgCur + 1; /* initially we assume `<foo' vs `< foo' */
if (*sbFile == chNull) {
/* there was white space between < and sbFile */
sbFile = NextArg(&sbArgs);
if (sbFile == sbNil) {
printf("Illegal indirection\n");
exit(1);
} /* if */
} /* if */
if (*sbArgCur == '<') {
/* changing stdin */
close(0);
if (open(sbFile, O_RDONLY) < 0) {
perror(sbFile);
exit(1);
} /* if */
}
else if (*sbArgCur == '>') {
/* changing stdout */
close(1);
if (creat(sbFile, 0666) < 0) {
perror(sbFile);
exit(1);
} /* if */
} /* if */
} /* if */
} /* while */
*argv = sbNil;
} /* DoArgs */
/* P R I N T S I G */
export void PrintSig(sig)
int sig;
{
switch (sig) {
case SIGHUP:
printf("Hangup");
break;
case SIGINT:
printf("interrupt");
break;
case SIGQUIT:
printf("quit");
break;
case SIGILL:
printf("illegal instruction");
break;
case SIGTRAP:
printf("breakpoint");
break;
case SIGIOT:
printf("IOT instruction");
break;
case SIGEMT:
printf("EMT instruction");
break;
case SIGFPE:
printf("floating point exception");
break;
case SIGKILL:
printf("kill");
break;
case SIGBUS:
printf("bus error");
break;
case SIGSEGV:
printf("segmentaion violation");
break;
case SIGSYS:
printf("bad arg to sys call");
break;
case SIGPIPE:
printf("write on pipe with no reader");
break;
case SIGALRM:
printf("alarm clock");
break;
case SIGTERM:
printf("software termination");
break;
#ifdef SYSIII
case SIGUSR1:
printf("user signal 1");
break;
case SIGUSR2:
printf("user signal 2");
break;
case SIGCLD:
printf("death of child");
break;
case SIGPWR:
printf("power fail");
break;
#endif
#ifdef BSD41
#ifdef BSD42
case SIGURG:
printf("urgent condition on IO channel");
break;
case SIGIO:
printf("input/output possible signal");
break;
case SIGVTALRM:
printf("virtual time alarm");
break;
case SIGPROF:
printf("profiling time alarm");
break;
#endif
case SIGSTOP:
printf("sendable stop signal not from tty");
break;
case SIGTSTP:
printf("stop signal from tty");
break;
case SIGCONT:
printf("attempt to continue a stopped process");
break;
case SIGCHLD:
printf("child stop or exit");
break;
case SIGTTIN:
printf("to readers pgrp upon background tty read");
break;
case SIGTTOU:
printf("to writers pgrp upon background tty write");
break;
case SIGXCPU:
printf("exceeded CPU time limit");
break;
case SIGXFSZ:
printf("exceeded file size limit");
break;
#endif
default:
printf("signal %d", sig);
break;
} /* switch */
} /* PrintSig */
/* I B P F W A I T */
export int IbpFWait(fDoBrk)
FLAGT fDoBrk;
{
int ibp, waitReturn;
pSAR sa;
keepGoing: /* we come here if the signal is not interesting */
signal(SIGINT, SIG_IGN); /* ignore INT - let child deal with it */
while ( ((waitReturn=wait(&vstat)) != vpid) AND (waitReturn != -1) )
;
#ifdef SYSIII
ioctl(0, TCGETA, &histty); /* save his state, restore my state */
ioctl(0, TCSETAW, &mytty);
#endif
#ifdef BSD41
gtty(0, &histty); /* save his state, restore my state */
stty(0, &mytty);
#endif
signal(SIGINT, Fixer); /* reconnect to the Fixer routine */
GetState();
vsig = vstatHi = vstat >> 8;
vstatLo = vstat & 0377;
vibp = ibp = ibpNil; /* index of the breakpoint we are at (if any) */
if (waitReturn == -1) {
if (errno == EINTR) {
printf("PANIC! received signal: %d????\n", vsig);
/* what do we do here?? */
exit(1);
}
else { /* some sort of error occurred */
perror("cdb");
exit(1);
} /* if */
}
else if (vstatLo == 0) { /* child terminated */
if (vstatHi != 0)
printf("Process exited with %d\n", vstatHi);
else printf("Process terminated normally\n");
KillChild(); /* go bury the corpse */
ibp = 0; /* small hack - causes single step to stop in cmd.c */
}
else if ((vstatLo&0177) == 0177) { /* child stopped */
sa = vmpSigSa + vsig;
if (sa->fNoStop) {
#ifdef SYSIII
ioctl(0, TCSETAW, &histty);
#endif
#ifdef BSD41
stty(0, &histty);
#endif
if (!(sa->fNoReport)) {
PrintSig(vsig);
printf(" at %s\n", SbFAdr(lengthen(vpc), true));
PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
} /* if */
vsig = (sa->fEatSig) ? 0 : vsig;
ptrace(ptResume, vpid, 1, vsig); /* continue */
goto keepGoing;
} /* if */
/* NOTE: BrkOut MIGHT back up pc, depends on machine and instruction */
vibp = ibp = (fDoBrk) ? BrkOut(&vpc) : ibpNil;
if (vpc == vadrBreak) {
/* we have hit the BP used for proc calls from command line */
return(ibp);
} /* if */
if ( (ibp >= 0)
AND (vrgBp[ibp].sbBp[0] != chNull) ) {
PushCmd(vsbCmd);
vsbCmd = vrgBp[ibp].sbBp;
} /* if */
if ( (vsig != SIGTRAP) /* we ALWAYS report non-break signals */
OR ((ibp >= 0) /* there is something to hear */
AND (*vsbCmd != 'Q')) ) { /* and BP's want's it heard */
printf("\n"); /* in case we were left in the middle of a line */
PrintSig(vsig);
printf(" at %s\n", SbFAdr(lengthen(vpc), true));
PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
}
else if ((vsbCmd != sbNil) AND (*vsbCmd == 'Q')) {
PrintPos(vpc, fmtNil);
} /* if */
vsig = (sa->fEatSig) ? 0 : vsig;
}
else if ((vstat & 0177) != 0177) { /* terminated on signal */
if (vstat & 0177)
PrintSig(vstat&0177);
if (vstat & 0200) {
printf(" (core dumped)");
close(vfnCore);
InitCorefile("core");
} /* if */
printf(" at %s\n", SbFAdr(lengthen(vpc), true));
PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
vpid = pidNil;
} /* if */
return(ibp);
} /* IbpFWait */
/* I B P F R U N */
export int IbpFRun(pt)
int pt;
{
int ibp;
ADRT pcOld;
if (vpid == pidNil)
UError("No process");
if ((vfRunAssert)
AND (vas == asActive)
AND (viadMac > 0)
AND (pt != ptSingle)) {
/* do the assertions */
if (FDoAssert(pt)) /* this will change vas and single step the child */
return(ibpNil); /* an assertion came up true */
if (vpid == pidNil)
return(ibpNil); /* the child died during assertions */
if (vibp != ibpNil)
return(vibp);
} /* if */
/* hit the GO button */
do { /* loop allows for bp's that say 'continue' */
/* if we are at a breakpoint, single step over it, then install it */
if (IbpFBrkIn(vpc) != ibpNil) {
PutState();
pcOld = vpc;
while (pcOld == vpc) {
ptrace(ptSingle, vpid, 1, vsig);
ibp = IbpFWait(false);
} /* while */
if (pt == ptSingle)
return(ibp); /* we have already single stepped it for them */
/* full steam ahead */
IbpFBrkIn(adrNil); /* put in bp's */
} /* if */
PutState();
#ifdef SYSIII
ioctl(0, TCSETAW, &histty);
#endif
#ifdef BSD41
stty(0, &histty);
#endif
errno = 0;
ptrace(pt, vpid, 1, vsig); /* start child with signal `sig' */
ibp = IbpFWait(true);
}
while (ibp == ibpContinue);
return(ibp);
} /* IbpFRun */
/* I B P F N E W C H I L D */
export int IbpFNewChild(sbArgs)
char *sbArgs;
{
int sig, i, ibp;
FLAGT fMaster;
KillChild(); /* in case there is already one out there */
#ifdef SYSIII
ioctl(0, TCGETA, &histty); /* to start with, he is the same as me */
ioctl(0, TCGETA, &mytty); /* save my stuff */
#endif
#ifdef BSD41
gtty(0, &histty); /* to start with, he is the same as me */
gtty(0, &mytty); /* save my stuff */
#endif
if (sbArgs == sbNil) {
*vsbArgsChild = chNull; /* this comes from the R command */
}
else {
fMaster = (sbArgs == vsbCmd); /* this is the normal command line */
while (*sbArgs == ' ' OR *sbArgs == '\011')
sbArgs++; /* eat leading white space */
if (*sbArgs != chNull) {
strcpy(vsbArgsChild, sbArgs);
for (i=strlen(sbArgs); i<cbArgsMax; i++)
vsbArgsChild[i] = chNull;
/* fixes obscure bug, don't ask why...... */
if (fMaster) {
/* eat it - this way we don't
* try to execute the arguments to the child
* as debugger commands
*/
vsbCmd = sbNil;
} /* if */
} /* if */
} /* if */
close(vfnSym); /* in case it is PURE or SPLIT I&D */
if ((vpid = fork()) == 0) {
for (sig=1; sig<NSIG; sig++)
signal(sig, SIG_DFL); /* start out with default response */
DoArgs(vsbSymfile, vsbArgsChild, argvChild, true);
ptrace(ptChild, 0, 0, 0); /* Hi, Mom! */
#ifdef REGULUS
#define flags 04+010+020 /* overlay + set trace + environment present */
maketask(vsbSymfile, flags, 0, argvChild, venvpParent);
#else
execvp(vsbSymfile, argvChild);
#endif
/* if we get here, exec failed */
perror("could not startup");
exit(1);
} /* if */
/* should only get here if parent */
printf("running '%s %s'\n", vsbSymfile, vsbArgsChild);
IbpFWait(false);
/* it is now safe to open symfile again */
/* printf("Opening file %s\n", vsbSymfile); */
vfnSym = open(vsbSymfile, O_RDONLY);
if (vfnSym < 0) {
perror(vsbSymfile);
exit(1);
} /* if */
IbpFAdr(vadrStart, 0, sbNil); /* at first instruction */
vfRunAssert = false; /* we don't want assertions during initialization */
ibp = IbpFRun(ptResume);
vfRunAssert = true;
return(ibp);
} /* IbpFNewChild */
/* K I L L C H I L D */
export void KillChild()
{
if (vpid != pidNil) {
ptrace(ptTerm, vpid, 0, 0);
}
vpid = pidNil;
vpc = adrNil;
vsig = 0;
vfp = 0;
if(vfnCore != fnNil) {
GetState(); /* refresh from the core file */
vpc -= 2; /* so we have true address of error */
} /* if */
} /* KillChild */
/* G O T O L N */
export void GotoLn(ln)
int ln;
{
ADRT adr;
adr = AdrFIfdLn(vifd, ln);
if (IpdFAdr(adr) != IpdFAdr(vpc))
UError("You can't goto a line outside of the current procedure");
/* if I can figure it out, it would be nice to be able to unwind the
* stack. We can get the pc, fp, and ap, but the sp seems to be unknown,
* plus the old register values. We might be able to 'goto' each
* procedure end, return up the stack, and keep doing that until we
* get there, but this is involved. Maybe if someone asks REAL nicely....
*/
PutReg(upc, adr);
} /* GotoAdr */
/* I N I T S A */
export void InitSa()
{
/* the 'Q' option shuts up the printout of the signal settings */
SaMaintain(SIGALRM, "srQ"); /* we don't stop, report or eat */
SaMaintain(SIGKILL, "srQ");
SaMaintain(SIGINT, "eQ"); /* we stop, report and eat */
SaMaintain(SIGTRAP, "eQ"); /* we stop, report and eat */
#ifdef BSD41
SaMaintain(SIGCONT, "srQ");
SaMaintain(SIGCHLD, "srQ");
#endif
} /* InitSa */
/* S A M A I N T A I N */
export void SaMaintain(sig, sbOptions)
int sig;
char *sbOptions;
{
pSAR sa;
sa = vmpSigSa + sig;
/* we toggle options based on the flags:
* r = report, s = stop, e = eat signal
*/
if (strchr(sbOptions, 'r'))
sa->fNoReport = ~sa->fNoReport;
if (strchr(sbOptions, 's'))
sa->fNoStop = ~sa->fNoStop;
if (strchr(sbOptions, 'e'))
sa->fEatSig = ~sa->fEatSig;
if (strchr(sbOptions, 'Q') == sbNil) {
printf(" Stop Eat Report Name\n");
printf("%2d %c %c %c ", sig,
(sa->fNoStop) ? 'F':'T',
(sa->fEatSig) ? 'T':'F',
(sa->fNoReport) ? 'F':'T');
PrintSig(sig);
printf("\n");
} /* if */
} /* SaMaintain */
/* L I S T S A */
export void ListSa()
{
int sig;
pSAR sa;
printf(" Stop Eat Report Name\n");
for (sig=1; sig < NSIG; sig++) {
sa = vmpSigSa + sig;
printf("%2d %c %c %c ", sig,
(sa->fNoStop) ? 'F':'T',
(sa->fEatSig) ? 'T':'F',
(sa->fNoReport) ? 'F':'T');
PrintSig(sig);
printf("\n");
} /* for */
} /* ListSa */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.