File:  [MW Coherent from dump] / coherent / b / bin / db_400 / i8086a.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

/*
 *	i8086a.c
 *
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.35
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 */

#include <stdio.h>
#include <sys/param.h>
#include <l.out.h>
#include <signal.h>
#include <sys/ptrace.h>
#include <sys/timeout.h>
#include <sys/uproc.h>
#include "trace.h"
#include "i8086.h"

extern	errno;

#define	MAGICTEST	hdrinfo.magic == L_MAGIC

/*
 * Given an l.out header, set up segmentation for an l.out.
 */
setaseg(ldhp)
register struct ldheader *ldhp;
{
	register long fbase;
	register long si;
	register long pi;
	register long bi;
	register long sd;
	register long pd;
	register long rs;

	fbase = sizeof(*ldhp);
	si = ldhp->l_ssize[L_SHRI];
	pi = ldhp->l_ssize[L_PRVI];
	bi = ldhp->l_ssize[L_BSSI];
	sd = ldhp->l_ssize[L_SHRD];
	pd = ldhp->l_ssize[L_PRVD];
	switch (ldhp->l_flag & (LF_SEP|LF_SHR)) {
	case 0:
		endpure = NULL;
		DSPACE = setsmap(NULL, (long)0, si+pi, fbase,
				getf, putf, 0);
		DSPACE = setsmap(DSPACE, si+pi+bi, sd+pd, fbase+si+pi,
				getf, putf, 0);
		ISPACE = DSPACE;
		break;

	case LF_SHR:
		endpure = NULL;
		rs = (si+sd+0xF) & ~0xF;
		DSPACE = setsmap(NULL, (long)0, si, fbase, getf, putf, 0);
		DSPACE = setsmap(DSPACE, si, sd, fbase+si+pi, getf, putf, 0);
		DSPACE = setsmap(DSPACE, rs, pi, fbase+si, getf, putf, 0);
		DSPACE = setsmap(DSPACE, rs+pi, pd, fbase+si+pi+sd,
				getf, putf, 0);
		ISPACE = DSPACE;
		break;

	case LF_SEP:
		endpure = NULL;
		ISPACE = setsmap(NULL, (long)0, si+pi, fbase, getf, putf, 0);
		DSPACE = setsmap(NULL, (long)0, sd+pd, fbase+si+pi,
				getf, putf, 0);
		break;

	case LF_SEP|LF_SHR:
		endpure = NULL;	/* No pure data */
		rs  = (sd+0xF) & ~0xF;
		ISPACE = setsmap(NULL, (long)0, si+pi, fbase, getf, putf, 0);
		DSPACE = setsmap(NULL, (long)0, sd, fbase+si+pi, getf, putf, 0);
		DSPACE = setsmap(DSPACE, rs, pd, fbase+si+pi+sd, getf, putf, 0);
		break;
	}
}

/*
 * Set up segmentation for kernel memory.
 */
setkmem(np)
char *np;
{
	register off_t l;
	unsigned n;
	struct LDSYM lds;

	cfp = openfil(np, rflag);
	USPACE = setsmap(NULL, (off_t)0, (off_t)LI, (off_t)0,
		getf, putf, 1);
	add = 2;
	if (getb(USEG, &n, sizeof(n)) == 0)
		panic("Bad memory file");
	l = (off_t)n << 4;
	ISPACE = setsmap(NULL, (off_t)0, (off_t)LI, (off_t)l,
		getf, putf, 1);
	strncpy(lds.ls_id, "etext_", NCPLN);
	if (nameval(&lds) == 0)
		DSPACE = ISPACE;
	else {
		n = (lds.ls_addr+0xF) & ~0xF;
		DSPACE = setsmap(NULL, (off_t)0, (off_t)LI, (off_t)l+n,
			getf, putf, 1);
	}
}

/*
 * Set up segmentation for a system dump.
 */
setdump(np)
char *np;
{
	setkmem(np);
}

#if FPTEST
void
fpdump(fstp)
struct _fpstate * fstp;
{
	int i;
	int tagbits;
	unsigned char opfirst, opsecond;
	unsigned int fcs = fstp->cssel;
	int tos = (fstp->sw >> 11) & 7;

	fflush(stdout);

