From 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 21:39:35 +0000 Subject: 20060303 --- utils/nm/nm.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 utils/nm/nm.c (limited to 'utils/nm/nm.c') diff --git a/utils/nm/nm.c b/utils/nm/nm.c new file mode 100644 index 00000000..cf36ad10 --- /dev/null +++ b/utils/nm/nm.c @@ -0,0 +1,287 @@ +/* + * nm.c -- drive nm + */ +#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 */ +int aflag; +int gflag; +int hflag; +int nflag; +int sflag; +int uflag; + +Sym **fnames; /* file path translation table */ +Sym **symptr; +int nsym; +Biobuf bout; +char* argv0; + +void error(char*, ...); +void execsyms(int); +void psym(Sym*, void*); +void printsyms(Sym**, long); +void doar(Biobuf*); +void dofile(Biobuf*); +void 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; + } ARGEND + if (argc > 1) + multifile++; + for(i=0; ivalue < (ulong)(*t)->value) + return -1; + else + return (ulong)(*s)->value > (ulong)(*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", argv0); + exits("memory"); + } + } + fnames[s->value] = s; +} + +/* + * get the symbol table from an executable file, if it has one + */ +void +execsyms(int fd) +{ + Fhdr f; + Sym *s; + long n; + + seek(fd, 0, 0); + if (crackhdr(fd, &f) == 0) { + error("Can't read header for %s", filename); + return; + } + if (syminit(fd, &f) < 0) + return; + s = symbase(&n); + nsym = 0; + while(n--) + psym(s++, 0); + + printsyms(symptr, nsym); +} + +void +psym(Sym *s, void* p) +{ + USED(p); + switch(s->type) { + case 'T': + case 'L': + case 'D': + case 'B': + if (uflag) + return; + if (!aflag && ((s->name[0] == '.' || s->name[0] == '$'))) + return; + break; + case 'b': + case 'd': + case 'l': + case 't': + if (uflag || gflag) + return; + if (!aflag && ((s->name[0] == '.' || s->name[0] == '$'))) + return; + break; + case 'U': + if (gflag) + return; + break; + case 'Z': + if (!aflag) + return; + break; + case 'm': + case 'f': /* we only see a 'z' when the following is true*/ + if(!aflag || uflag || gflag) + return; + if (strcmp(s->name, ".frame")) + zenter(s); + break; + case 'a': + case 'p': + case 'z': + default: + if(!aflag || uflag || gflag) + return; + break; + } + symptr = realloc(symptr, (nsym+1)*sizeof(Sym*)); + if (symptr == 0) { + error("out of memory"); + exits("memory"); + } + symptr[nsym++] = s; +} + +void +printsyms(Sym **symptr, long nsym) +{ + Sym *s; + char *cp; + char path[512]; + + if(!sflag) + qsort(symptr, nsym, sizeof(*symptr), cmp); + 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; + va_list arg; + + s = buf; + s += sprint(s, "%s: ", argv0); + va_start(arg, fmt); + s = vseprint(s, buf + sizeof(buf) / sizeof(*buf), fmt, arg); + va_end(arg); + *s++ = '\n'; + write(2, buf, s - buf); + errs = "errors"; +} -- cgit v1.2.3