[comp.os.minix] Updated version of MBD Part

bds@lzaz.ATT.COM (B.SZABLAK) (03/30/89)

/*
 * mdbexp.c - MINIX expresion parser
 *
 * Written by Bruce D. Szablak
 *
 * This free software is provided for non-commerical use. No warrantee
 * of fitness for any use is implied. You get what you pay for. Anyone
 * may make modifications and distribute them, but please keep this header
 * in the distribution. NOTE: A PORTION OF THIS FILE IS DERIVED FROM THE
 * SOURCE TO ANM.C WHOSE AUTHOR IS UNKNOWN TO ME (AST?). BEWARE THAT
 * OTHER RESTRICTIONS MAY APPLY.
 */

#include <ctype.h>
#include <setjmp.h>
#include <stdio.h>
#include "user.h"
#include "out.h"

extern jmp_buf mainlp;
extern curpid;

int nsyms;
struct outname *nbufp = NULL;
long value(), strtol(), lookup(), ptrace();

#define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_')

char *
addr_to_name(rel_addr, off_p)
	long rel_addr, *off_p;
{
	register int i, l = 0, r = nsyms;

	while (l < r)
	{
		i = (l + r) >> 1;
		if (rel_addr < nbufp[i].on_valu) r = i;
		else if (rel_addr > nbufp[i].on_valu) l = i + 1;
		else break;
	}
	if (l == nsyms || r == 0)
	{
		*off_p = rel_addr;
		return "_start";
	}
	if (rel_addr < nbufp[i].on_valu) i--;
	*off_p = rel_addr - nbufp[i].on_valu;
	return nbufp[i].on_mptr;
}

symbolic(addr, sep)
	long addr;
	char sep;
{
	long off;
	extern long saddr, eaddr;

	if (addr < saddr || addr > eaddr)
	{
		printf("0x%lx%c", addr, sep);
		return;
	}
	fputs(addr_to_name(addr - saddr, &off), stdout);
	if (off) printf("+0x%lx", off);
	fputc(sep, stdout);
}

char *
getexp(buf, exp_p, seg_p)
	char *buf;
	int *seg_p;
	long *exp_p;
{
	extern char *skip();
	long v = 0L;

	buf = skip(buf);
	if ((isalpha(*buf) && (isspace(buf[1]) || buf[1]==';'))
		|| *buf=='\n' || *buf==';' || *buf=='/' || *buf == '!')
	{
		*exp_p = 0L;
		return buf;
	}
	v = value(buf, &buf, seg_p);
	buf = skip(buf);
	if (*buf == '+')
	{
		v += value(skip(buf+1), &buf, seg_p);
	}
	else if (*buf == '-')
	{
		v -= value(skip(buf+1), &buf, seg_p);
	}
	*exp_p = v;
	return skip(buf);
}

long
reg_addr(s)
	char *s;
{
	long val;

	switch (*s++)
	{
	case	'a': case 'A': val = 32; break;
	case	'd': case 'D': val = 0; break;
	default: goto error;
	}
	if (*s >= '0' && *s <= '7')
	{
		return val + 4*(*s - '0');
	}

error:
	printf("Unknown register: %2.2s\n", s);
	longjmp(mainlp);
}

long
value(s, s_p, seg_p)
	char *s, **s_p;
	int *seg_p;
{
	long k;

	if (*s == '\'') /* handle character constants here */
	{
		*s_p = s + 2;
		return s[1];
	}
	if (*s == '-' || isdigit(*s))
	{
		return strtol(s, s_p, 0);
	}
	if (*s == '$')
	{
		k = reg_addr(s+1);
		*s_p = s + 3;
		return ptrace(3, curpid, k, 0L);
	}
	return lookup(s, s_p, seg_p);
}

long
lookup(s, s_p, seg_p)
	char *s, **s_p;
	int *seg_p;
{
	extern long saddr;
	char c;
	int i, l;

	for (l = 1; idchar(s[l]); ++l ) {}
	c = s[l]; s[l] = 0;
	
	if (strcmp("_start", s) == 0)
	{
		*seg_p = T;
		*(*s_p = s + 6) = c;
		return saddr;
	}
	for (i = 0; i < nsyms; i++)
		if (strcmp(nbufp[i].on_mptr, s) == 0)
		{
			*seg_p = (nbufp[i].on_type & S_TYP) == S_MIN ? T : D;
			*(*s_p = s + l) = c;
			return nbufp[i].on_valu + saddr;
		}

	printf("%s: symbol not found\n", s);
	longjmp(mainlp);
}

/******************END OF ORIGINAL CODE***********************/