	printf("fstp=%08x  tos=%d  ", fstp, tos);
	opfirst = 0xD8 | ((fcs >> 24) & 7);
	opsecond = fcs >> 16;
	printf("cw=%04x  sw=%04x  tag=%04x\n",
	  fstp->cw&0xFFFF, fstp->sw&0xFFFF, fstp->tag&0xffff);
	printf("op=%02x %02x  fcs=%04x fip=%08x  fos=%04x foo=%08x\n",
	  opfirst, opsecond,
	  fcs&0xFFFF, fstp->ipoff, fstp->datasel&0xFFFF, fstp->dataoff);
	for (i = 0; i < 8; i++) {
		tagbits = (fstp->tag >> (((tos + i) & 7) * 2)) & 3;
		printf("st[%d]:(%d) at %08x ", i, tagbits,
		  fstp->_st + i);
		switch(tagbits) {
		case 0:
			{
			  int j;
			  for (j = 0; j < 4; j++)
			    printf("%04x ", fstp->_st[i].significand[j]);
			  printf(":%04x ", fstp->_st[i].exponent);
			}
			printf("\n");
			break;
		case 1:
			printf("Zero\n");
			break;
		case 2:
			printf("Special: %08x %08x %08x %08x : %08x\n",
			  fstp->_st[i].significand[0],
			  fstp->_st[i].significand[1],
			  fstp->_st[i].significand[2],
			  fstp->_st[i].significand[3],
			  fstp->_st[i].exponent);
			break;
		case 3:
			printf("Empty\n");
			break;
		}
	}
	fflush(stdout);
}
#endif

/*
 * Update register structure in memory.
 */
setregs()
{
	struct ureg ureg;

	regflag = 0;
	add = 0; /* UGLY! FIX THIS! */
	if (getb(USEG, (char *)&ureg, sizeof(ureg)) == 0) {
		printr("Cannot read registers");
		return 0;
	}

#if FPTEST
	fpdump(&ureg.ur_fpstate);
#endif
	copyreg(&ureg);
	regflag = 1;
	return 1;
}

/*
 * Copy registers from the User area structure to the register
 * structure.
 */
copyreg(up)
register struct ureg *up;
{
	reg.r_ax = up->ur_ax;
	reg.r_bx = up->ur_bx;
	reg.r_cx = up->ur_cx;
	reg.r_dx = up->ur_dx;
	reg.r_sp = up->ur_sp;
	reg.r_bp = up->ur_bp;
	reg.r_si = up->ur_si;
	reg.r_di = up->ur_di;
	reg.r_cs = up->ur_cs;
	reg.r_ds = up->ur_ds;
	reg.r_ss = up->ur_ss;
	reg.r_es = up->ur_es;
	reg.r_ip = up->ur_ip;
	reg.r_fw = up->ur_fw;
	reg.r_fs = up->ur_fs;
	reg.r_gs = up->ur_gs;
	reg.valid = 1;
}

/*
 * If the given name matches a register, set up `ldp' with the address
 * of a register in the user area.
 */
regaddr(ldp)
struct LDSYM *ldp;
{
	register char *cp;
	register int c0;
	register int c1;
	register int a;

	a = 0;	/* UGLY!  FIX THIS */
	cp = ldp->ls_id;
	if ((c0=*cp++) == '\0')
		return 0;
	if ((c1=*cp++) == '\0')
		return 0;
	if (*cp != '\0')
		return 0;
	switch (c1) {
	case 'h':
		a++;
	case 'l':
		c1 = 'x';
	}
	cp = regitab;
	do {
		if (cp[0]==c0 && cp[1]==c1) {
			ldp->ls_addr = a;
			ldp->ls_type = L_REG;
			return 1;
		}
		a += 2;
		cp += 2;
	} while (*cp != '\0');
	return 0;
}

/*
 * Return the program counter.
 */
caddr_t
getpc()
{
	return reg.r_ip;
}

/*
 * Set the program counter.
 */
setpc(ip)
caddr_t ip;
{
fprintf(stderr, "setpc(%x)\n", ip);
	reg.r_ip = ip;
	add = PTRACE_EIP;
	putb(USEG, &reg.r_ip, sizeof(reg.r_ip));
}

/*
 * Return the frame pointer.
 */
getfp()
{
	return reg.r_bp;
}

/*
 * Print out a constant in a reasonable format.
 */
concons(sp, l)
register char *sp;
unsigned long l;
{
/* Another bug in unsigned long on the PDP11
	if (l < 0x10)
*/
	if ((unsigned)l < 0x10)
		sprintf(sp, "%d", (int)l);
	else
		sprintf(sp, "0x%lx", l);
}

/*
 * Display registers.
 */
