/* ** print symbol tables for ** object or archive files ** ** nm [-goprun] [name ...] */ #include #include #include #include #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 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, "nm: 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, "nm: cannot open %s\n", *argv); 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); 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, "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; 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, "nm: 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; nn_value > p2->n_value) return(revsort_flg); if (p1->n_value < p2->n_value) return(-revsort_flg); } for(i=0; in_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); if (arp.ar_size & 1) ++arp.ar_size; off = ftell(af) + arp.ar_size; /* offset to next element */ return(1); }