+static char sccsid[] = "@(#)nm.c 4.1 10/1/80";
/*
-** print symbol tables for
-** object or archive files
-**
-** nm [-goprun] [name ...]
-*/
-
-
-
-#include <ar.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <a.out.h>
-#include <pagsiz.h>
-
-#define MAGIC exp.a_magic
-#define BADMAG MAGIC!=A_MAGIC1 && MAGIC!=A_MAGIC2 \
- && MAGIC!=A_MAGIC3 && MAGIC!=A_MAGIC4 && MAGIC != 0412 && MAGIC != 0413
-#define SELECT arch_flg ? arp.ar_name : *argv
-int numsort_flg;
-int undef_flg;
-int revsort_flg = 1;
-int globl_flg;
-int nosort_flg;
-int arch_flg;
-int prep_flg;
-struct ar_hdr arp;
-struct exec exp;
+ * nm - print name list; VAX string table version
+ */
+#include <sys/types.h>
+#include <ar.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <a.out.h>
+#include <stab.h>
+#include <pagsiz.h>
+#include <stat.h>
+
+#define SELECT archive ? archdr.ar_name : *xargv
+
+int aflg, gflg, nflg, oflg, pflg, uflg;
+int rflg = 1;
+char **xargv;
+int archive;
+struct ar_hdr archdr;
+union {
+ char mag_armag[SARMAG+1];
+ struct exec mag_exp;
+} mag_un;
+#define OARMAG 0177545
FILE *fi;
-long off;
-long ftell();
+off_t off;
+off_t ftell();
char *malloc();
char *realloc();
+char *strp;
+char *stab();
+off_t strsiz;
+int compare();
+int narg;
+int errs;
main(argc, argv)
char **argv;
{
- int narg;
- int compare();
if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
argv++;
while (*++*argv) switch (**argv) {
- case 'n': /* sort numerically */
- numsort_flg++;
- continue;
- case 'g': /* globl symbols only */
- globl_flg++;
+ case 'n':
+ nflg++;
continue;
-
- case 'u': /* undefined symbols only */
- undef_flg++;
+ case 'g':
+ gflg++;
continue;
-
- case 'r': /* sort in reverse order */
- revsort_flg = -1;
+ case 'u':
+ uflg++;
continue;
-
- case 'p': /* don't sort -- symbol table order */
- nosort_flg++;
+ case 'r':
+ rflg = -1;
continue;
-
- case 'o': /* prepend a name to each line */
- prep_flg++;
+ case 'p':
+ pflg++;
continue;
-
- default: /* oops */
- fprintf(stderr, "nm: invalid argument -%c\n", *argv[0]);
- exit(1);
+ case 'o':
+ oflg++;
+ continue;
+ case 'a':
+ aflg++;
+ continue;
+ default:
+ fprintf(stderr, "nm: invalid argument -%c\n",
+ *argv[0]);
+ exit(2);
}
argc--;
}
argv[1] = "a.out";
}
narg = argc;
- while(argc--) {
- fi = fopen(*++argv,"r");
- if (fi == NULL) {
- fprintf(stderr, "nm: cannot open %s\n", *argv);
+ xargv = argv;
+ while (argc--) {
+ ++xargv;
+ namelist();
+ }
+ exit(errs);
+}
+
+namelist()
+{
+ register int j;
+
+ archive = 0;
+ fi = fopen(*xargv, "r");
+ if (fi == NULL) {
+ error(0, "cannot open");
+ return;
+ }
+ off = SARMAG;
+ fread((char *)&mag_un, 1, sizeof(mag_un), fi);
+ if (mag_un.mag_exp.a_magic == OARMAG) {
+ error(0, "old archive");
+ return;
+ }
+ if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0)
+ archive++;
+ else if (N_BADMAG(mag_un.mag_exp)) {
+ error(0, "bad format");
+ return;
+ }
+ fseek(fi, 0L, 0);
+ if (archive) {
+ nextel(fi);
+ if (narg > 1)
+ printf("\n%s:\n", *xargv);
+ }
+ do {
+ off_t o;
+ register i, n, c;
+ struct nlist *symp = NULL;
+ struct nlist sym;
+ struct stat stb;
+
+ fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi);
+ if (N_BADMAG(mag_un.mag_exp))
+ continue;
+ if (archive == 0)
+ fstat(fileno(fi), &stb);
+ o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec);
+ fseek(fi, o, 1);
+ n = mag_un.mag_exp.a_syms / sizeof(struct nlist);
+ if (n == 0) {
+ error(0, "no name list");
continue;
}
- off = sizeof(exp.a_magic);
- fread((char *)&exp, 1, sizeof(MAGIC), fi); /* get magic no. */
- if (MAGIC == ARMAG)
- arch_flg++;
- else if (BADMAG) {
- fprintf(stderr, "nm: %s-- bad format\n", *argv);
+ if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) >
+ (archive ? off : stb.st_size))
+ error(1, "old format .o (no string table) or truncated file");
+ i = 0;
+ if (strp)
+ free(strp), strp = 0;
+ while (--n >= 0) {
+ fread((char *)&sym, 1, sizeof(sym), fi);
+ if (gflg && (sym.n_type&N_EXT)==0)
+ continue;
+ if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg))
+ continue;
+ if (symp==NULL)
+ symp = (struct nlist *)
+ malloc(sizeof(struct nlist));
+ else
+ symp = (struct nlist *)
+ realloc(symp,
+ (i+1)*sizeof(struct nlist));
+ if (symp == NULL)
+ error(1, "out of memory");
+ symp[i++] = sym;
+ }
+ if (archive && ftell(fi)+sizeof(off_t) >= off) {
+ error(0, "no string table (old format .o?)");
continue;
}
- fseek(fi, 0L, 0);
- if (arch_flg) {
- nextel(fi);
- if (narg > 1)
- printf("\n%s:\n", *argv);
+ if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) {
+ error(0, "no string table (old format .o?)");
+ goto out;
}
- do {
- long o;
- register i, n, c;
- struct nlist *symp = NULL;
- struct nlist sym;
-
- fread((char *)&exp, 1, sizeof(struct exec), fi);
- if (BADMAG) /* archive element not in */
- continue; /* proper format - skip it */
- o = (long)exp.a_text + exp.a_data + exp.a_trsize + exp.a_drsize;
- if (MAGIC==0412 || MAGIC==0413)
- o += PAGSIZ - sizeof(struct exec);
- fseek(fi, o, 1);
- n = exp.a_syms / sizeof(struct nlist);
- if (n == 0) {
- fprintf(stderr, "nm: %s-- no name list\n", SELECT);
- continue;
- }
- i = 0;
- while (--n >= 0) {
- fread((char *)&sym, 1, sizeof(sym), fi);
- if (globl_flg && (sym.n_type&N_EXT)==0)
- continue;
- if (symp==NULL)
- symp = (struct nlist *)malloc(sizeof(struct nlist));
- else {
- symp = (struct nlist *)realloc(symp, (i+1)*sizeof(struct nlist));
- }
- if (symp == NULL) {
- fprintf(stderr, "nm: out of memory on %s\n", *argv);
- exit(2);
- }
- symp[i++] = sym;
+ strp = (char *)malloc(strsiz);
+ if (strp == NULL)
+ error(1, "ran out of memory");
+ if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1)
+ error(1, "error reading string table");
+ for (j = 0; j < i; j++)
+ if (symp[j].n_un.n_strx)
+ symp[j].n_un.n_name =
+ symp[j].n_un.n_strx + strp;
+ else
+ symp[j].n_un.n_name = "";
+ if (pflg==0)
+ qsort(symp, i, sizeof(struct nlist), compare);
+ if ((archive || narg>1) && oflg==0)
+ printf("\n%s:\n", SELECT);
+ psyms(symp, i);
+ if (symp)
+ free((char *)symp), symp = 0;
+ if (strp)
+ free((char *)strp), strp = 0;
+ } while(archive && nextel(fi));
+out:
+ fclose(fi);
+}
+
+psyms(symp, nsyms)
+ register struct nlist *symp;
+ int nsyms;
+{
+ register int n, c;
+
+ for (n=0; n<nsyms; n++) {
+ c = symp[n].n_type;
+ if (c & N_STAB) {
+ if (oflg) {
+ if (archive)
+ printf("%s:", *xargv);
+ printf("%s:", SELECT);
}
- if (nosort_flg==0)
- qsort(symp, i, sizeof(struct nlist), compare);
- if ((arch_flg || narg>1) && prep_flg==0)
- printf("\n%s:\n", SELECT);
- for (n=0; n<i; n++) {
- if (prep_flg) {
- if (arch_flg)
- printf("%s:", *argv);
- printf("%s:", SELECT);
- }
- c = symp[n].n_type;
-
- if (c & STABTYPE) {
- printf("%08x - %-8.8s %02x %02x %04x\n",
- symp[n].n_value,
- symp[n].n_name,
- symp[n].n_type & 0xff,
- symp[n].n_other & 0xff,
- symp[n].n_desc & 0xffff);
- continue;
- }
- switch (c&(N_TYPE-N_EXT)) {
-
- case N_UNDF:
- c = 'u';
- if (symp[n].n_value)
- c = 'c';
- break;
-
- case N_ABS:
- c = 'a';
- break;
-
- case N_TEXT:
- c = 't';
- break;
-
- case N_DATA:
- c = 'd';
- break;
-
- case N_BSS:
- c = 'b';
- break;
-
- case N_FN:
- c = 'f';
- break;
+ printf("%08x - %02x %04x %5.5s %s\n",
+ symp[n].n_value,
+ symp[n].n_other & 0xff, symp[n].n_desc & 0xffff,
+ stab(symp[n].n_type & 0xff),
+ symp[n].n_un.n_name);
+ continue;
+ }
+ switch (c&N_TYPE) {
-/*
- case N_REG:
- c = 'r';
- break;
- */
- }
- if (undef_flg && c!='u')
- continue;
- if (symp[n].n_type&N_EXT)
- c = toupper(c);
- if (!undef_flg) {
- if (c=='u' || c=='U')
- printf(" ");
- else
- printf(FORMAT, symp[n].n_value);
- printf(" %c ", c);
- }
- printf("%.8s\n", symp[n].n_name);
- l1:; }
- if (symp)
- free((char *)symp);
- } while(arch_flg && nextel(fi));
- fclose(fi);
+ case N_UNDF:
+ c = 'u';
+ if (symp[n].n_value)
+ c = 'c';
+ break;
+ case N_ABS:
+ c = 'a';
+ break;
+ case N_TEXT:
+ c = 't';
+ break;
+ case N_DATA:
+ c = 'd';
+ break;
+ case N_BSS:
+ c = 'b';
+ break;
+ case N_FN:
+ c = 'f';
+ break;
+ }
+ if (uflg && c!='u')
+ continue;
+ if (oflg) {
+ if (archive)
+ printf("%s:", *xargv);
+ printf("%s:", SELECT);
+ }
+ if (symp[n].n_type&N_EXT)
+ c = toupper(c);
+ if (!uflg) {
+ if (c=='u' || c=='U')
+ printf(" ");
+ else
+ printf(N_FORMAT, symp[n].n_value);
+ printf(" %c ", c);
+ }
+ printf("%s\n", symp[n].n_un.n_name);
+l1: ;
}
- exit(0);
}
compare(p1, p2)
{
register i;
- if (numsort_flg) {
+ if (nflg) {
if (p1->n_value > p2->n_value)
- return(revsort_flg);
+ return(rflg);
if (p1->n_value < p2->n_value)
- return(-revsort_flg);
+ return(-rflg);
}
- for(i=0; i<sizeof(p1->n_name); i++)
- if (p1->n_name[i] != p2->n_name[i]) {
- if (p1->n_name[i] > p2->n_name[i])
- return(revsort_flg);
- else
- return(-revsort_flg);
- }
- return(0);
+ return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name));
}
nextel(af)
FILE *af;
{
+ register char *cp;
register r;
+ long arsize;
fseek(af, off, 0);
- r = fread((char *)&arp, 1, sizeof(struct ar_hdr), af); /* read archive header */
- if (r <= 0)
+ r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
+ if (r != sizeof(struct ar_hdr))
return(0);
- if (arp.ar_size & 1)
- ++arp.ar_size;
- off = ftell(af) + arp.ar_size; /* offset to next element */
+ for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
+ if (*cp == ' ')
+ *cp = '\0';
+ arsize = atol(archdr.ar_size);
+ if (arsize & 1)
+ ++arsize;
+ off = ftell(af) + arsize; /* beginning of next element */
return(1);
}
+
+error(n, s)
+char *s;
+{
+ fprintf(stderr, "nm: %s:", *xargv);
+ if (archive) {
+ fprintf(stderr, "(%s)", archdr.ar_name);
+ fprintf(stderr, ": ");
+ } else
+ fprintf(stderr, " ");
+ fprintf(stderr, "%s\n", s);
+ if (n)
+ exit(2);
+ errs = 1;
+}
+
+struct stabnames {
+ int st_value;
+ char *st_name;
+} stabnames[] ={
+ N_GSYM, "GSYM",
+ N_FNAME, "FNAME",
+ N_FUN, "FUN",
+ N_STSYM, "STSYM",
+ N_LCSYM, "LCSYM",
+ N_RSYM, "RSYM",
+ N_SLINE, "SLINE",
+ N_SSYM, "SSYM",
+ N_SO, "SO",
+ N_LSYM, "LSYM",
+ N_SOL, "SOL",
+ N_PSYM, "PSYM",
+ N_ENTRY, "ENTRY",
+ N_LBRAC, "LBRAC",
+ N_RBRAC, "RBRAC",
+ N_BCOMM, "BCOMM",
+ N_ECOMM, "ECOMM",
+ N_ECOML, "ECOML",
+ N_LENG, "LENG",
+ N_PC, "PC",
+ 0, 0
+};
+
+char *
+stab(val)
+{
+ register struct stabnames *sp;
+ static char prbuf[32];
+
+ for (sp = stabnames; sp->st_name; sp++)
+ if (sp->st_value == val)
+ return (sp->st_name);
+ sprintf(prbuf, "%02x", val);
+ return (prbuf);
+}