BSD 4 release
[unix-history] / usr / src / cmd / nm.c
index 1c620f3..38b8906 100644 (file)
@@ -1,73 +1,73 @@
+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;
 FILE   *fi;
-long   off;
-long   ftell();
+off_t  off;
+off_t  ftell();
 char   *malloc();
 char   *realloc();
 char   *malloc();
 char   *realloc();
+char   *strp;
+char   *stab();
+off_t  strsiz;
+int    compare();
+int    narg;
+int    errs;
 
 main(argc, argv)
 char **argv;
 {
 
 main(argc, argv)
 char **argv;
 {
-       int narg;
-       int  compare();
 
        if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
                argv++;
                while (*++*argv) switch (**argv) {
 
        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;
                        continue;
-
-               case 'u':               /* undefined symbols only */
-                       undef_flg++;
+               case 'g':
+                       gflg++;
                        continue;
                        continue;
-
-               case 'r':               /* sort in reverse order */
-                       revsort_flg = -1;
+               case 'u':
+                       uflg++;
                        continue;
                        continue;
-
-               case 'p':               /* don't sort -- symbol table order */
-                       nosort_flg++;
+               case 'r':
+                       rflg = -1;
                        continue;
                        continue;
-
-               case 'o':               /* prepend a name to each line */
-                       prep_flg++;
+               case 'p':
+                       pflg++;
                        continue;
                        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--;
        }
                }
                argc--;
        }
@@ -76,134 +76,180 @@ char **argv;
                argv[1] = "a.out";
        }
        narg = 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;
                }
                        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;
                }
                        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)
 }
 
 compare(p1, p2)
@@ -211,33 +257,87 @@ struct nlist *p1, *p2;
 {
        register i;
 
 {
        register i;
 
-       if (numsort_flg) {
+       if (nflg) {
                if (p1->n_value > p2->n_value)
                if (p1->n_value > p2->n_value)
-                       return(revsort_flg);
+                       return(rflg);
                if (p1->n_value < p2->n_value)
                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;
 {
 }
 
 nextel(af)
 FILE *af;
 {
+       register char *cp;
        register r;
        register r;
+       long arsize;
 
        fseek(af, off, 0);
 
        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);
                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);
 }
        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);
+}