/* * nm.c -- drive nm */ #include #include #include #include #include enum{ CHUNK = 256 /* must be power of 2 */ }; char *errs; /* exit status */ char *filename; /* current file */ char symname[]="__.SYMDEF"; /* table of contents file name */ int multifile, /* processing multiple files */ aflag, gflag, hflag, nflag, sflag, uflag, vflag; Sym **fnames; /* file path translation table */ Biobuf bout; int cmp(Sym **, Sym **); void error(char*, ...), execsyms(Biobuf*), printsyms(Sym*, long), psym(Sym**, long), doar(Biobuf*), dofile(Biobuf*), zenter(Sym*); void main(int argc, char *argv[]) { int i; Biobuf *bin; Binit(&bout, 1, OWRITE); argv0 = argv[0]; ARGBEGIN { case 'a': aflag = 1; break; case 'g': gflag = 1; break; case 'h': hflag = 1; break; case 'n': nflag = 1; break; case 's': sflag = 1; break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; } ARGEND if (argc > 1) multifile++; for(i=0; ivalue < (*t)->value) return -1; else return (*s)->value > (*t)->value; return strcmp((*s)->name, (*t)->name); } /* * enter a symbol in the table of filename elements */ void zenter(Sym *s) { static int maxf = 0; if (s->value > maxf) { maxf = (s->value+CHUNK-1) &~ (CHUNK-1); fnames = realloc(fnames, maxf*sizeof(*fnames)); if(fnames == 0) { error("out of memory\n", argv0); exits("memory"); } } fnames[s->value] = s; } /* * get the symbol table from an executable file, if it has one */ void execsyms(Biobuf *bp) { Fhdr f; Sym *s; long nsyms; Bseek(bp, 0, 0); if (crackhdr(Bfildes(bp), &f) == 0) { error("Can't read header for %s\n", filename); return; } if (syminit(Bfildes(bp), &f) < 0) return; s = symbase(&nsyms); printsyms(s, nsyms); Bclose(bp); } void printsyms(Sym *sp, long nsym) { Sym *s; Sym **symptr; int n; n = nsym*sizeof(Sym*); symptr = malloc(n); if (symptr == 0) { error("out of memory\n"); return; } memset(symptr, 0, n); for (s = sp, n = 0; nsym-- > 0; s++) { s->value = beswal(s->value); switch(s->type) { case 'T': case 'L': case 'D': case 'B': if (!uflag) if (aflag || ((s->name[0] != '.' && s->name[0] != '$'))) symptr[n++] = s; break; case 'b': case 'd': case 'l': case 't': if (!uflag && !gflag) if (aflag || ((s->name[0] != '.' && s->name[0] != '$'))) symptr[n++] = s; break; case 'U': if (!gflag) symptr[n++] = s; break; case 'Z': if (aflag) symptr[n++] = s; break; case 'f': /* we only see a 'z' when the following is true*/ if (aflag && !uflag && !gflag) { if (strcmp(s->name, ".frame")) zenter(s); symptr[n++] = s; } break; case 'a': case 'p': case 'm': case 'z': default: if (aflag && !uflag && !gflag) symptr[n++] = s; break; } } if(!sflag) qsort(symptr, n, sizeof(*symptr), cmp); psym(symptr, n); free(symptr); } void psym(Sym **symptr, int nsym) { Sym *s; char *cp; char path[512]; while (nsym-- > 0) { s = *symptr++; if (multifile && !hflag) Bprint(&bout, "%s:", filename); if (s->type == 'z') { fileelem(fnames, (uchar *) s->name, path, 512); cp = path; } else cp = s->name; if (s->value || s->type == 'a' || s->type == 'p') Bprint(&bout, "%8lux %c %s\n", s->value, s->type, cp); else Bprint(&bout, " %c %s\n", s->type, cp); } } void error(char *fmt, ...) { char buf[4096], *s; s = buf; s += sprint(s, "%s: ", argv0); s = doprint(s, buf + sizeof(buf) / sizeof(*buf), fmt, &fmt + 1); *s++ = '\n'; write(2, buf, s - buf); errs = "errors"; }