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