File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / bin / cdb / pt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.