11 CHUNK = 256 /* must be power of 2 */
14 char *errs; /* exit status */
15 char *filename; /* current file */
16 char symname[]="__.SYMDEF"; /* table of contents file name */
17 int multifile; /* processing multiple files */
26 Sym **fnames; /* file path translation table */
31 int cmp(void*, void*);
32 void error(char*, ...);
34 void psym(Sym*, void*);
35 void printsyms(Sym**, long);
43 fprint(2, "usage: nm [-aghnsTu] file ...\n");
48 main(int argc, char *argv[])
53 Binit(&bout, 1, OWRITE);
57 case 'a': aflag = 1; break;
58 case 'g': gflag = 1; break;
59 case 'h': hflag = 1; break;
60 case 'n': nflag = 1; break;
61 case 's': sflag = 1; break;
62 case 'u': uflag = 1; break;
63 case 'T': Tflag = 1; break;
69 for(i=0; i<argc; i++){
71 bin = Bopen(filename, OREAD);
73 error("cannot open %s", filename);
88 * read an archive file,
89 * processing the symbols for each intermediate file in it.
94 int offset, size, obj;
95 char membername[SARNAME];
98 for (offset = Boffset(bp);;offset += size) {
99 size = nextar(bp, offset, membername);
101 error("phase error on ar header %ld", offset);
106 if (strcmp(membername, symname) == 0)
108 obj = objtype(bp, 0);
110 error("inconsistent file %s in %s",
111 membername, filename);
114 if (!readar(bp, obj, offset+size, 1)) {
115 error("invalid symbol reference in file %s",
119 filename = membername;
121 objtraverse(psym, 0);
122 printsyms(symptr, nsym);
127 * process symbols in a file
134 obj = objtype(bp, 0);
136 execsyms(Bfildes(bp));
138 if (readobj(bp, obj)) {
140 objtraverse(psym, 0);
141 printsyms(symptr, nsym);
146 * comparison routine for sorting the symbol table
147 * this screws up on 'z' records when aflag == 1
150 cmp(void *vs, void *vt)
157 if((*s)->value < (*t)->value)
160 return (*s)->value > (*t)->value;
161 return strcmp((*s)->name, (*t)->name);
164 * enter a symbol in the table of filename elements
171 if (s->value > maxf) {
172 maxf = (s->value+CHUNK-1) &~ (CHUNK-1);
173 fnames = realloc(fnames, (maxf+1)*sizeof(*fnames));
175 error("out of memory", argv0);
179 fnames[s->value] = s;
183 * get the symbol table from an executable file, if it has one
193 if (crackhdr(fd, &f) == 0) {
194 error("Can't read header for %s", filename);
197 if (syminit(fd, &f) < 0)
204 printsyms(symptr, nsym);
208 psym(Sym *s, void* p)
218 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
227 if (!aflag && ((s->name[0] == '.' || s->name[0] == '$')))
239 case 'f': /* we only see a 'z' when the following is true*/
240 if(!aflag || uflag || gflag)
242 if (strcmp(s->name, ".frame"))
249 if(!aflag || uflag || gflag)
253 symptr = realloc(symptr, (nsym+1)*sizeof(Sym*));
255 error("out of memory");
262 printsyms(Sym **symptr, long nsym)
270 qsort(symptr, nsym, sizeof(*symptr), cmp);
273 for (i=0; i<nsym; i++) {
275 if (s->value && wid == 0)
277 else if (s->value >= 0x100000000LL && wid == 8)
280 for (i=0; i<nsym; i++) {
282 if (multifile && !hflag)
283 Bprint(&bout, "%s:", filename);
284 if (s->type == 'z') {
285 fileelem(fnames, (uchar *) s->name, path, 512);
290 Bprint(&bout, "%8ux ", s->sig);
291 if (s->value || s->type == 'a' || s->type == 'p')
292 Bprint(&bout, "%*llux ", wid, s->value);
294 Bprint(&bout, "%*s ", wid, "");
295 Bprint(&bout, "%c %s\n", s->type, cp);
300 error(char *fmt, ...)
306 fmtfdinit(&f, 2, buf, sizeof buf);
307 fmtprint(&f, "%s: ", argv0);
309 fmtvprint(&f, fmt, arg);