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

/*
 * List a coff symbol table.
 */
#include <misc.h>
#include <canon.h>
#include <l.out.h>
#include <ar.h>
#include <errno.h>

FILE *fd;	/* Current input file */

int asw;	/* list all symbols */
int dsw;	/* list only defined symbols */
int gsw;	/* print only global symbols */
int nsw;	/* list numerically not alphabetically */
int osw;	/* append file name to each line */
int psw;	/* print symbols in symbol table order */
int rsw;	/* print in reverse alpha order */
int usw;	/* print only undefined symbols */
int vsw;	/* print coff type symbols */

int namesw;	/* one if header is required */
char *str_tab;
char *fname;

/*
 * read or have an error.
 */
static void
xread(to, size, msg)
char *to;
unsigned size;
char *msg;
{
	if (1 != fread(to, size, 1, fd))
		fatal("Error reading %s - %s", fname, msg);
}

/*
 * Old form sort logic.
 */
ncomp_old(s1, s2)
struct nlist *s1, *s2;
{
	long i;

	if (!(i = (s1->n_value - s2->n_value)))
		return (0);
	if (i < 0)
		return (-1);
	return (1);
}

acomp_old(s1, s2)
struct nlist *s1, *s2;
{
	return(strncmp(s1->n_name, s2->n_name, NCPLN));
}

rcomp_old(s1, s2)
struct nlist *s1, *s2;
{
	return(strncmp(s2->n_name, s1->n_name, NCPLN));
}

/*
 * Process old ar files.
 */
old_ar(filen, at)
char *filen;
long at;
{
	long arhend;
	struct old_ar_hdr arh;

	namesw = 0;
	for (arhend = at + sizeof(short); ; ) {
		fseek(fd, arhend, 0);
		if (1 != fread(&arh, sizeof(arh), 1, fd))
			break;
		arhend += sizeof(arh);
		arh.ar_date = 0;	/* terminate name */
		cansize(arh.ar_size);
		if (strcmp(arh.ar_name, HDRNAME)) {
			printf("%s(%s)\n", filen, arh.ar_name);
			readHeaders(arhend, arh.ar_size);
		}
		arhend += arh.ar_size;
	}
	namesw = 1;
}

/*
 * Process old form stuff.
 */
old_nout(at)
long at;
{
	struct ldheader ldh;
	struct ldsym *sym, *s;
	register unsigned i, syms, ct;
	long toSym;
	short type;
	extern char *realloc();

	fseek(fd, at, 0);
	xread(&ldh, sizeof(ldh), "n.out header");
	if (!ldh.l_ssize[L_SYM]) {
		printf("No symbols in %s\n", fname);
		return;
	}

	if (namesw)
		printf("%s:\n", fname);

	canshort(ldh.l_machine);
	toSym = ldh.l_entry + sizeof(ldh);

	for (i = 0; i < L_SYM; i++) {
		cansize(ldh.l_ssize[i]);
		if (i != L_BSSI && i != L_BSSD)
			toSym += ldh.l_ssize[i];
	}

	fseek(fd, at + toSym, 0);
	cansize(ldh.l_ssize[L_SYM]);
	i = ldh.l_ssize[L_SYM];
	if (i != ldh.l_ssize[L_SYM])
		fatal("Out of space");
	sym = alloc(i);
	xread(sym, i, "symbol table");
	ct = i / sizeof(*sym);

	/* squeeze out unneeded stuff before sort */
	for (i = syms = 0; i < ct; i++) {
		canshort(sym[i].ls_type);
		canshort(sym[i].ls_addr);
		type = sym[i].ls_type;
		if (gsw && !(type & L_GLOBAL))
			continue;
		if ((type & ~L_GLOBAL) == L_REF) {	/* a reference */
			if (dsw)	/* list only defined */
				continue;
			if (usw && sym[i].ls_addr)
				continue;
		}
		else if (usw)
			continue;
		if (!asw && !csymbol(sym + i))
			continue;
		if (i != syms)
			sym[syms] = sym[i];
		syms++;
	}
	sym = realloc(sym, syms * sizeof(*sym));

	if (nsw)
		qsort(sym, syms, sizeof(*sym), ncomp_old);
	else if (rsw)
		qsort(sym, syms, sizeof(*sym), rcomp_old);
	else if (!psw)
		qsort(sym, syms, sizeof(*sym), acomp_old);

	for (s = sym; s < (sym + syms); s++) {
		static char *gn[] = {
			"SI", "PI", "BI",
			"SD", "PD", "BD",
			" D", "  ", "  ",
			" A", " C", "??"
		};
		static char *ln[] = {
			"si", "pi", "bi",
			"sd", "pd", "bd",
			" d", "  ", "  ",
			" a", " c", "??"
		};
		if (osw)
			printf("%s ", fname);
		i = s->ls_type & L_GLOBAL;
		type = s->ls_type & ~ L_GLOBAL;
		if (type < L_SHRI || type > L_REF)
			type = L_REF + 1;
		if (type == L_REF && !s->ls_addr)
			printf("      %c", i ? 'U' : 'u');
		else
			printf("%04x %s",
				s->ls_addr,
				i ? gn[type] : ln[type]);
		printf(" %.*s\n", NCPLN, s->ls_id);
	}

	free(sym);
}

