[comp.os.minix] adb

ast@cs.vu.nl (Andy Tanenbaum) (05/30/88)

This is a reposting of Don Dugger's adb.  It really isn't quite finished
enough to include in 1.3, unless some person with an interest in adb works
on it real fast (hint).

Andy Tanenbaum (ast@cs.vu.nl)

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'adb.c'
sed 's/^X//' > 'adb.c' << '+ END-OF-FILE ''adb.c'
X#include <stdio.h>
X#include "adb.h"
X
Xstruct file binary;
Xstruct file core;
X
Xlong dot;
Xint dotoff;
Xint maxoff = 256;
Xint ibase = 16;
X
Xint lastc = 0;
Xchar lbuf[128];
Xchar *bufp = lbuf;
Xchar sign = 0;
X
Xint mode = 0;
Xint buffer = 0;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char *cp;
X
X	binary.symptr = 0;
X	core.symptr = 0;
X	while (argc > 1 && argv[1][0] == '-') {
X		for (cp = &argv[1][1]; *cp; )
X			switch (*cp++) {
X
X			case 'b':
X				buffer++;
X				break;
X			case 'w':
X				mode = 2;
X				break;
X			case 'm':
X				setsym(argv[2]);
X				argc--;
X				argv++;
X				break;
X			default:
X				printf("%c:unknown flag\n", cp[-1]);
X				break;
X
X			}
X		argc--;
X		argv++;
X	}
X	if (argc > 1) {
X		binary.name = argv[1];
X		core.name = argv[1];
X	}
X	if (argc > 2)
X		core.name = argv[2];
X	if ((binary.fid = open(binary.name, mode)) < 0) {
X		printf("%s:cannot open\n", binary.name);
X		exit(1);
X	}
X	if ((core.fid = open(core.name, mode)) < 0) {
X		printf("%s:cannot open\n", core.name);
X		exit(2);
X	}
X	setobj(&binary);
X	setcor(&core);
X	adb();
X}
Xsetobj(fp)
Xstruct file *fp;
X{
X	struct fheader hdr;
X
X	fp->b1 = 0;
X	fp->e1 = -1;
X	fp->f1 = 0;
X	fp->b2 = 0;
X	fp->e2 = -1;
X	fp->f2 = 0;
X	fp->cblock = -1;
X	lseek(fp->fid, (long)0, 0);
X	if (read(fp->fid, &hdr, sizeof(hdr)) != sizeof(hdr))
X		return;
X	if (hdr.magic != MAGIC && hdr.magic != IDMAGIC)
X		return;
X	fp->b1 = 0;
X	fp->e1 = hdr.tsize;
X	fp->f1 = sizeof(hdr);
X	fp->b2 = hdr.tsize;
X	fp->e2 = hdr.tsize + hdr.dsize;
X	fp->f2 = hdr.tsize + hdr.tsize;
X	return;
X}
Xsetcor(fp)
Xstruct file *fp;
X{
X
X	fp->b1 = 0;
X	fp->e1 = -1;
X	fp->f1 = 0;
X	fp->b2 = 0;
X	fp->e2 = 0;
X	fp->f2 = 0;
X	fp->cblock = -1;
X	return;
X}
Xadb()
X{
X	int cmddol(), cmdcol(), cmdprt(), cmdwrt(), null();
X	long getn(), getdot();
X	long expr();
X	register int c, lc, count;
X	int (*f)();
X	long (*g)();
X	char fmt[128];
X
X	f = cmdprt;
X	g = getdot;
X	lc = '=';
X	dot = 0;
X	dotoff = 0;
X	for (;;) {
X		if ((c = peekc()) == '(' || c == '.' || (type(c) & ALPHANUM)) {
X			dot = expr();
X			dotoff = 0;
X		}
X		if (peekc() == ',') {
X			nb();
X			count = expr();
X		} else
X			count = 1;
X		switch (c = nb()) {
X
X		case EOF:
X			return;
X		case '$':
X			f = cmddol;
X			break;
X		case ':':
X			f = cmdcol;
X			break;
X		case '?':
X		case '/':
X			g = getn;
X			switch (peekc()) {
X
X			case 'w':
X			case 'W':
X				f = cmdwrt;
X				break;
X			default:
X				f = cmdprt;
X				getfmt(fmt);
X			case '\n':
X				break;
X
X			}
X			break;
X		case '=':
X			f = cmdprt;
X			g = getdot;
X			getfmt(fmt);
X			break;
X		case '\r':
X		case '\n':
X			c = lc;
X			dot += dotoff;
X			break;
X		default:
X			f = null;
X			count = 1;
X			break;
X
X		}
X		dotoff = 0;
X		while (count--)
X			(*f)(c, fmt, g);
X		lc = c;
X		while (getchr() != '\n')
X			;
X	}
X}
Xgetchr()
X{
X	register int c;
X
X	if (lastc) {
X		c = lastc;
X		lastc = 0;
X	} else
X		c = getchar();
X	return(c);
X}
Xpushc(c)
Xint c;
X{
X
X	lastc = c;
X	return(c);
X}
Xpeekc()
X{
X
X	return(pushc(nb()));
X}
Xnb()
X{
X	register int c;
X
X	while ((c = getchr()) == ' ' || c == '\t')
X		;
X	if (c == '\n')
X		pushc(c);
X	return(c);
X}
Xtype(c)
Xchar c;
X{
X
X	if (c >= '0' && c <= '9')
X		return(NUMERIC);
X	if (c >= 'a' && c <= 'f')
X		return(HEX);
X	if (c >= 'A' && c <= 'F')
X		return(HEX);
X	if (c >= 'g' && c <= 'z')
X		return(ALPHA);
X	if (c >= 'G' && c <= 'Z')
X		return(ALPHA);
X	if (c == '_')
X		return(ALPHA);
X	return(SPEC);
X}
X	long
Xexpr()
X{
X	long term();
X	long r;
X	int c;
X
X	r = term();
X	for (;;)
X		switch (c = nb()) {
X
X		case '+':
X			r += term();
X			break;
X		case '-':
X			r -= term();
X			break;
X		case '*':
X			r *= term();
X			break;
X		case '%':
X			r /= term();
X			break;
X		case ')':
X		default:
X			pushc(c);
X			return(r);
X
X		}
X}
X	long
Xterm()
X{
X	long n;
X	register int c, base;
X	char *cp, buf[80];
X	struct symbol *sp, *findnam();
X
X	if ((c = nb()) == '(') {
X		n = expr();
X		if (nb() != ')')
X			putchr('?');
X		return(n);
X	} else if (c == '\'') {
X		n = 0;
X		while ((c = getchr()) != '\'')
X			if (c == '\n') {
X				pushc(c);
X				break;
X			} else
X				n = (n << 8) | c;
X		return(n);
X	} else if (c == '.' || (type(c) & ALPHAONLY)) {
X		cp = buf;
X		*cp++ = c;
X		if (c == '.')
X			if (type(pushc(getchr())) == SPEC)
X				return(dot);
X		while (type(c = getchr()) & ALPHANUM)
X			*cp++ = c;
X		*cp = '\0';
X		pushc(c);
X		if (sp = findnam(buf, binary.symptr))
X			return(sp->value);
X		else if (sp = findnam(buf, core.symptr))
X			return(sp->value);
X		pushc('@');
X		return(0);
X	}
X	n = 0;
X	base = ibase;
X	if (c == '0') {
X		base = 8;
X		switch (pushc(getchr())) {
X
X		case 'x':
X			base += 6;
X		case 't':
X			base += 2;
X		case 'o':
X			getchr();
X			c = getchr();
X			break;
X		default:
X			base = ibase;
X			break;
X
X		}
X	}
X	while (type(c) & HEXDIG) {
X		if (c >= 'a' && c <= 'f')
X			c -= 'a' - '9' - 1;
X		if (c >= 'A' && c <= 'F')
X			c -= 'A' - '9' - 1;
X		n = (n * base) + (c - '0');
X		c = getchr();
X	}
X	pushc(c);
X	return(n);
X}
Xnull(c, fmt, get)
Xint c;
Xchar *fmt;
Xlong (*get)();
X{
X
X	printf("?\n");
X	return(0);
X}
Xcmdcol(c, fmt, get)
Xint c;
Xchar *fmt;
Xlong (*get)();
X{
X
X	printf("?\n");
X	return(0);
X}
Xcmddol(c, fmt, get)
Xint c;
Xchar *fmt;
Xlong (*get)();
X{
X
X	switch (c = nb()) {
X
X	case 'm':
X	case 'M':
X		prtmap('?', &binary);
X		prtmap('/', &core);
X		break;
X	case 'q':
X		exit(0);
X	case 'd':
X		ibase = 10;
X		break;
X	case 'o':
X		ibase = 8;
X		break;
X	case 'x':
X		ibase = 16;
X		break;
X	case 's':
X		maxoff = dot;
X		break;
X	default:
X		pushc(c);
X		putchr('?');
X		putchr('\n');
X		break;
X
X	}
X	return(0);
X}
Xprtmap(c, fp)
Xchar c;
Xstruct file *fp;
X{
X
X	printf("%c\t%s\n", c, fp->name);
X	putx(fp->b1, 10);
X	putx(fp->e1, 10);
X	putx(fp->f1, 10);
X	putchr('\n');
X	putx(fp->b2, 10);
X	putx(fp->e2, 10);
X	putx(fp->f2, 10);
X	putchr('\n');
X	return;
X}
Xcmdwrt(c, fmt, get)
Xchar c;
Xchar *fmt;
Xlong (*get)();
X{
X	long l;
X	struct file *fp;
X
X	if (mode != 2) {
X		prt("not is write mode\n");
X		return;
X	}
X	fp = (c == '?') ? &binary : &core;
X	c = nb();
X	l = expr();
X	putn(l, dot + dotoff, c == 'w' ? 2 : 4, fp);
X	return;
X}
Xcmdprt(c, fmt, get)
Xint c;
Xchar *fmt;
Xlong (*get)();
X{
X	register int c1;
X	long *ip;
X	struct file *fp;
X	struct symbol *sp, *findsym();
X
X	fp = (c == '?') ? &binary : &core;
X	while (c = *fmt++)
X		switch (c) {
X
X		case 'a':
X		case 'p':
X			if ((sp = findsym((int)(dot + dotoff), binary.symptr)) ||
X				(sp = findsym((int)(dot + dotoff), core.symptr)))
X					prtsym((int)(dot + dotoff), sp);
X				else
X					putx(dot + dotoff, 8);
X			if (c == 'p')
X				break;
X			putchr(':');
X			putchr('\t');
X			break;
X		case 'i':
X			if (get == getdot) {
X				putchr('?');
X				break;
X			}
X			puti(fp);
X			if (*fmt)
X				putchr('\n');
X			break;
X		case 'm':
X		case 'M':
X			if (get == getdot) {
X				putchr('?');
X				break;
X			}
X			ip = c == 'm' ? fp->tmap : fp->dmap;
X			for (c1 = 0; c1 < 3; c1++) {
X				if (peekc() == '\n')
X					break;
X				*ip++ = expr();
X			}
X			return;
X		case 'o':
X			puto((*get)(dot + dotoff, 2, fp) & 0xffff, 6);
X			break;
X		case 'O':
X			puto((*get)(dot + dotoff, 4, fp), 12);
X			break;
X		case 'd':
X			putd((*get)(dot + dotoff, 2, fp), 6);
X			break;
X		case 'D':
X			putd((*get)(dot + dotoff, 4, fp), 11);
X			break;
X		case 'x':
X			putx((*get)(dot + dotoff, 2, fp) & 0xffff, 4);
X			break;
X		case 'X':
X			putx((*get)(dot + dotoff, 4, fp), 8);
X			break;
X		case 'b':
X			puto((*get)(dot + dotoff, 1, fp) & 0xff, 4);
X			break;
X		case 'c':
X			putchr((char)(*get)(dot + dotoff, 1, fp));
X			break;
X		case 'S':
X		case 's':
X			while (c1 = (char)(*get)(dot + dotoff, 1, fp)) {
X				if ((c1 < ' ' || c1 > 127) && (c == 'S'))
X					c1 = '.';
X				putchr(c1);
X			}
X			break;
X		case '"':
X			while ((c = *fmt++) != '"' && c)
X				putchr(c);
X			if (c != '"')
X				fmt--;
X			break;
X		default:
X			putchr(c);
X			break;
X
X		}
X	putchr('\n');
X	return;
X}
Xgetfmt(fmt)
Xchar *fmt;
X{
X	char c;
X
X	if ((c = peekc()) == 'm' || c == 'M' || c == '*') {
X		nb();
X		if (c == '*')
X			if ((c = nb()) != 'm' && c != 'M') {
X				pushc(c);
X				c = '?';
X			} else
X				c = 'M';
X		else
X			c = 'm';
X		*fmt++ = c;
X		*fmt++ = '\0';
X		return;
X	}
X	while ((*fmt = getchr()) != '\n')
X		fmt++;
X	*fmt = '\0';
X	pushc('\n');
X	return;
X}
X	long
Xgetdot(d, n, fp)
Xlong d;
Xint n;
Xstruct file *fp;
X{
X	long l;
X
X	l = dot;
X	if (n == 2)
X		l &= 0xffff;
X	else if (n == 1)
X		l &= 0xff;
X	return(l);
X}
X	unsigned char
Xgetb(fp)
Xstruct file *fp;
X{
X
X	return(getn(dot + dotoff, 1, fp));
X}
X	unsigned int
Xgetw(fp)
Xstruct file *fp;
X{
X
X	return(getn(dot + dotoff, 2, fp));
X}
Xputn(v, d, n, fp)
Xlong v, d;
Xint n;
Xstruct file *fp;
X{
X	long b, no;
X	register int o;
X	char *p;
X
X	if (d >= fp->b1 && d < fp->e1)
X		d += fp->f1 - fp->b1;
X	else if (d >= fp->b2 && d < fp->e2)
X		d += fp->f2 - fp->b2;
X	b = d >> LOGBS;
X	o = d & (BSIZE - 1);
X	if (buffer) {
X		if (fp->cblock != b) {
X			fp->cblock = b;
X			lseek(fp->fid, b << LOGBS, 0);
X			read(fp->fid, fp->buf, sizeof(fp->buf));
X		}
X	} else {
X		lseek(fp->fid, d, 0);
X		read(fp->fid, &fp->buf[o], n);
X	}
X	p = &fp->buf[o];
X	dotoff += n;
X	switch (n) {
X
X	case 2:
X		putx(((long)*(int *)p) & 0xffff, 4);
X		prt(" =");
X		putx(v & 0xffff, 4);
X		putchr('\n');
X		*(int *)p = v;
X		break;
X	case 4:
X		putx(*(long *)p, 8);
X		prt(" =");
X		putx(v, 8);
X		putchr('\n');
X		*(long *)p = v;
X		break;
X
X	}
X	if (buffer) {
X		lseek(fp->fid, b << LOGBS, 0);
X		write(fp->fid, fp->buf, sizeof(fp->buf));
X	} else {
X		lseek(fp->fid, d, 0);
X		write(fp->fid, &fp->buf[o], n);
X	}
X	return;
X}
X	long
Xgetn(d, n, fp)
Xlong d;
Xint n;
Xstruct file *fp;
X{
X	long b, no;
X	register int o;
X	char *p;
X
X	if (d >= fp->b1 && d < fp->e1)
X		d += fp->f1 - fp->b1;
X	else if (d >= fp->b2 && d < fp->e2)
X		d += fp->f2 - fp->b2;
X	b = d >> LOGBS;
X	o = d & (BSIZE - 1);
X	if (buffer) {
X		if (fp->cblock != b) {
X			fp->cblock = b;
X			lseek(fp->fid, b << LOGBS, 0);
X			read(fp->fid, fp->buf, sizeof(fp->buf));
X		}
X	} else {
X		lseek(fp->fid, d, 0);
X		read(fp->fid, &fp->buf[o], n);
X	}
X	p = &fp->buf[o];
X	dotoff += n;
X	switch (n) {
X
X	case 1:
X		no = *p;
X		break;
X	case 2:
X		no = *(int *)p;
X		break;
X	case 4:
X		no = *(long *)p;
X		break;
X
X	}
X	return(no);
X}
Xputo(n, s)
Xunsigned long n;
Xint s;
X{
X
X	if (n > 0)
X		puto((n >> 3) & 0x1fffffff, --s);
X	else
X		while (s-- > 0)
X			putchr(' ');
X	putchr((char)((n & 7) + '0'));
X	return;
X}
Xputd(n, s)
Xlong n;
Xint s;
X{
X
X	if (n < 0) {
X		s--;
X		n = -n;
X		if (n < 0) {
X			while (s-- > 0)
X				putchr(' ');
X			putchr('?');
X			return;
X		} else
X			sign = '-';
X	}
X	if (n > 9)
X		putd(n / 10, --s);
X	else
X		while (s-- > 0)
X			putchr(' ');
X	if (sign) {
X		putchr(sign);
X		sign = 0;
X	}
X	putchr((char)((n % 10) + '0'));
X	return;
X}
Xputx(n, s)
Xunsigned long n;
Xint s;
X{
X
X	if (n > 0xf)
X		putx((n >> 4) & 0xfffffff, --s);
X	else
X		while (s-- > 0)
X			putchr(' ');
X	putchr("0123456789abcdef"[n & 0xf]);
X	return;
X}
Xprt(s)
Xchar *s;
X{
X
X	while (*s)
X		putchr(*s++);
X	return;
X}
Xputchr(c)
Xchar c;
X{
X
X	*bufp++ = c;
X	if (c == '\n' || bufp > &lbuf[70]) {
X		write(1, lbuf, bufp - lbuf);
X		bufp = lbuf;
X	}
X	return(c);
X}
Xsetsym(mn)
Xchar *mn;
X{
X	FILE *fd;
X	char buf[80];
X
X	if ((fd = fopen(mn, "r")) == NULL) {
X		printf("%s:cannot open\n", mn);
X		return;
X	}
X	while (fgets(buf, sizeof(buf), fd))
X		switch(buf[0]) {
X
X		case 'T':
X			addsym(&binary.symptr, buf);
X			break;
X		case 'A':
X		case 'D':
X		case 'B':
X			addsym(&core.symptr, buf);
X			break;
X
X		}
X	return;
X}
Xaddsym(sp, cp)
Xstruct symbol *sp;
Xchar *cp;
X{
X	unsigned int v;
X	char *cptr;
X	struct symbol *p;
X
X	v = htoi(cp + 2);
X	while (sp->next)
X		if (sp->next->value > v)
X			break;
X		else
X			sp = sp->next;
X	p = (struct symbol *)malloc(sizeof(*p));
X	p->next = sp->next;
X	sp->next = p;
X	p->value = v;
X	cp += 7;
X	cptr = p->name;
X	while ((type(*cp) & ALPHANUM) || *cp == '.')
X		*cptr++ = *cp++;
X	*cptr = '\0';
X	return;
X}
X	struct symbol *
Xfindnam(cp, sp)
Xchar *cp;
Xstruct symbol *sp;
X{
X
X	while (sp)
X		if (strcmp(cp, sp->name) == 0)
X			return(sp);
X		else
X			sp = sp->next;
X	return(0);
X}
X	struct symbol *
Xfindsym(v, sp)
Xunsigned int v;
Xstruct symbol *sp;
X{
X	struct symbol *lp;
X
X	lp = sp;
X	while (sp)
X		if (sp->value > v)
X			break;
X		else {
X			lp = sp;
X			sp = sp->next;
X		}
X	if (lp && v >= lp->value && v < lp->value + maxoff)
X		return(lp);
X	return(0);
X}
Xhtoi(cp)
Xchar *cp;
X{
X	int n;
X	char c;
X
X	n = 0;
X	while (type(c = *cp++) & HEXDIG) {
X		if (c >= 'a' && c <= 'f')
X			c -= 'a' - '9' - 1;
X		else if (c >= 'A' && c <= 'F')
X			c -= 'A' - '9' - 1;
X		n = (n << 4) + (c - '0');
X	}
X	return(n);
X}
Xprtsym(v, sp)
Xunsigned int v;
Xstruct symbol *sp;
X{
X
X	prt(sp->name);
X	if (v != sp->value) {
X		putchr('+');
X		putx((long)(v - sp->value), 0);
X	}
X	return;
X}
+ END-OF-FILE adb.c
chmod 'u=rw,g=r,o=r' 'adb.c'
set `wc -c 'adb.c'`
count=$1
case $count in
12095)	:;;
*)	echo 'Bad character count in ''adb.c' >&2
		echo 'Count should be 12095' >&2
