/* nm11 -- list names in a PDP11 object file * * Matt Bishop, Purdue University, Sept. 2, 1981 */ /* ** print symbol tables for object files ** (will not work for new format ar files) ** ** nm11 [-goprun] [name ...] */ #include "/usr/Xinu/include/a.out.h" #include <ar.h> #include <stdio.h> #include <ctype.h> #define MAGIC exp.a_magic #define BADMAG MAGIC!=A_MAGIC1 && MAGIC!=A_MAGIC2 \ && MAGIC!=A_MAGIC3 && MAGIC!=A_MAGIC4 #define SELECT arch_flg ? arp.ar_name : *argv union ints { struct fun { short h1; short h2; } xxjunk; int w1; } x; int ar_size; 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; FILE *fi; long off; long ftell(); char *malloc(); char *realloc(); 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++; continue; case 'u': /* undefined symbols only */ undef_flg++; continue; case 'r': /* sort in reverse order */ revsort_flg = -1; continue; case 'p': /* don't sort -- symbol table order */ nosort_flg++; continue; case 'o': /* prepend a name to each line */ prep_flg++; continue; default: /* oops */ fprintf(stderr, "nm11: invalid argument -%c\n", *argv[0]); exit(1); } argc--; } if (argc == 0) { argc = 1; argv[1] = "a.out"; } narg = argc; while(argc--) { fi = fopen(*++argv,"r"); if (fi == NULL) { fprintf(stderr, "nm11: cannot open %s\n", *argv); continue; } off = sizeof(exp.a_magic); /* get magic no. */ fread((char *)&exp, 1, sizeof(MAGIC), fi); /*T*/ /* if (MAGIC == ARMAG) arch_flg++; else /*T*/ if (BADMAG) { fprintf(stderr, "nm11: %s-- bad format\n", *argv); continue; } fseek(fi, 0L, 0); if (arch_flg) { nextel(fi); if (narg > 1) printf("\n%s:\n", *argv); } 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; if ((exp.a_flag & 01) == 0) o *= 2; fseek(fi, o, 1); n = exp.a_syms / sizeof(struct nlist); if (n == 0) { fprintf(stderr, "nm11: %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; switch (sym.n_type&N_TYPE) { case N_UNDF: c = 'u'; if (sym.n_value) c = 'c'; break; default: 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; case N_REG: c = 'r'; break; } if (undef_flg && c!='u') continue; if (sym.n_type&N_EXT) c = toupper(c); sym.n_type = c; 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, "nm11: out of memory on %s\n", *argv); exit(2); } symp[i++] = sym; } 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 (!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); } if (symp) free((char *)symp); } while(arch_flg && nextel(fi)); fclose(fi); } exit(0); } compare(p1, p2) struct nlist *p1, *p2; { register i; if (numsort_flg) { if (p1->n_value > p2->n_value) return(revsort_flg); if (p1->n_value < p2->n_value) return(-revsort_flg); } 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); } nextel(af) FILE *af; { register r; fseek(af, off, 0); r = fread((char *)&arp, 1, sizeof(struct ar_hdr), af); /* read archive header */ if (r <= 0) return(0); /*T ar_size = swap(&arp.ar_size); if (ar_size & 1) ++ar_size; /*T*/ off = ftell(af) + ar_size; /* offset to next element */ return(1); } /* swap(word) short *word; { x.h1 = ((struct fun *) word) -> h2; x.h2 = ((struct fun *) word) -> h1; return(x.w1); } /*T*/