/*
 * This routine gets called if we
 * are not in '-a' mode. It determines if
 * the symbol pointed to by 'sp' is a C
 * style symbol (trailing '_' or longer than
 * (NCPLN-1) characters). If it is it eats the '_'
 * and returns true.
 */
csymbol(sp)
register struct ldsym *sp;
{
	register char *cp1, *cp2;

	cp1 = &sp->ls_id[0];
	cp2 = &sp->ls_id[NCPLN];
	while (cp2!=cp1 && *--cp2==0)
		;
	if (*cp2 != 0) {
		if (*cp2 == '_') {
			*cp2 = 0;
			return (1);
		}
		if (cp2-cp1 >= (NCPLN-1))
			return (1);
	}
	return (0);
}

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

#define cx(x) case C_ ## x: printf("%6.6s ", #x); break
#define ct(x) case T_ ## x: printf("%6.6s ", #x); break

static char helpmsg[] =
	"-d list only defined symbols\n"
	"-g print only global symbols\n"
	"-n list numerically not alphabetically\n"
	"-o append file name to each line\n"
	"-p print symbols in symbol table order\n"
	"-r print in reverse alpha order\n"
	"-u print only undefined symbols\n"
	"-v print coff type symbols\n";

FILEHDR fh;
SCNHDR *scns;

/*
 * Symbol name.
 */
static char *
symName(sym, work)
SYMENT *sym;
char *work;
{
	if (!sym->n_zeroes)
		return (str_tab + sym->n_offset - 4);

	/* make sure it's zero terminated */
	memcpy(work, sym->n_name, SYMNMLEN);
	work[SYMNMLEN] = '\0';
	return (work);
}

main(argc, argv)
char *argv[];
{
	char c;
	extern int optind;
	extern char *optarg;

	while (EOF != (c = getopt(argc, argv, "adgnopruv?"))) {
		switch (c) {
		case '?':
			printf(helpmsg);
			break;
		case 'a':
			asw = 1;
			break;
		case 'd':
			dsw = 1;
			break;
		case 'g':
			gsw = 1;
			break;
		case 'n':
			nsw = 1;
			break;
		case 'o':
			osw = 1;
			break;
		case 'p':
			psw = 1;
			break;
		case 'r':
			rsw = 1;
			break;
		case 'u':
			usw = 1;
			break;
		case 'v':
			vsw = 1;
			break;
		default:
			printf("usage: nm [-dgnopruv?] file ...\n");
			exit(1);
		}
	}

	if ((psw + rsw + nsw) > 1)
		fatal("More than one sort order");

	namesw = (argc - optind) > 1;
	for (; optind < argc; optind++) {
		fd = xopen(fname = argv[optind], "rb");

		printf("%s\n", fname);
		readHeaders(0L, 0L);
		fclose(fd);
	}

	exit (0);
}