esac
echo Extracting 'adb.doc'
sed 's/^X//' > 'adb.doc' << '+ END-OF-FILE ''adb.doc'
XNAME
X	adb - absolute debugger
X
XSYNOPSIS
X	adb [ -w ] [ -b ] [ -m map ] a.out [ core ]
X
XDESCRIPTION
X
XThis is a rewritten version of adb for MINIX.  It can
Xbe used to examine and/or write binary files, especially a.out
Ximages and core dumps.  The command line parameters (those inclosed
Xin brackets are optional) are:
X
X-w	Normally, files cannot be written.  This flag enables the
X	writing capabilities of `adb'.
X-b	Files are read and written 1 to 4 bytes at a time.  Since
X	this is rather slow the `b' flag causes the file data to be
X	buffered 1024 bytes at a time.  This will normally speed
X	things up but if you are examining time sensitive data, such
X	as the contents of `/dev/kmem', you should not use this flag.
X-m	Indicates that `map' is a load map associated with file `a.out'.
Xa.out	The a.out image that is to be examined.
Xcore	An optional core dump associated with `a.out'.  (Currently
X	`adb' does not recognize core dumps so this parameter just allows
X	2 different files to be examined at the same time.)
X
XThe commands to `adb' normally consist of the fields:
X	[address][,count][file][format]
XEach field is optional and except for `count' keeps its prior value if
Xomitted.  `count' takes the value 1 if it is omitted.
X
XAn address can be:
X
Xnnn	An absolute number in the default base.  The default base starts
X	out at 16.
X0xn	A hexadecimal number.
X0on	An octal number.  That is zero followed by the letter o.
X0tn	A decimal number.
Xsymbol	A symbol from the load map.  Only external symbols are recognized
X	and all `C' language symbols have a leading `_' that must be
X	specified, e.g. `_main' is the symbol for the main routine.
X.	The period (dot) represents the current address to `adb'.
X
XAddresses and counts can be formed from arithmetic expressions made from
Xaddress quantities.  The following operators have equal precedence but can
Xbe grouped with parenthesis:
X
X+	Addition
X-	Subtraction
X*	Multiplication
X%	Division
X
XThe `file' field identifies which file from which to read the data.
X
X?	Data from/to a.out
X/	Data from/to core.
X=	Don't use a file, instead the address field specifies the data
X	rather than the address of the data.
X$	Special commands to `adb' unrelated to the files.
X:	Process control commands.  (Currently unimplemented.)
X
X`format' specifies how the data in the specified file will be
Xprinted.  It consists of a string of format characters.  If more
Xthan one format character is given then successive data from
Xthe file will be printed.  The current format characters are:
X
Xx	2-byte hexadecimal integer
XX	4-byte hexadecimal integer
Xo	2-byte octal integer
XO	4-byte octal integer
Xd	2-byte decimal integer
XD	4-byte decimal integer
Xb	1-byte octal integer
Xi	print as an 8086 instruction
Xp	print the current address.  If a map was specified it will
X	be printed as a positive offset from the closest symbol.
Xa	same as `a' only a `:\t' will follow the address.
Xc	one character
Xs	string of characters terminated by a 0 byte.
XS	string of characters terminated by a 0 byte.  Unprintable
X	ASCII characters show as a period.
X"ss"	print the enclosed string.  There are no escapes, you can't
X	print a ".
X
XThe special commands, indicated by a file field of `$', are:
X
Xq	quit
Xd	set the default base to 10.
Xo	set the default base to 8.
Xx	set the default base to 16.
Xs	set the `symbol offset' match to the current address.  Under the
X	`a' and `p' format characters I lied.  Addresses are only printed
X	as symbol plus offset if the address if closer than `symbol offset'
X	from the nearest external symbol.  This command allows you to change
X	that `symbol offset', which defaults to 256, to a different value.
Xm	print the current address maps.  Address maps are described later.
XM	same as `m'.
X
XA new-line alone is a special command.  This command means increment
Xthe current address by the size of the current format and then print
Xdata from the current file with the current format.
X
XIn order to write 2 bytes to a file use the command:
X	[address][,count][file]w value
Xwhere `value' is an arithmetic expression.  To write 4 bytes use a `W'
Xrather than a `w'.  This command can only be used if the `-w' flag was
Xgiven on the command line.
X
X`adb' maintains 2 address maps for both the a.out and core files.  These
Xmaps are needed because program virtual addresses are not one-to-one with
Xfile addresses for either an a.out image or a core dump.  To deal with
Xthis `adb' maintains two 3-tuples for both files.  The 3-tuples are:
X
Xb1,b2	first program virtual address
Xe1,e2	ending program virtual address
Xf1,f2	file offset
X
XTo map between program virtual addresses and file addresses, `adb'
Xapplies the following 3 rules:
X
X1:	if b1 <= address < e1 then file address = address - b1 + f1
X
X2:	if b2 <= address < e2 then file address = address - b2 + f2
X
X3:	otherwise file address = address
X
XTo change the mapping numbers for `a.out' use the commands
X
X?m b1 e1 f1
X?*m b2 e2 f2
X
Xwhere `b1', `e1', `f1', `b2', `e2', and `f2' are the new values for
Xthe associated map numbers.
X
XLikewise, to change the mapping numbers for `core' use the commands
X
X/m b1 e1 f1
X/*m b2 e2 f2
X
XEXAMPLES
X
X100,3/X		starting at location 100 print 3 4-byte integers in hex.
X
X100/XXX		same thing as prior command
X
X_main?aiiii	starting at `main' print the current address and then
X		decode 4 instructions
X
X0t100$s		set the `symbol offset' to 100 decimal
X
X100/X		print the 4-byte integer at 100 in hex
X./W 0x123	write 0x123 to the 4 bytes starting at 100
X
X1+2*3=D		print the expression (1+2)*3 in decimal
X1+(2*3)=x	print the expression 1+(2*3) in hex.
X1000=p		print nearest symbol to 1000.
X
XCAVEATS
X
XThe instruction decode is my interpretation of INTEL's encoding scheme.
XIt has not been tested for all valid instructions so I'm sure there are
Xsome glitches in it.
+ END-OF-FILE adb.doc
chmod 'u=rw,g=r,o=r' 'adb.doc'
set `wc -c 'adb.doc'`
count=$1
case $count in
5731)	:;;
*)	echo 'Bad character count in ''adb.doc' >&2
		echo 'Count should be 5731' >&2
esac
echo Extracting 'adb.h'
sed 's/^X//' > 'adb.h' << '+ END-OF-FILE ''adb.h'
X#define NUMERIC		3
X#define HEX		7
X#define ALPHA		5
X#define SPEC		8
X
X#define ALPHANUM	1
X#define HEXDIG		2
X#define ALPHAONLY	4
X
X#define BSIZE		512
X#define LOGBS		9
X#define SYMSZ		10
X
Xstruct symbol {
X	struct symbol *	next;
X	unsigned int	value;
X	char			name[SYMSZ];
X};
X
Xstruct file {
X	int	fid;
X	char *	name;
X	struct symbol *symptr;
X	long	cblock;
X	long	tmap[3];
X	long	dmap[3];
X	char	buf[BSIZE + BSIZE];
X};
X
X#define b1	tmap[0]
X#define e1	tmap[1]
X#define f1	tmap[2]
X#define b2	dmap[0]
X#define e2	dmap[1]
X#define f2	dmap[2]
X
Xstruct fheader {
X	long	magic;
X	long	flag;
X	long	tsize;
X	long	dsize;
X	long	bsize;
X	long	entry;
X	long	size;
X	long	fill;
X};
X#define MAGIC	0x04100301L
X#define IDMAGIC	0x04200301L
+ END-OF-FILE adb.h
chmod 'u=rw,g=r,o=r' 'adb.h'
set `wc -c 'adb.h'`
count=$1
case $count in
692)	:;;
*)	echo 'Bad character count in ''adb.h' >&2
		echo 'Count should be 692' >&2
esac
echo Extracting 'makefile'
sed 's/^X//' > 'makefile' << '+ END-OF-FILE ''makefile'
XOBJ=adb.s optab.s
X
XCFLAGS=-c -T.
X
X.c.s:
X	cc $(CFLAGS) $*.c
X
Xadb:	$(OBJ)
X	rm /lib/cpp /lib/cem
X	cc -T. $(OBJ)
+ END-OF-FILE makefile
chmod 'u=rw,g=r,o=r' 'makefile'
set `wc -c 'makefile'`
count=$1
case $count in
109)	:;;
*)	echo 'Bad character count in ''makefile' >&2
		echo 'Count should be 109' >&2
esac
echo Extracting 'optab.c'
sed 's/^X//' > 'optab.c' << '+ END-OF-FILE ''optab.c'
X#include "adb.h"
X
Xint i_normal(), i_incdec(), i_ill(), i_jmp(), i_immed();
Xint i_mov(), i_movi(), i_movs();
Xint i_misc1(), i_misc2(), i_misc3();
Xint i_string(), i_xchg(), i_shift(), i_esc();
Xint i_ioi(), i_ior(), i_monad(), i_misc4();
X
Xextern long dot;
Xextern int dotoff;
Xextern struct file binary;
Xextern struct file core;
X
Xstruct symbol *findsym();
Xlong getn();
Xunsigned char getb();
Xunsigned int getw();
X
Xchar *mon0[] = { "add",	"push\tes",	"pop\tes" };
Xchar *mon1[] = { "or",	"push\tcs",	"???" };
Xchar *mon2[] = { "adc",	"push\tss",	"pop\tss" };
Xchar *mon3[] = { "sbb",	"push\tds",	"pop\tds" };
Xchar *mon4[] = { "and",	"es:",		"daa" };
Xchar *mon5[] = { "sub",	"cs:",		"das" };
Xchar *mon6[] = { "xor",	"ss:",		"aaa" };
Xchar *mon7[] = { "cmp",	"ds:",		"aas" };
Xchar *mon8[] = {
X	"add",	"or",	"adc",	"sbb",
X	"and",	"sub",	"xor",	"cmp"
X};
Xchar *mon9[] = {
X	"jo",	"jno",	"jb",	"jnb",
X	"je",	"jne",	"jna",	"ja"
X};
Xchar *mon10[] = {
X	"js",	"jns",	"jp",	"jnp",
X	"jl",	"jnl",	"jng",	"jg"
X};
Xchar *mon11[] = {
X	"cbw",	"cwd",	"call",	"wait",
X	"pushf",	"popf",	"sahf",	"lahf"
X	};
Xchar *mon12[] = {
X	"mov",	"mov",	"mov",	"mov",
X	"movs",	"movs",	"cmps",	"cmps"
X	};
Xchar *mon13[] = {
X	"test\tal",	"test\tax",	"stosb",	"stosw",
X	"lodsb",	"lodsw",	"scasb",	"scasw"
X};
Xchar *mon14[] = {
X	"rol",	"ror",	"rcl",	"rcr",
X	"shl",	"shr",	"???",	"sar"
X};
Xchar *mon15[] = {
X	"loopne\t",	"loope\t",	"loop\t",	"jcxz\t",
X	"in\tal",	"in\tax",	"out\tal",	"out\tax"
X};
Xchar *mon16[] = {
X	"lock",	"???",	"repne",	"rep",
X	"hlt",	"cmd"
X};
Xchar *mon17[] = {
X	"clc",	"stc",	"cli",	"sti",
X	"cld",	"std"
X};
Xchar *mon18[] = {
X	"test",	"???",	"not",	"neg",
X	"mul",	"imul",	"div",	"idiv"
X};
Xchar *mon19[] = {
X	"incw",	"decw",	"call",	"call",
X	"jmp",	"jmpf",	"push"
X};
X
Xchar *reg8[] = {
X	"al",	"cl",	"dl",	"bl",
X	"ah",	"ch",	"dh",	"bh"
X};
X
Xchar *reg16[] = {
X	"ax",	"cx",	"dx",	"bx",
X	"sp",	"bp",	"si",	"di"
X};
X
Xchar *regsg[] = { "es",	"cs",	"ss",	"ds" };
X
Xchar *regi[] = {
X	"[bx+si]",	"[bx+di]",	"[bp+si]",	"[bp+di]",
X	"[si]",		"[di]",		"[bp]",		"[bx]"
X};
X
Xstruct optable {
X	char	**numon;
X	int	(*proc)();
X} optable[] = {
X	mon0,	i_normal,				/* 00000xxx */
X	mon1,	i_normal,				/* 00001xxx */
X	mon2,	i_normal,				/* 00010xxx */
X	mon3,	i_normal,				/* 00011xxx */
X	mon4,	i_normal,				/* 00100xxx */
X	mon5,	i_normal,				/* 00101xxx */
X	mon6,	i_normal,				/* 00110xxx */
X	mon7,	i_normal,				/* 00111xxx */
X	(char **)"inc",	i_incdec,		/* 01000xxx */
X	(char **)"dec",	i_incdec,		/* 01001xxx */
X	(char **)"push",	i_incdec,	/* 01010xxx */
X	(char **)"pop",	i_incdec,		/* 01011xxx */
X	0,	i_ill,						/* 01100xxx */
X	0,	i_ill,						/* 01101xxx */
X	mon9,	i_jmp,					/* 01110xxx */
X	mon10,	i_jmp,					/* 01111xxx */
X	0,	i_immed,					/* 10000xxx */
X	0,	i_mov,						/* 10001xxx */
X	0,	i_xchg,						/* 10010xxx */
X	mon11,	i_misc1,				/* 10011xxx */
X	mon12,	i_movs,					/* 10100xxx */
X	mon13,	i_string,				/* 10101xxx */
X	reg8,	i_movi,					/* 10110xxx */
X	reg16,	i_movi,					/* 10111xxx */
X	0,	i_misc2,					/* 11000xxx */
X	0,	i_misc3,					/* 11001xxx */
X	0,	i_shift,					/* 11010xxx */
X	0,	i_esc,						/* 11011xxx */
X	0,	i_ioi,						/* 11100xxx */
X	0,	i_ior,						/* 11101xxx */
X	0,	i_monad,					/* 11110xxx */
X	0,	i_misc4						/* 11111xxx */
X};
X
Xputi(fp)
Xstruct file *fp;
X{
X	int opcode;
X	struct optable *op;
X
X	opcode = (int)getb(fp) & 0xff;
X	op = &optable[opcode >> 3];
X	(*(op->proc))(opcode, op->numon, fp);
X	return;
X}
Xi_ill(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X
X	putchr('?');
X	putchr('?');
X	putchr('?');
X	return;
X}
X
Xi_incdec(opc, mon, fp)
Xint opc;
Xchar *mon;
Xstruct file *fp;
X{
X
X	prt(mon);
X	putchr('\t');
X	prt(reg16[opc & 7]);
X	return;
X}
Xi_normal(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod;
X
X	switch (opc & 7) {
X
X	case 0:
X	case 1:
X	case 2:
X	case 3:
X		mod = getb(fp);
X		prt(mon[0]);
X		putchr('\t');
X		putad(opc, mod, fp);
X		break;
X	case 4:
X		prt(mon[0]);
X		prt("\tal,");
X		putx((long)getb(fp) & 0xff, 0);
X		break;
X	case 5:
X		prt(mon[0]);
X		prt("\tax,");
X		putx((long)getw(fp), 0);
X		break;
X	case 6:
X	case 7:
X		prt(mon[(opc & 7) - 5]);
X		break;
X
X	}
X	return;
X}
Xputad(opc, mod, fp)
Xint opc, mod;
Xstruct file *fp;
X{
X
X	switch (opc & 3) {
X
X	case 0:
X		putea(mod, reg8, fp);
X		putchr(',');
X		prt(reg8[(mod >> 3) & 7]);
X		break;
X	case 1:
X		putea(mod, reg16, fp);
X		putchr(',');
X		prt(reg16[(mod >> 3) & 7]);
X		break;
X	case 2:
X		prt(reg8[(mod >> 3) & 7]);
X		putchr(',');
X		putea(mod, reg8, fp);
X		break;
X	case 3:
X		prt(reg16[(mod >> 3) & 7]);
X		putchr(',');
X		putea(mod, reg16, fp);
X		break;
X
X	}
X	return;
X}
Xputea(mod, rp, fp)
Xint mod;
Xchar *rp[];
Xstruct file *fp;
X{
X	int type, reg;
X	long l;
X	struct symbol *sp;
X
X	type = mod & 0xc0;
X	reg = mod & 7;
X	if (type == 0xc0) {
X		prt(rp[reg]);
X		return;
X	}
X	if (type == 0x00 && reg == 6) {
X		l = getw(fp);
X		l &= 0xffff;
X		if (sp = findsym((int)l, core.symptr))
X			prtsym((int)l, sp);
X		else {
X			putchr('[');
X			putx(l, 0);
X			putchr(']');
X		}
X		return;
X	}
X	if (type == 0x40)
X		putx((long)getb(fp) & 0xff, 0);
X	else if (type == 0x80)
X		putx((long)getw(fp), 0);
X	prt(regi[reg]);
X	return;
X}
Xi_immed(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, reg;
X
X	mod = getb(fp);
X	reg = (mod >> 3) & 7;
X	mon = opc & 1 ? reg16 : reg8;
X	if (opc & 4) {
X		prt(opc & 2 ? "xchg\t" : "test\t");
X		putad(opc, mod, fp);
X		return;
X	}
X	prt(mon8[reg]);
X	putchr('\t');
X	putea(mod, mon, fp);
X	putchr(',');
X	if ((opc & 3) == 1)
X		putx((long)getw(fp), 0);
X	else
X		putx((long)getb(fp) & 0xff, 0);
X	return;
X}
Xi_jmp(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	unsigned int pc;
X	struct symbol *sp;
X
X	pc = getb(fp);
X	pc += dot + dotoff;
X	prt(mon[opc & 7]);
X	putchr('\t');
X	if (sp = findsym(pc, binary.symptr))
X		prtsym(pc, sp);
X	else
X		putx((long)(pc), 0);
X	return;
X}
Xi_mov(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod;
X
X	mod = getb(fp);
X	mon = opc & 1 ? reg16 : reg8;
X	switch (opc & 7) {
X
X	case 0:
X	case 1:
X	case 2:
X	case 3:
X		prt("mov\t");
X		putad(opc, mod, fp);
X		break;
X	case 4:
X		if (mod & 0x20) {
X			prt("???");
X			break;
X		}
X		prt("mov\t");
X		putea(mod, reg16, fp);
X		putchr(',');
X		prt(regsg[(mod >> 3) & 3]);
X		break;
X	case 5:
X		prt("lea\t");
X		putad(opc, mod, fp);
X		break;
X	case 6:
X		if (mod & 0x20) {
X			prt("???");
X			break;
X		}
X		prt("mov\t");
X		prt(regsg[(mod >> 3) & 3]);
X		putchr(',');
X		putea(mod, reg16, fp);
X		break;
X	case 7:
X		if (mod & 0x38) {
X			prt("???");
X			break;
X		}
X		prt("pop\t");
X		putea(mod, reg16, fp);
X		break;
X
X	}
X	return;
X}
Xi_xchg(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X
X	if ((opc & 7) == 0)
X		prt("nop");
X	else {
X		prt("xchg\tax,");
X		prt(reg16[opc & 7]);
X	}
X	return;
X}
Xi_misc1(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	long pc;
X	struct symbol *sp;
X
X	prt(mon[opc & 7]);
X	if ((opc & 7) == 2) {
X		putchr('\t');
X		pc = getw(fp);
X		putx((long)getw(fp), 0);
X		putchr(':');
X		if (sp = findsym((int)pc, binary.symptr))
X			prtsym((int)pc, sp);
X		else
X			putx(pc, 0);
X	}
X	return;
X}
Xi_misc2(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, reg;
X
X	if ((opc & 7) >= 4) {
X		mod = getb(fp);
X		reg = (mod >> 3) & 7;
X	}
X	switch (opc & 7) {
X
X	case 2:
X		prt("ret\t");
X		putx((long)getw(fp), 0);
X		break;
X	case 3:
X		prt("ret");
X		break;
X	case 4:
X		prt("lea\t");
X		prt(reg16[reg]);
X		putchr(',');
X		putea(mod, reg16, fp);
X		break;
X	case 5:
X		prt("lds\t");
X		prt(reg16[reg]);
X		putchr(',');
X		putea(mod, reg16, fp);
X		break;
X	case 6:
X		prt("movb\t");
X		putea(mod, reg8, fp);
X		putchr(',');
X		putx((long)getb(fp) & 0xff, 0);
X		break;
X	case 7:
X		prt("movw\t");
X		putea(mod, reg16, fp);
X		putchr(',');
X		putx((long)getw(fp), 0);
X		break;
X	default:
X		prt("???");
X		break;
X
X	}
X	return;
X}
Xi_misc3(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int sub;
X	long l;
X
X	sub = opc & 7;
X	if (sub == 2)
X		l = getw(fp);
X	else if (sub == 5)
X		l = (long)getb(fp) & 0xff;
X	switch (sub) {
X
X	case 2:
X		prt("ret\t");
X		putx(l, 0);
X		break;
X	case 3:
X		prt("ret");
X		break;
X	case 4:
X		prt("int\t3");
X		break;
X	case 5:
X		prt("int\t");
X		putx(l, 0);
X		break;
X	case 6:
X		prt("into");
X		break;
X	case 7:
X		prt("iret");
X		break;
X	default:
X		prt("???");
X		break;
X
X	}
X	return;
X}
Xi_movs(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int sub;
X	long l;
X
X	sub = opc & 7;
X	prt(mon[sub]);
X	putchr('\t');
X	if (sub < 5)
X		l = getw(fp);
X	switch (sub) {
X
X	case 0:
X		prt("al,");
X		putx(l, 0);
X		break;
X	case 1:
X		prt("ax,");
X		putx(l, 0);
X		break;
X	case 2:
X		putx(l, 0);
X		prt(",al");
X		break;
X	case 3:
X		putx(l, 0);
X		prt(",ax");
X		break;
X	case 4:
X	case 5:
X	case 6:
X	case 7:
X		break;
X
X	}
X	return;
X}
Xi_string(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int sub;
X
X	sub = opc & 7;
X	prt(mon[sub]);
X	if (sub == 0)
X		putx((long)getb(fp) & 0xff, 0);
X	else
X		putx((long)getw(fp), 0);
X	return;
X}
Xi_movi(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	long l;
X
X	if (opc & 8)
X		l = getw(fp);
X	else
X		l = getb(fp) & 0xff;
X	prt("mov\t");
X	prt(mon[opc & 7]);
X	putchr(',');
X	putx(l, 0);
X	return;
X}
Xi_shift(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, reg;
X	char *count;
X
X	switch (opc & 7) {
X
X	case 4:
X		mod = getb(fp);
X		prt(mod == 0x0a ? "aam" : "???");
X		return;
X	case 5:
X		mod = getb(fp);
X		prt(mod == 0x0a ? "aad" : "???");
X		return;
X	case 6:
X		prt("???");
X		return;
X	case 7:
X		prt("xlat");
X		return;
X
X	}
X	mod = getb(fp);
X	reg = (mod >> 3) & 7;
X	mon = opc & 1 ? reg16 : reg8;
X	count = opc & 2 ? ",cl" : ",1";
X	if (reg == 6) {
X		prt("???");
X		return;
X	}
X	prt(mon14[reg]);
X	putchr('\t');
X	putea(mod, mon, fp);
X	prt(count);
X	return;
X}
Xi_esc(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, code;
X
X	mod = getb(fp);
X	code = ((opc & 7) << 3) | ((mod >> 3) & 7);
X	prt("esc\t");
X	putx((long)code, 0);
X	putchr(',');
X	putea(mod, reg8, fp);
X	return;
X}
Xi_ioi(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int sub;
X	long pc;
X	struct symbol *sp;
X
X	pc = getb(fp);
X	sub = opc & 7;
X	prt(mon15[sub]);
X	putchr(',');
X	if (sub < 4)
X		pc += dot + dotoff;
X	else
X		pc &= 0xff;
X	if (sp = findsym((int)pc, binary.symptr))
X		prtsym((int)pc, sp);
X	else
X		putx(pc, 0);
X	return;
X}
Xi_ior(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	long pc;
X	struct symbol *sp;
X
X	switch (opc & 7) {
X
X	case 0:
X		prt("call\t");
X		pc = getn(dot + dotoff, 2, fp);
X		pc += dot + dotoff;
X		break;
X	case 1:
X		prt("jmp\t");
X		pc = getn(dot + dotoff, 2, fp);
X		pc += dot + dotoff;
X		break;
X	case 2:
X		prt("jmp\t");
X		pc = getw(fp);
X		putx((long)getw(fp), 0);
X		putchr(':');
X		break;
X	case 3:
X		prt("jmp\t");
X		pc = getn(dot + dotoff, 1, fp);
X		pc += dot + dotoff;
X		break;
X	case 4:
X	case 5:
X	case 6:
X	case 7:
X		prt(mon15[opc & 7]);
X		prt(",dx");
X		return;
X
X	}
X	if (sp = findsym((int)pc, binary.symptr))
X		prtsym((int)pc, sp);
X	else
X		putx(pc, 0);
X	return;
X}
Xi_monad(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, sub;
X
X	sub = opc & 7;
X	switch (sub) {
X
X	case 0:
X	case 1:
X	case 2:
X	case 3:
X	case 4:
X	case 5:
X		prt(mon16[sub]);
X		break;
X	case 6:
X	case 7:
X		mon = sub == 7 ? reg16 : reg8;
X		mod = getb(fp);
X		sub = (mod >> 3) & 7;
X		if (sub == 1) {
X			prt("???");
X			break;
X		}
X		prt(mon18[sub]);
X		putchr('\t');
X		putea(mod, mon, fp);
X		if (sub == 0) {
X			putchr(',');
X			if (opc & 1)
X				putx((long)getw(fp), 0);
X			else
X				putx((long)getb(fp) & 0xff, 0);
X		}
X		break;
X
X	}
X	return;
X}
Xi_misc4(opc, mon, fp)
Xint opc;
Xchar *mon[];
Xstruct file *fp;
X{
X	int mod, sub;
X
X	sub = opc & 7;
X	switch (sub) {
X
X	case 0:
X	case 1:
X	case 2:
X	case 3:
X	case 4:
X	case 5:
X		prt(mon17[sub]);
X		break;
X	case 6:
X		mod = getb(fp);
X		sub = (mod >> 3) & 7;
X		if (sub == 0) {
X			prt("incb\t");
X			putea(mod, reg8, fp);
X		} else if (sub == 1) {
X			prt("decb\t");
X			putea(mod, reg8, fp);
X		} else
X			prt("???");
X		break;
X	case 7:
X		mod = getb(fp);
X		sub = (mod >> 3) & 7;
X		if (sub == 7)
X			prt("???");
X		else {
X			prt(mon19[sub]);
X			putchr('\t');
X			putea(mod, reg16, fp);
X		}
X		break;
X
X	}
X	return;
X}
X
X
+ END-OF-FILE optab.c
chmod 'u=rw,g=r,o=r' 'optab.c'
set `wc -c 'optab.c'`
count=$1
case $count in
11771)	:;;
*)	echo 'Bad character count in ''optab.c' >&2
		echo 'Count should be 11771' >&2
esac
exit 0