dispreg()
{
	if (testint())
		return;
	if (hdrinfo.defsegatt == DSA16)
		printf("%%ip=%04x %%fw=%04x\n", reg.r_ip, reg.r_fw);
	else 
		printf("%%eip=%08x %%efw=%08x\n", reg.r_ip, reg.r_fw);

	if (testint())
		return;
	if (hdrinfo.defsegatt == DSA16)
		printf("%%ax=%08x %%bx=%08x %%cx=%08x %%dx=%08x\n",
			reg.r_ax, reg.r_bx, reg.r_cx, reg.r_dx);
	else
		printf("%%eax=%08x %%ebx=%08x %%ecx=%08x %%edx=%08x\n",
			reg.r_ax, reg.r_bx, reg.r_cx, reg.r_dx);

	if (testint())
		return;
	if (hdrinfo.defsegatt == DSA16)
		printf("%%sp=%08x %%bp=%08x %%si=%08x %%di=%08x\n",
			reg.r_sp, reg.r_bp, reg.r_si, reg.r_di);
	else
		printf("%%esp=%08x %%ebp=%08x %%esi=%08x %%edi=%08x\n",
			reg.r_sp, reg.r_bp, reg.r_si, reg.r_di);

	if (testint())
		return;
	printf("%%cs=%04x %%ds=%04x %%ss=%04x %%es=%04x %%fs=%04x %%gs=%04x\n",
		reg.r_cs&0xffff, reg.r_ds&0xffff, reg.r_ss&0xffff,
		reg.r_es&0xffff, reg.r_fs&0xffff, reg.r_gs&0xffff);
}

/*
 * Stack traceback.
 */
dispsbt(l)
{
	register int argc;
	register int iflag;
	register int sflag;
	register int qflag;
	unsigned amain;
	unsigned int pc;
	unsigned int rpc;
	unsigned int fp;
	unsigned int n;
	unsigned char e[1];
	unsigned char b[3];
	struct LDSYM ldsym;

	amain = 1;
	strcpy(ldsym.ls_id, MAGICTEST ? "main_" : "main");
	if (nameval(&ldsym) != 0)
		amain = ldsym.ls_addr;
	add = MAGICTEST ? (unsigned short)reg.r_ip : reg.r_ip;
	if (getb(ISEG, b, 1) == 0) {
		printe("Illegal ip");
		return;
	}
	sflag = 0;
	fp = reg.r_bp;
	e[0] = MAGICTEST ? 0x56 : 0xc8;			/* push si : enter */
	if (valname(1, (off_t)reg.r_ip, &ldsym) != 0) {
		add = (long)ldsym.ls_addr;
		getb(ISEG, (char *)e, 1);
	}
	if ( MAGICTEST ? (b[0]==0x56 || e[0]!=0x56)		/* push si */
			: (b[0]==0xc8 || e[0]!=0xc8) ) {	/* enter */
		sflag = 1;
		fp = reg.r_sp - (MAGICTEST ? 6 : 4);
	}
	pc = reg.r_ip;
	qflag = 0;
	for (;;) {
		add = MAGICTEST ? (unsigned short)fp + 6 : fp + 4;
		if (getb(DSEG, &rpc, MAGICTEST ? 2 : 4) == 0)
			break;
		argc = 0;
		add = MAGICTEST ? (unsigned short)rpc : rpc;
		if (getb(ISEG, b, 3) != 0) {
			if (b[0]==0x83 && b[1]==0xC4)	/* add sp,$? */
				argc = b[2]/(MAGICTEST ? 2 : 4);
		}
		add = MAGICTEST ? (unsigned short)rpc - 3 : rpc - 5;
		if (getb(ISEG, b, 1) == 0)
			break;
		if (getb(ISEG, &n, (MAGICTEST ? 2 : 4)) == 0)
			break;
		printx(DAFMT, (long)fp);
		printx("  ");
		printx(DAFMT, (long)pc);
		printx("  ");
		if (b[0] == 0xE8) {			/* call ? */
			n += MAGICTEST ? (unsigned short) rpc : rpc;
			putaddr(1, (long)n, I);
			if (n == amain) {
				qflag = 1;
				argc = 3;
			}
		} else {
			if (valname(1, (off_t)pc, &ldsym) == 0)
				printx("*");
			else {
				printx("%.*s", NCPLN, ldsym.ls_id);
				if (strcmp(ldsym.ls_id
					, MAGICTEST ? "main_" : "main") == 0) {
					qflag = 1;
					argc = 3;
				}
			}
		}
		putx('(');
		iflag = 0;
		add = (MAGICTEST ? (unsigned short)fp : fp) + 8;
			/* offset 8 coincidently works for both file formats */
		while (argc--) {
			if (getb(DSEG, &n, MAGICTEST ? 2 : 4) == 0)
				break;
			if (iflag++ != 0)
				printx(", ");
			putaddr(1, (long)n, -1);
		}
		printx(")\n");
		if (testint())
			return;
		if (qflag)
			break;
		if (sflag) {
			sflag = 0;
			fp = reg.r_bp;
		} else {
			add = MAGICTEST ? (unsigned short)fp : fp;
			if (getb(DSEG, &fp, (MAGICTEST ? 2 : 4)) == 0)
				break;
		}
		if (--l == 0)
			return;
		pc = MAGICTEST ? (unsigned short)rpc : rpc;
	}
}