static
readHeaders(at, size)
long at, size;
{
	unsigned i;

	if (1 != fread(&fh, sizeof(fh), 1, fd)) {
		if (ferror(fd))
			fatal("Error reading %s", fname);
		printf("Inappropriate filetype %s\n", fname);
		return (0);
	}
	if (C_386_MAGIC != fh.f_magic) {
		if (!memcmp(ARMAG, &fh, SARMAG))
			return(archive(at));

		canshort(fh.f_magic);
		if (fh.f_magic == OLD_ARMAG)
			return (old_ar(fname, at));
		if (fh.f_magic == L_MAGIC)
			return (old_nout(at));
		printf("Inappropriate filetype %s\n", fname);
		return (0);
	}
	if (fh.f_opthdr)	/* pass opt hdr */
		fseek(fd, at + sizeof(fh) + fh.f_opthdr, 0);
	scns = alloc(i = (fh.f_nscns * sizeof(SCNHDR)));
	xread(scns, i, "section headers");

	if (fh.f_nsyms)
		readSymbols(at, size);
	else
		printf("No symbols in %s\n", fname);

}

/*
 * Sort by alpha.
 */
acomp(s1, s2)
SYMENT *s1, *s2;
{
	char w1[SYMNMLEN + 1], w2[SYMNMLEN + 1];

	return (strcmp(symName(s1, w1), symName(s2, w2)));
}

/*
 * Sort by reverse alpha.
 */
rcomp(s1, s2)
SYMENT *s1, *s2;
{
	char w1[SYMNMLEN + 1], w2[SYMNMLEN + 1];

	return (- strcmp(symName(s1, w1), symName(s2, w2)));
}

/*
 * Sort by value;
 */
ncomp(s1, s2)
SYMENT *s1, *s2;
{
	long i;

	if (!(i = (s1->n_value - s2->n_value)))
		return (0);
	if (i < 0)
		return (-1);
	return (1);
}

