File:  [MW Coherent from dump] / coherent / b / bin / db / db8.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * db/db8.c
 * A debugger.
 * Child process.
 * All the machine-independent ptrace() code is here.
 */

#include <errno.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/ptrace.h>
#include "db.h"

/*
 * Read 'n' characters starting at address 'a' into the buffer 'bp'
 * from segment 'f' in the child process.
 * Return 1 on success, 0 on failure.
 */
int
getp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n;
{
	int d, n1, pcmd;

	/* Set pcmd to the appropriate ptrace() read command. */
	switch(f) {
	case ISEG:	pcmd = PTRACE_RD_TXT;		break;
	case DSEG:	pcmd = PTRACE_RD_DAT;		break;
	case USEG:	pcmd = PTRACE_RD_USR;		break;
	}

	/* Read in PTSIZE-sized chunks. */
	for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) {
		n1 = (n > PTSIZE) ? PTSIZE : n;
		d = ptrace(pcmd, pid, (int)a, 0);
		if (errno)
			return 0;
		memcpy(bp, &d, n1);
	}
	return 1;
}

/*
 * Infanticide.
 */
void
killc()
{
	reg_flag = R_INVALID;
	if (execflag) {
		ptrace(PTRACE_TERM, pid, 0, 0);
		waitc();
		execflag = 0;
	}
#if	0
	trapstr = NULL;
#endif
}

/*
 * Write 'n' characters from the buffer 'bp'
 * to segment 'f' in the child process starting at address 'a'.
 * Return 1 on success, 0 on failure.
 */
int
putp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n;
{
	int d, n1, pcmd, prcmd;

	/* Set pcmd to the appropriate ptrace() write command. */
	switch(f) {
	case ISEG:	pcmd = PTRACE_WR_TXT;	break;
	case DSEG:	pcmd = PTRACE_WR_DAT;	break;
	case USEG:	pcmd = PTRACE_WR_USR;	break;
	}
	for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) {
		if (n < PTSIZE) {
			/* Read first so write can leave extra bytes unchanged. */
			n1 = n;
			switch(f) {
			case ISEG:	prcmd = PTRACE_RD_TXT;	break;
			case DSEG:	prcmd = PTRACE_RD_DAT;	break;
			case USEG:	prcmd = PTRACE_RD_USR;	break;
			}
			d = ptrace(prcmd, pid, (int)a, 0);
		} else
			n1 = PTSIZE;
		memcpy(&d, bp, n1);
		ptrace(pcmd, pid, (int)a, d);
		if (errno) {
			perror("putp()");
			return 0;
		}
	}
	return 1;
}

/*
 * Run the child and wait for it to stop.
 * Return 0 on error.
 */
int
runc()
{
	register int pcmd;

	switch (step_mode) {
	case SNULL:
	case SWAIT:
		pcmd = PTRACE_RESUME;
		break;
	case SCALL:
	case SCONT:
	case SSTEP:
		pcmd = PTRACE_SSTEP;
		break;
	default:
		panic("invalid step_mode=%d", step_mode);
	}
	errno = 0;
	reg_flag = R_INVALID;
	ptrace(pcmd, pid, 1, 0);
	if (errno) {
		perror("ptrace");
		return 0;
	}
	if (waitc() == 0)
		return 0;
	get_regs(R_SOME);
	return 1;
}

/*
 * Start execution of the child.
 * 'argv' is the argument list,
 * 'ifn' is the name of the input file,
 * 'ofn' is the name of the output file, and
 * 'aflag' tells us whether the output file is opened for append or write.
 */
int
startc(argv, ifn, ofn, aflag) char **argv; char *ifn; char *ofn; int aflag;
{
	register int n;

	reg_flag = R_INVALID;
	if ((pid = fork()) < 0)
		return printr("Cannot fork");
	if (pid == 0) {
		/* Child process. */
		if (ifn != NULL) {
			if ((n=open(ifn, 0)) < 0)
				panic("Cannot open \"%s\"", ifn);
			dup2(n, 0);
			close(n);
		}
		if (ofn != NULL) {
			n = -1;
			if (aflag) {
				if ((n = open(ofn, 1)) >= 0)
					lseek(n, 0L, SEEK_END);
			}
			if (n < 0) {
				if ((n=creat(ofn, 0644)) < 0)
					panic("%s: cannot create", ofn);
			}
			dup2(n, 1);
			close(n);
		}
		ptrace(PTRACE_SETUP, 0, 0, 0);	/* I hear you, Dad... */
		execv(lfn, argv);
		exit(1);
	}
	/* Parent process. */
	if (waitc() == 0)
		return 0;

	/*
	 * Now the child is running, so map the child process rather
	 * than the disk file.
	 * FIX_ME The map addresses for DSEG and ISEG here are bogus.
	 */
	map_init();
	map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD);
	map_set(ISEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD);
	map_set(USEG, MIN_ADDR, (ADDR_T)UPASIZE, (off_t)0, MAP_CHILD);
	execflag = 1;
	get_regs(R_SOME);
	return 1;
}

/*
 * Wait for the child to stop.
 */
int
waitc()
{
	register int p;
	int s;

	while ((p = wait(&s)) != pid) {
		if (p >= 0) {
			printr("Adopted a child %d", p);
			continue;
		}
		if (intflag == 0) {
			execflag = 0;
			return printr("Nonexistent child");
		}
		intflag = 0;
	}
	if ((s & 0xff) != 0x7f) {
		execflag = 0;
		return printr("Child process terminated (0x%X)", (s >> 8) & 0xFF );
	}
	return 1;
}

#if	DBPTRACE
#undef	ptrace
int
dbptrace(cmd, pid, loc, val) int cmd, pid, loc, val;
{
	register int n;

	printf("ptrace(%d, %d, 0x%X, 0x%X) = ", cmd, pid, loc, val);
	n = ptrace(cmd, pid, loc, val);
	printf("0x%X\n", n);
	return n;
}
#endif

/* end of db/db8.c */

unix.superglobalmegacorp.com

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