|
|
1.1 root 1: /*
2: * List a coff symbol table.
3: */
4: #include <misc.h>
5: #include <canon.h>
6: #include <l.out.h>
7: #include <ar.h>
8: #include <errno.h>
9:
10: FILE *fd; /* Current input file */
11:
12: int asw; /* list all symbols */
13: int dsw; /* list only defined symbols */
14: int gsw; /* print only global symbols */
15: int nsw; /* list numerically not alphabetically */
16: int osw; /* append file name to each line */
17: int psw; /* print symbols in symbol table order */
18: int rsw; /* print in reverse alpha order */
19: int usw; /* print only undefined symbols */
20: int vsw; /* print coff type symbols */
21:
22: int namesw; /* one if header is required */
23: char *str_tab;
24: char *fname;
25:
26: /*
27: * read or have an error.
28: */
29: static void
30: xread(to, size, msg)
31: char *to;
32: unsigned size;
33: char *msg;
34: {
35: if (1 != fread(to, size, 1, fd))
36: fatal("Error reading %s - %s", fname, msg);
37: }
38:
39: /*
40: * Old form sort logic.
41: */
42: ncomp_old(s1, s2)
43: struct nlist *s1, *s2;
44: {
45: long i;
46:
47: if (!(i = (s1->n_value - s2->n_value)))
48: return (0);
49: if (i < 0)
50: return (-1);
51: return (1);
52: }
53:
54: acomp_old(s1, s2)
55: struct nlist *s1, *s2;
56: {
57: return(strncmp(s1->n_name, s2->n_name, NCPLN));
58: }
59:
60: rcomp_old(s1, s2)
61: struct nlist *s1, *s2;
62: {
63: return(strncmp(s2->n_name, s1->n_name, NCPLN));
64: }
65:
66: /*
67: * Process old ar files.
68: */
69: old_ar(filen, at)
70: char *filen;
71: long at;
72: {
73: long arhend;
74: struct old_ar_hdr arh;
75:
76: namesw = 0;
77: for (arhend = at + sizeof(short); ; ) {
78: fseek(fd, arhend, 0);
79: if (1 != fread(&arh, sizeof(arh), 1, fd))
80: break;
81: arhend += sizeof(arh);
82: arh.ar_date = 0; /* terminate name */
83: cansize(arh.ar_size);
84: if (strcmp(arh.ar_name, HDRNAME)) {
85: printf("%s(%s)\n", filen, arh.ar_name);
86: readHeaders(arhend, arh.ar_size);
87: }
88: arhend += arh.ar_size;
89: }
90: namesw = 1;
91: }
92:
93: /*
94: * Process old form stuff.
95: */
96: old_nout(at)
97: long at;
98: {
99: struct ldheader ldh;
100: struct ldsym *sym, *s;
101: register unsigned i, syms, ct;
102: long toSym;
103: short type;
104: extern char *realloc();
105:
106: fseek(fd, at, 0);
107: xread(&ldh, sizeof(ldh), "n.out header");
108: if (!ldh.l_ssize[L_SYM]) {
109: printf("No symbols in %s\n", fname);
110: return;
111: }
112:
113: if (namesw)
114: printf("%s:\n", fname);
115:
116: canshort(ldh.l_machine);
117: toSym = ldh.l_entry + sizeof(ldh);
118:
119: for (i = 0; i < L_SYM; i++) {
120: cansize(ldh.l_ssize[i]);
121: if (i != L_BSSI && i != L_BSSD)
122: toSym += ldh.l_ssize[i];
123: }
124:
125: fseek(fd, at + toSym, 0);
126: cansize(ldh.l_ssize[L_SYM]);
127: i = ldh.l_ssize[L_SYM];
128: if (i != ldh.l_ssize[L_SYM])
129: fatal("Out of space");
130: sym = alloc(i);
131: xread(sym, i, "symbol table");
132: ct = i / sizeof(*sym);
133:
134: /* squeeze out unneeded stuff before sort */
135: for (i = syms = 0; i < ct; i++) {
136: canshort(sym[i].ls_type);
137: canshort(sym[i].ls_addr);
138: type = sym[i].ls_type;
139: if (gsw && !(type & L_GLOBAL))
140: continue;
141: if ((type & ~L_GLOBAL) == L_REF) { /* a reference */
142: if (dsw) /* list only defined */
143: continue;
144: if (usw && sym[i].ls_addr)
145: continue;
146: }
147: else if (usw)
148: continue;
149: if (!asw && !csymbol(sym + i))
150: continue;
151: if (i != syms)
152: sym[syms] = sym[i];
153: syms++;
154: }
155: sym = realloc(sym, syms * sizeof(*sym));
156:
157: if (nsw)
158: qsort(sym, syms, sizeof(*sym), ncomp_old);
159: else if (rsw)
160: qsort(sym, syms, sizeof(*sym), rcomp_old);
161: else if (!psw)
162: qsort(sym, syms, sizeof(*sym), acomp_old);
163:
164: for (s = sym; s < (sym + syms); s++) {
165: static char *gn[] = {
166: "SI", "PI", "BI",
167: "SD", "PD", "BD",
168: " D", " ", " ",
169: " A", " C", "??"
170: };
171: static char *ln[] = {
172: "si", "pi", "bi",
173: "sd", "pd", "bd",
174: " d", " ", " ",
175: " a", " c", "??"
176: };
177: if (osw)
178: printf("%s ", fname);
179: i = s->ls_type & L_GLOBAL;
180: type = s->ls_type & ~ L_GLOBAL;
181: if (type < L_SHRI || type > L_REF)
182: type = L_REF + 1;
183: if (type == L_REF && !s->ls_addr)
184: printf(" %c", i ? 'U' : 'u');
185: else
186: printf("%04x %s",
187: s->ls_addr,
188: i ? gn[type] : ln[type]);
189: printf(" %.*s\n", NCPLN, s->ls_id);
190: }
191:
192: free(sym);
193: }
194:
195: /*
196: * This routine gets called if we
197: * are not in '-a' mode. It determines if
198: * the symbol pointed to by 'sp' is a C
199: * style symbol (trailing '_' or longer than
200: * (NCPLN-1) characters). If it is it eats the '_'
201: * and returns true.
202: */
203: csymbol(sp)
204: register struct ldsym *sp;
205: {
206: register char *cp1, *cp2;
207:
208: cp1 = &sp->ls_id[0];
209: cp2 = &sp->ls_id[NCPLN];
210: while (cp2!=cp1 && *--cp2==0)
211: ;
212: if (*cp2 != 0) {
213: if (*cp2 == '_') {
214: *cp2 = 0;
215: return (1);
216: }
217: if (cp2-cp1 >= (NCPLN-1))
218: return (1);
219: }
220: return (0);
221: }
222:
223: /*
224: * Note some #defines in these include files interferes with
225: * items in preceeding include files. Hence the strange
226: * program order.
227: */
228: #include <coff.h>
229: #include <arcoff.h>
230:
231: #define cx(x) case C_ ## x: printf("%6.6s ", #x); break
232: #define ct(x) case T_ ## x: printf("%6.6s ", #x); break
233:
234: static char helpmsg[] =
235: "-d list only defined symbols\n"
236: "-g print only global symbols\n"
237: "-n list numerically not alphabetically\n"
238: "-o append file name to each line\n"
239: "-p print symbols in symbol table order\n"
240: "-r print in reverse alpha order\n"
241: "-u print only undefined symbols\n"
242: "-v print coff type symbols\n";
243:
244: FILEHDR fh;
245: SCNHDR *scns;
246:
247: /*
248: * Symbol name.
249: */
250: static char *
251: symName(sym, work)
252: SYMENT *sym;
253: char *work;
254: {
255: if (!sym->n_zeroes)
256: return (str_tab + sym->n_offset - 4);
257:
258: /* make sure it's zero terminated */
259: memcpy(work, sym->n_name, SYMNMLEN);
260: work[SYMNMLEN] = '\0';
261: return (work);
262: }
263:
264: main(argc, argv)
265: char *argv[];
266: {
267: char c;
268: extern int optind;
269: extern char *optarg;
270:
271: while (EOF != (c = getopt(argc, argv, "adgnopruv?"))) {
272: switch (c) {
273: case '?':
274: printf(helpmsg);
275: break;
276: case 'a':
277: asw = 1;
278: break;
279: case 'd':
280: dsw = 1;
281: break;
282: case 'g':
283: gsw = 1;
284: break;
285: case 'n':
286: nsw = 1;
287: break;
288: case 'o':
289: osw = 1;
290: break;
291: case 'p':
292: psw = 1;
293: break;
294: case 'r':
295: rsw = 1;
296: break;
297: case 'u':
298: usw = 1;
299: break;
300: case 'v':
301: vsw = 1;
302: break;
303: default:
304: printf("usage: nm [-dgnopruv?] file ...\n");
305: exit(1);
306: }
307: }
308:
309: if ((psw + rsw + nsw) > 1)
310: fatal("More than one sort order");
311:
312: namesw = (argc - optind) > 1;
313: for (; optind < argc; optind++) {
314: fd = xopen(fname = argv[optind], "rb");
315:
316: printf("%s\n", fname);
317: readHeaders(0L, 0L);
318: fclose(fd);
319: }
320:
321: exit (0);
322: }
323:
324: static
325: readHeaders(at, size)
326: long at, size;
327: {
328: unsigned i;
329:
330: if (1 != fread(&fh, sizeof(fh), 1, fd)) {
331: if (ferror(fd))
332: fatal("Error reading %s", fname);
333: printf("Inappropriate filetype %s\n", fname);
334: return (0);
335: }
336: if (C_386_MAGIC != fh.f_magic) {
337: if (!memcmp(ARMAG, &fh, SARMAG))
338: return(archive(at));
339:
340: canshort(fh.f_magic);
341: if (fh.f_magic == OLD_ARMAG)
342: return (old_ar(fname, at));
343: if (fh.f_magic == L_MAGIC)
344: return (old_nout(at));
345: printf("Inappropriate filetype %s\n", fname);
346: return (0);
347: }
348: if (fh.f_opthdr) /* pass opt hdr */
349: fseek(fd, at + sizeof(fh) + fh.f_opthdr, 0);
350: scns = alloc(i = (fh.f_nscns * sizeof(SCNHDR)));
351: xread(scns, i, "section headers");
352:
353: if (fh.f_nsyms)
354: readSymbols(at, size);
355: else
356: printf("No symbols in %s\n", fname);
357:
358: }
359:
360: /*
361: * Sort by alpha.
362: */
363: acomp(s1, s2)
364: SYMENT *s1, *s2;
365: {
366: char w1[SYMNMLEN + 1], w2[SYMNMLEN + 1];
367:
368: return (strcmp(symName(s1, w1), symName(s2, w2)));
369: }
370:
371: /*
372: * Sort by reverse alpha.
373: */
374: rcomp(s1, s2)
375: SYMENT *s1, *s2;
376: {
377: char w1[SYMNMLEN + 1], w2[SYMNMLEN + 1];
378:
379: return (- strcmp(symName(s1, w1), symName(s2, w2)));
380: }
381:
382: /*
383: * Sort by value;
384: */
385: ncomp(s1, s2)
386: SYMENT *s1, *s2;
387: {
388: long i;
389:
390: if (!(i = (s1->n_value - s2->n_value)))
391: return (0);
392: if (i < 0)
393: return (-1);
394: return (1);
395: }
396:
397: static
398: readSymbols(at, size)
399: long at;
400: {
401: register SYMENT *s;
402: SYMENT *sym;
403: long str_len;
404: unsigned len;
405: int i, aux, syms;
406: extern char *realloc();
407:
408: /* read whole symbol table */
409: fseek(fd, at + fh.f_symptr, 0);
410: len = str_len = SYMESZ * fh.f_nsyms;
411: if (str_len != len)
412: fatal("Cannot process small model");
413: sym = alloc(len);
414: xread(sym, len, "symbol table");
415:
416: /* squeeze out unneeded stuff before sort */
417: for (i = aux = syms = 0; i < fh.f_nsyms; i++) {
418: if (aux) {
419: aux--;
420: continue;
421: }
422: s = sym + i;
423: aux = s->n_numaux;
424: switch (s->n_sclass) {
425: case C_EXT:
426: if (s->n_scnum || s->n_value) { /* defined */
427: if (usw) /* print only undefined */
428: continue;
429: } else { /* undefined */
430: if (dsw) /* print only defined */
431: continue;
432: }
433: break;
434: case C_EXTDEF:
435: if (dsw)
436: continue;
437: break;
438: case C_STAT:
439: if (gsw || usw)
440: continue;
441: switch (s->n_scnum) {
442: case 1:
443: if (!strcmp(s->n_name, ".text"))
444: continue;
445: break;
446: case 2:
447: if (!strcmp(s->n_name, ".data"))
448: continue;
449: break;
450: case 3:
451: if (!strcmp(s->n_name, ".bss"))
452: continue;
453: break;
454: }
455: break;
456: default:
457: if (!vsw)
458: continue;
459: }
460: if (i != syms)
461: sym[syms] = *s;
462: syms++;
463: }
464: sym = realloc(sym, syms * SYMESZ);
465:
466: str_len = 0;
467: if (!size || ((fh.f_symptr + len + sizeof(long)) < size))
468: if (1 != fread(&str_len, sizeof(str_len), 1, fd))
469: str_len = 0;
470: if (str_len) {
471: len = str_len -= 4;
472: if (len != str_len)
473: fatal("Cannot process small model");
474: str_tab = alloc(len);
475: xread(str_tab, len, "string table");
476: }
477:
478: if (nsw)
479: qsort(sym, syms, SYMESZ, ncomp);
480: else if (rsw)
481: qsort(sym, syms, SYMESZ, rcomp);
482: else if (!psw)
483: qsort(sym, syms, SYMESZ, acomp);
484:
485: for (s = sym; s < (sym + syms); s++) {
486: char w1[SYMNMLEN + 1], *n;
487:
488: i = strlen(n = symName(s, w1));
489:
490: if (osw)
491: printf("%s ", fname);
492:
493: /* display section name */
494: switch (s->n_scnum) {
495: case N_DEBUG:
496: printf("DEBUG ");
497: break;
498: case N_ABS:
499: printf("ABSOLUTE ");
500: break;
501: case N_TV:
502: printf("TV ");
503: break;
504: case N_UNDEF:
505: if (s->n_value)
506: printf(".comm ");
507: else
508: printf("UNDEF ");
509: break;
510: default:
511: printf("%-8.8s ", scns[s->n_scnum - 1].s_name);
512: }
513:
514: if (vsw) { /* print coff type data */
515: /* display storage class */
516: switch (s->n_sclass) {
517: cx(EFCN);
518: cx(NULL);
519: cx(AUTO);
520: cx(EXT);
521: cx(STAT);
522: cx(REG);
523: cx(EXTDEF);
524: cx(LABEL);
525: cx(ULABEL);
526: cx(MOS);
527: cx(ARG);
528: cx(STRTAG);
529: cx(MOU);
530: cx(UNTAG);
531: cx(TPDEF);
532: cx(USTATIC);
533: cx(ENTAG);
534: cx(MOE);
535: cx(REGPARM);
536: cx(FIELD);
537: cx(BLOCK);
538: cx(FCN);
539: cx(EOS);
540: cx(FILE);
541: default:
542: printf("unknown ");
543: }
544:
545: if (s->n_type & N_TMASK) {
546: if (ISPTR(s->n_type))
547: printf("pointer ");
548: else if (ISFCN(s->n_type))
549: printf("function ");
550: else if (ISARY(s->n_type))
551: printf("array ");
552: else if (ISTAG(s->n_type))
553: printf("struct ");
554: else if (INCREF(s->n_type))
555: printf("union ");
556: else if (DECREF(s->n_type))
557: printf("enum ");
558: }
559: else
560: printf("- ");
561:
562: /* display type */
563: switch (BTYPE(s->n_type)) {
564: ct(NULL);
565: ct(ARG);
566: ct(CHAR);
567: ct(SHORT);
568: ct(INT);
569: ct(LONG);
570: ct(FLOAT);
571: ct(DOUBLE);
572: ct(STRUCT);
573: ct(UNION);
574: ct(ENUM);
575: ct(MOE);
576: ct(UCHAR);
577: ct(USHORT);
578: ct(UINT);
579: ct(ULONG);
580: default:
581: printf("unknown ");
582: }
583: }
584:
585: printf("%08lX %s\n", s->n_value, n);
586: }
587: free(sym);
588: }
589:
590: /*
591: * Print members of archive.
592: */
593: archive(at)
594: long at;
595: {
596: long arhend;
597: struct ar_hdr coff_arh;
598: struct old_ar_hdr arh;
599: char *p;
600: extern char *strchr();
601:
602: namesw = 0;
603: for (arhend = at + SARMAG; ; ) {
604: fseek(fd, arhend, 0);
605: if (1 != fread(&coff_arh, sizeof(coff_arh), 1, fd))
606: break;
607: memset(&arh, '\0', sizeof(arh));
608: memcpy(arh.ar_name, coff_arh.ar_name, DIRSIZ);
609: if (NULL != (p = strchr(arh.ar_name, '/')))
610: *p = '\0';
611:
612: sscanf(coff_arh.ar_date, "%ld %d %d %o %ld",
613: &arh.ar_date, &arh.ar_uid,
614: &arh.ar_gid, &arh.ar_mode, &arh.ar_size);
615:
616: arhend += sizeof(coff_arh);
617: if (arh.ar_name[0]) {
618: printf("%s(%s)\n", fname, arh.ar_name);
619: readHeaders(arhend, arh.ar_size);
620: }
621: arhend += arh.ar_size;
622: if (arhend & 1)
623: arhend++;
624: }
625: namesw = 1;
626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.