static
readSymbols(at, size)
long at;
{
	register SYMENT *s;
	SYMENT *sym;
	long str_len;
	unsigned len;
	int i, aux, syms;
	extern char *realloc();

	/* read whole symbol table */
	fseek(fd, at + fh.f_symptr, 0);
	len = str_len = SYMESZ * fh.f_nsyms;
	if (str_len != len)
		fatal("Cannot process small model");
	sym = alloc(len);
	xread(sym, len, "symbol table");

	/* squeeze out unneeded stuff before sort */
	for (i = aux = syms = 0; i < fh.f_nsyms; i++) {
		if (aux) {
			aux--;
			continue;
		}
		s = sym + i;
		aux = s->n_numaux;
		switch (s->n_sclass) {
		case C_EXT:
			if (s->n_scnum || s->n_value) { /* defined */
				if (usw)	/* print only undefined */
					continue;
			} else {			/* undefined */
				if (dsw)	/* print only defined */
					continue;
			}
			break;
		case C_EXTDEF:
			if (dsw)
				continue;
			break;
		case C_STAT:
			if (gsw || usw)
				continue;
			switch (s->n_scnum) {
			case 1:
				if (!strcmp(s->n_name, ".text"))
					continue;
				break;
			case 2:
				if (!strcmp(s->n_name, ".data"))
					continue;
				break;
			case 3:
				if (!strcmp(s->n_name, ".bss"))
					continue;
				break;
			}
			break;
		default:
			if (!vsw)
				continue;
		}
		if (i != syms)
			sym[syms] = *s;
		syms++;
	}
	sym = realloc(sym, syms * SYMESZ);

	str_len = 0;
	if (!size || ((fh.f_symptr + len + sizeof(long)) < size))
		if (1 != fread(&str_len, sizeof(str_len), 1, fd))
			str_len = 0;
	if (str_len) {
		len = str_len -= 4;
		if (len != str_len)
			fatal("Cannot process small model");
		str_tab = alloc(len);
		xread(str_tab, len, "string table");
	}

	if (nsw)
		qsort(sym, syms, SYMESZ, ncomp);
	else if (rsw)
		qsort(sym, syms, SYMESZ, rcomp);
	else if (!psw)
		qsort(sym, syms, SYMESZ, acomp);

	for (s = sym; s < (sym + syms); s++) {
		char w1[SYMNMLEN + 1], *n;

		i = strlen(n = symName(s, w1));

		if (osw)
			printf("%s ", fname);

		/* display section name */
		switch (s->n_scnum) {
		case N_DEBUG:
			printf("DEBUG    ");
			break;
		case N_ABS:
			printf("ABSOLUTE ");
			break;
		case N_TV:
			printf("TV       ");
			break;		
		case N_UNDEF:
			if (s->n_value)
				printf(".comm    ");
			else
				printf("UNDEF    ");
			break;
		default:
			printf("%-8.8s ", scns[s->n_scnum - 1].s_name);
		}

		if (vsw) {	/* print coff type data */
			/* display storage class */
			switch (s->n_sclass) {
			cx(EFCN);
			cx(NULL);
			cx(AUTO);
			cx(EXT);
			cx(STAT);
			cx(REG);
			cx(EXTDEF);
			cx(LABEL);
			cx(ULABEL);
			cx(MOS);
			cx(ARG);
			cx(STRTAG);
			cx(MOU);
			cx(UNTAG);
			cx(TPDEF);
			cx(USTATIC);
			cx(ENTAG);
			cx(MOE);
			cx(REGPARM);
			cx(FIELD);
			cx(BLOCK);
			cx(FCN);
			cx(EOS);
			cx(FILE);
			default:
				printf("unknown ");
			}

			if (s->n_type & N_TMASK) {
				if (ISPTR(s->n_type))
					printf("pointer ");
				else if (ISFCN(s->n_type))
					printf("function ");
				else if (ISARY(s->n_type))
					printf("array ");
				else if (ISTAG(s->n_type))
					printf("struct ");
				else if (INCREF(s->n_type))
					printf("union  ");
				else if (DECREF(s->n_type))
					printf("enum ");
			}
			else
				printf("- ");
	
			/* display type */
			switch (BTYPE(s->n_type)) {
			ct(NULL);
			ct(ARG);
			ct(CHAR);
			ct(SHORT);
			ct(INT);
			ct(LONG);
			ct(FLOAT);
			ct(DOUBLE);
			ct(STRUCT);
			ct(UNION);
			ct(ENUM);
			ct(MOE);
			ct(UCHAR);
			ct(USHORT);
			ct(UINT);
			ct(ULONG);
			default:
				printf("unknown ");
			}
		}

		printf("%08lX %s\n", s->n_value, n);
	}
	free(sym);
}

/*
 * Print members of archive.
 */
archive(at)
long at;
{
	long arhend;
	struct ar_hdr coff_arh;
	struct old_ar_hdr arh;
	char *p;
	extern char *strchr();

	namesw = 0;
	for (arhend = at + SARMAG; ; ) {
		fseek(fd, arhend, 0);
		if (1 != fread(&coff_arh, sizeof(coff_arh), 1, fd))
			break;
		memset(&arh, '\0', sizeof(arh));
		memcpy(arh.ar_name, coff_arh.ar_name, DIRSIZ);
		if (NULL != (p = strchr(arh.ar_name, '/')))
			*p = '\0';

		sscanf(coff_arh.ar_date, "%ld %d %d %o %ld",
			&arh.ar_date, &arh.ar_uid,
			&arh.ar_gid, &arh.ar_mode, &arh.ar_size);

		arhend += sizeof(coff_arh);
		if (arh.ar_name[0]) {
			printf("%s(%s)\n", fname, arh.ar_name);
			readHeaders(arhend, arh.ar_size);
		}
		arhend += arh.ar_size;
		if (arhend & 1)
			arhend++;		
	}
	namesw = 1;
}

unix.superglobalmegacorp.com

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