/*
 * Get the return pc and frame pointer to set a return breakpoint.
 */
setretf(pcp, fpp)
register caddr_t *pcp;
register caddr_t *fpp;
{
	unsigned char b[1];

	add = reg.r_ip;
	if (getb(ISEG, b, sizeof(b)) == 0)
		return 0;
	if (b[0] == 0x56) {			/* push si */
		*fpp = reg.r_bp;
		add = reg.r_sp;
	} else {
		add = reg.r_bp;
		if (getb(DSEG, (char *)fpp, sizeof(*fpp)) == 0)
			return 0;
		add = reg.r_bp + 6;
	}
	if (getb(DSEG, (char *)pcp, sizeof(*pcp)) == 0)
		return 0;
}

/*
 * Initialise after getting a trap.
 */
trapint()
{
	caddr_t pc;
	caddr_t fw;

#if 0
/* new trap handler clears TF in PSW */
	add = PTRACE_EFL;
	if (getb(USEG, &fw, sizeof(int)) == 0) {
		printr("Cannot get psw");
		return 0;
	}
	fw &= ~TBIT;
	add = PTRACE_EFL;
	if (putb(USEG, &fw, sizeof(int)) == 0) {
		printr("Cannot set psw");
		return 0;
	}
#endif
	if (sysflag) {
		add = PTRACE_EIP;
		if (getb(USEG, &pc, sizeof(pc)) == 0) {
			printr("Cannot get eip");
			return 0;
		}
		pc -= 2;
		add = PTRACE_EIP;
		if (putb(USEG, &pc, sizeof(pc)) == 0) {
			printr("Cannot set eip");
			return 0;
		}
		add = (long)pc;
		if (putb(ISEG, (char *)sin, sizeof(sin)) == 0) {
			printr("Cannot set sin");
			return 0;
		}
		bitflag = 1;
	}
	return 1;
}

/*
 * Set up before returning from a trap.  Single stepping over a system
 * call is handled here.
 */
restret()
{
	unsigned char w[1];

	sysflag = 0;
	if (bitflag == 0)
		return 1;
	add = reg.r_ip;
	if (getb(ISEG, (char *)w, sizeof(w)) == 0)
		return 1;

/* FIX THIS FOR 386 */
	if (w[0] != 0xCD)		/* Interrupt (system call) */
		return 1;
	add = reg.r_ip + 2;
	if (getb(ISEG, (char *)sin, sizeof(sin)) == 0) {
		printr("Cannot get breakpoint");
		return 0;
	}
	add -= sizeof(sin);
	if (putb(ISEG, (char *)bin, sizeof(bin)) == 0) {
		printr("Cannot set breakpoint");
		return 0;
	}
	bitflag = 0;
	sysflag = 1;
	return 1;
}

/*
 * Change sinmode to SCSET if instruction at EIP is a call.
 */
setcont()
{
	unsigned char	w[4];
	int	xx;

	add = reg.r_ip;
	if (getb(ISEG, &xx, sizeof(xx)) == 0) {
		return;
	}
	w[0] = xx & 0xff;
	w[1] = (xx>>8) & 0xff;
	if (w[0] == 0xE8) {			/* Direct call */
		sinmode = SCSET;
	}
	if (w[0]==0xFF && (w[1]&0x38)==0x10) {	/* Indirect call */
		sinmode = SCSET;
	}
}

/*
 * Get return address from ESP and set BSIN breakpoint there.
 */
intcont()
{
	unsigned return_addr;

	add = reg.r_sp;
	if (getb(DSEG, &return_addr, sizeof(return_addr))) {
		setibpt(BSIN, return_addr, reg.r_bp, NULL);
	}
}

/*
 * See if the given instruction is a breakpoint.
 */
testbpt(pc)
{
	unsigned char w[1];

	add = pc;
	return (getb(ISEG, w, sizeof(w))!=0 && w[0]==0xCC);
}

/*
 * Read `n' characters into the buffer `bp' starting at address `a'
 * from the traced process, segment `f'.
 */