/*
 * The following code is actually a highly edited
 * version of anm.c - The ACK version of nm
 * That file's header follows:
 */

/* @(#)anm.c	1.6 */
/*
**	print symbol tables for
**	ACK object files
**
**	anm [-gopruns] [name ...]
*/

#define	ushort	unsigned short

long	off;
char	*malloc();
char	*realloc();
long	s_base[S_MAX];	/* for specially encoded bases */

getsyms(file)
	char *file;
{
	int	compare();
	FILE		*fi;
	struct	outsect	sbuf;
	struct	outhead	hbuf;
	struct	outname	nbuf;
	char		*cbufp;
	long		fi_to_co;
	long		n;
	unsigned	readcount;
	int		j;

	fi = fopen(file,"r");
	if (fi == NULL) {
		fprintf(stderr, "db: cannot open %s\n", file);
		return;
	}

	getofmt((char *)&hbuf, SF_HEAD, fi);
	if (BADMAGIC(hbuf)) {
		fprintf(stderr, "db: %s-- bad format\n", file);
		fclose(fi);
		return;
	}

	n = hbuf.oh_nname;
	if (n == 0) {
		fprintf(stderr, "db: %s-- no name list\n", file);
		fclose(fi);
		return;
	}

	if (hbuf.oh_nchar == 0) {
		fprintf(stderr, "db: %s-- no names\n", file);
		fclose(fi);
		return;
	}
	if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) {
		fprintf(stderr, "db: string area too big in %s\n", file);
		exit(2);
	}

	/* store special section bases */
	if (hbuf.oh_flags & HF_8086) {
		int i;
		for (i=0; i<hbuf.oh_nsect; i++) {
			getofmt((char *)&sbuf, SF_SECT, fi);
			s_base[i+S_MIN] =
				(sbuf.os_base>>12) & 03777760;
		}
	}
		 
	if ((cbufp = (char *)malloc(readcount)) == NULL) {
		fprintf(stderr, "db: out of memory on %s\n", file);
		exit(2);
	}
	fseek(fi, OFF_CHAR(hbuf), 0);
	if (fread(cbufp, 1, readcount, fi) == 0) {
		fprintf(stderr, "db: read error on %s\n", file);
		exit(2);
	}
	fi_to_co = (long)cbufp - OFF_CHAR(hbuf);

	fseek(fi, OFF_NAME(hbuf), 0);
	nsyms = 0;
	while (--n >= 0) {
		getofmt((char *)&nbuf, SF_NAME, fi);

		if (nbuf.on_foff == 0)
			continue; /* skip entries without names */

		if ((nbuf.on_type&S_EXT)==0)
			continue;

		nbuf.on_mptr = (char *)(nbuf.on_foff + fi_to_co);

		/* adjust value for specially encoded bases */
		if (hbuf.oh_flags & HF_8086) {
		    if (((nbuf.on_type&S_ETC) == 0) ||
			((nbuf.on_type&S_ETC) == S_SCT)) {
			j = nbuf.on_type&S_TYP;
			if ((j>=S_MIN) && (j<=S_MAX))
			    nbuf.on_valu += s_base[j];
		    }
		}

		if (nbufp == NULL)
			nbufp = (struct outname *)malloc(sizeof(struct outname));
		else
			nbufp = (struct outname *)realloc(nbufp, (nsyms+1)*sizeof(struct outname));
		if (nbufp == NULL) {
			fprintf(stderr, "db: out of memory on %s\n", file);
			exit(2);
		}
		nbufp[nsyms++] = nbuf;
	}

	qsort(nbufp, nsyms, sizeof(struct outname), compare);

	fclose(fi);
}

compare(p1, p2)
struct outname	*p1, *p2;
{
	if (p1->on_valu < p2->on_valu) return -1;
	if (p1->on_valu > p2->on_valu) return 1;
	return 0;
}

getofmt(p, s, f)
register char	*p;
register char	*s;
register FILE	*f;
{
	register i;
	register long l;

	for (;;) {
		switch (*s++) {
/*		case '0': p++; continue; */
		case '1':
			*p++ = getc(f);
			continue;
		case '2':
			i = getc(f);
			i |= (getc(f) << 8);
			*((short *)p) = i; p += sizeof(short);
			continue;
		case '4':
			l = (long)getc(f);
			l |= ((long)getc(f) << 8);
			l |= ((long)getc(f) << 16);
			l |= ((long)getc(f) << 24);
			*((long *)p) = l; p += sizeof(long);
			continue;
		default:
		case '\0':
			break;
		}
		break;
	}
}