getp(f, a, bp, n)
long a;
register char *bp;
register int n;
{
	int d, n1;
	char *memcpy();
	int	pcmd;

	for (errno = 0; n; n -= n1, a += n1, bp += n1) {
		n1 =n>sizeof(long) ? sizeof(long) : n;
		switch(f) {
		case ISEG:	pcmd = PTRACE_RD_TXT;	break;
		case DSEG:	pcmd = PTRACE_RD_DAT;	break;
		case USEG:	pcmd = PTRACE_RD_USR;	break;
		}
		d = ptrace(pcmd, pid, (int *) a, 0);
		if (errno)
			return 0;
		memcpy(bp, &d, n1);
	}
	return 1;
}

/*
 * Write `n' characters from the buffer `bp' starting at address `a' in
 * the traced process to segment `f'.
 */
putp(f, a, bp, n)
long a;
register char *bp;
register int n;
{
	int d, n1;
	int	pcmd;

	for (errno = 0; n; n -= n1, a += n1, bp += n1) {
		if (n < sizeof(long)) {
			n1 = n;
			switch(f) {
			case ISEG:	pcmd = PTRACE_RD_TXT;	break;
			case DSEG:	pcmd = PTRACE_RD_DAT;	break;
			case USEG:	pcmd = PTRACE_RD_USR;	break;
			}
			d = ptrace(pcmd, pid, (int *)a, 0);
		} else
			n1 = sizeof(long);
		memcpy(&d, bp, n1);
		switch(f) {
		case ISEG:	pcmd = PTRACE_WR_TXT;	break;
		case DSEG:	pcmd = PTRACE_WR_DAT;	break;
		case USEG:	pcmd = PTRACE_WR_USR;	break;
		}
		ptrace(pcmd, pid, (int *) a, d);
		if (errno) {
			perror("db: putp()");
			return 0;
		}
	}
	return 1;
}

/******************************************************************************
 *
 * Note some #defines in these include files interferes with
 * items in preceeding include files. Hence the strange
 * program order.
 *
 ******************************************************************************/

#include <coff.h>

/*
 * Given an l.out header, set up segmentation for an l.out.
 */
setcoffseg(fp, coffhp)
FILE	*fp;
FILEHDR *coffhp;
{
	off_t	fbase, tbase, tsize, dbase, dsize, bbase, bsize;
	off_t	f_tscnp, f_dscnp, f_bscnp;
	SCNHDR	*scnhp;
	short	i;

	if (coffhp->f_opthdr)
		fbase = sizeof(FILEHDR) + coffhp->f_opthdr;
	else
		fbase = sizeof (FILEHDR);
	if ( (scnhp=nalloc(coffhp->f_nscns*sizeof(SCNHDR))) == NULL ) {
		printf("No memory to alloc to coff.h section headers");
		return;
	}

	fseek(fp, fbase, 0);
	for (i=0; i<coffhp->f_nscns; scnhp++, i++) {
		if (fread(scnhp, sizeof(SCNHDR), 1, fp) != 1)
			printf("Cannot read coff.h section headers");

		switch((int)scnhp->s_flags) {
		case STYP_TEXT:
			tbase = scnhp->s_vaddr;
			tsize = scnhp->s_size;
			f_tscnp = scnhp->s_scnptr; 
			break;
		case STYP_DATA:
			dbase = scnhp->s_vaddr;
			dsize = scnhp->s_size;
			f_dscnp = scnhp->s_scnptr; 
			break;
		case STYP_BSS:
			bbase = scnhp->s_vaddr;
			bsize = scnhp->s_size;
			f_bscnp = scnhp->s_scnptr; 
			break;
		default:
			continue;
		}
	}

#if 0	/* Assume NOT separate */
	endpure = NULL;
	DSPACE = setsmap(NULL, tbase, tsize, f_tscnp, getf, putf, 0);
/*	dbase = (dbase + (off_t)0xF) & ~(off_t)0xF;
*/	DSPACE = setsmap(DSPACE, dbase, dsize, f_dscnp, getf, putf, 0);
	DSPACE = setsmap(DSPACE, bbase, bsize+4L, f_bscnp, getf, putf, 0);
	ISPACE = DSPACE;

#else	/* Assume separate */
	endpure = NULL;
	ISPACE = setsmap(NULL, tbase, tsize, f_tscnp, getf, putf, 0);
/*	dbase = (dbase + (off_t)0xF) & ~(off_t)0xF;
*/	DSPACE = setsmap(NULL, dbase, dsize, f_dscnp, getf, putf, 0);
	DSPACE = setsmap(DSPACE, bbase, bsize+4L, f_bscnp, getf, putf, 0);
#endif
	nfree(scnhp);
}

/* end of i8086a.c */

unix.superglobalmegacorp.com

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