|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)nm.c 1.1 86/02/03 SMI"; /* from UCB X.X XX/XX/XX */
3: #endif
4:
5: /*
6: * nm - print name list; string table version
7: */
8: #include <sys/types.h>
9: #include <ar.h>
10: #include <stdio.h>
11: #include <ctype.h>
12: #include <a.out.h>
13: #include <stab.h>
14: #include <sys/stat.h>
15:
16: #define SELECT archive ? archdr.ar_name : *xargv
17:
18: int aflg, gflg, nflg, oflg, pflg, uflg;
19: int rflg = 1;
20: char **xargv;
21: int archive;
22: struct ar_hdr archdr;
23: union {
24: char mag_armag[SARMAG+1];
25: struct exec mag_exp;
26: } mag_un;
27: #define OARMAG 0177545
28: FILE *fi;
29: off_t off;
30: off_t ftell();
31: char *malloc();
32: char *realloc();
33: char *strp;
34: char *stab();
35: off_t strsiz;
36: int compare();
37: int narg;
38: int errs;
39:
40: main(argc, argv)
41: char **argv;
42: {
43:
44: if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
45: argv++;
46: while (*++*argv) switch (**argv) {
47:
48: case 'n':
49: nflg++;
50: continue;
51: case 'g':
52: gflg++;
53: continue;
54: case 'u':
55: uflg++;
56: continue;
57: case 'r':
58: rflg = -1;
59: continue;
60: case 'p':
61: pflg++;
62: continue;
63: case 'o':
64: oflg++;
65: continue;
66: case 'a':
67: aflg++;
68: continue;
69: default:
70: fprintf(stderr, "nm: invalid argument -%c\n",
71: *argv[0]);
72: exit(2);
73: }
74: argc--;
75: }
76: if (argc == 0) {
77: argc = 1;
78: argv[1] = "a.out";
79: }
80: narg = argc;
81: xargv = argv;
82: while (argc--) {
83: ++xargv;
84: namelist();
85: }
86: exit(errs);
87: }
88:
89: namelist()
90: {
91: register int j;
92:
93: archive = 0;
94: fi = fopen(*xargv, "r");
95: if (fi == NULL) {
96: error(0, "cannot open");
97: return;
98: }
99: off = SARMAG;
100: fread((char *)&mag_un, 1, sizeof(mag_un), fi);
101: if (mag_un.mag_exp.a_magic == OARMAG) {
102: error(0, "old archive");
103: goto out;
104: }
105: if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0)
106: archive++;
107: else if (N_BADMAG(mag_un.mag_exp)) {
108: error(0, "bad format");
109: goto out;
110: }
111: fseek(fi, 0L, 0);
112: if (archive) {
113: nextel(fi);
114: if (narg > 1)
115: printf("\n%s:\n", *xargv);
116: }
117: do {
118: off_t o;
119: register i, n, c;
120: struct nlist *symp = NULL;
121: struct nlist sym;
122: struct stat stb;
123:
124: fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi);
125: if (N_BADMAG(mag_un.mag_exp))
126: continue;
127: if (archive == 0)
128: fstat(fileno(fi), &stb);
129: o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec);
130: fseek(fi, o, 1);
131: n = mag_un.mag_exp.a_syms / sizeof(struct nlist);
132: if (n == 0) {
133: error(0, "no name list");
134: continue;
135: }
136: if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) >
137: (archive ? off : stb.st_size))
138: error(1, "old format .o (no string table) or truncated file");
139: i = 0;
140: if (strp)
141: free(strp), strp = 0;
142: while (--n >= 0) {
143: fread((char *)&sym, 1, sizeof(sym), fi);
144: if (gflg && (sym.n_type&N_EXT)==0)
145: continue;
146: if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg))
147: continue;
148: if (symp==NULL)
149: symp = (struct nlist *)
150: malloc(sizeof(struct nlist));
151: else
152: symp = (struct nlist *)
153: realloc(symp,
154: (i+1)*sizeof(struct nlist));
155: if (symp == NULL)
156: error(1, "out of memory");
157: symp[i++] = sym;
158: }
159: if (archive && ftell(fi)+sizeof(off_t) >= off) {
160: error(0, "no string table (old format .o?)");
161: continue;
162: }
163: if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) {
164: error(0, "no string table (old format .o?)");
165: goto out;
166: }
167: strp = (char *)malloc(strsiz);
168: if (strp == NULL)
169: error(1, "ran out of memory");
170: if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1)
171: error(1, "error reading string table");
172: for (j = 0; j < i; j++)
173: if (symp[j].n_un.n_strx)
174: symp[j].n_un.n_name =
175: symp[j].n_un.n_strx + strp;
176: else
177: symp[j].n_un.n_name = "";
178: if (pflg==0)
179: qsort(symp, i, sizeof(struct nlist), compare);
180: if ((archive || narg>1) && oflg==0)
181: printf("\n%s:\n", SELECT);
182: psyms(symp, i);
183: if (symp)
184: free((char *)symp), symp = 0;
185: if (strp)
186: free((char *)strp), strp = 0;
187: } while(archive && nextel(fi));
188: out:
189: fclose(fi);
190: }
191:
192: psyms(symp, nsyms)
193: register struct nlist *symp;
194: int nsyms;
195: {
196: register int n, c;
197:
198: for (n=0; n<nsyms; n++) {
199: c = symp[n].n_type;
200: if (c & N_STAB) {
201: if (oflg) {
202: if (archive)
203: printf("%s:", *xargv);
204: printf("%s:", SELECT);
205: }
206: printf("%08x - %02x %04x %5.5s %s\n",
207: symp[n].n_value,
208: symp[n].n_other & 0xff, symp[n].n_desc & 0xffff,
209: stab(symp[n].n_type & 0xff),
210: symp[n].n_un.n_name);
211: continue;
212: }
213: switch (c&N_TYPE) {
214:
215: case N_UNDF:
216: c = 'u';
217: if (symp[n].n_value)
218: c = 'c';
219: break;
220: case N_ABS:
221: c = 'a';
222: break;
223: case N_TEXT:
224: c = 't';
225: break;
226: case N_DATA:
227: c = 'd';
228: break;
229: case N_BSS:
230: c = 'b';
231: break;
232: case N_FN:
233: c = 'f';
234: break;
235: }
236: if (uflg && c!='u')
237: continue;
238: if (oflg) {
239: if (archive)
240: printf("%s:", *xargv);
241: printf("%s:", SELECT);
242: }
243: if (symp[n].n_type&N_EXT)
244: c = toupper(c);
245: if (!uflg) {
246: if (c=='u' || c=='U')
247: printf(" ");
248: else
249: printf(N_FORMAT, symp[n].n_value);
250: printf(" %c ", c);
251: }
252: printf("%s\n", symp[n].n_un.n_name);
253: l1: ;
254: }
255: }
256:
257: compare(p1, p2)
258: struct nlist *p1, *p2;
259: {
260: register i;
261:
262: if (nflg) {
263: if (p1->n_value > p2->n_value)
264: return(rflg);
265: if (p1->n_value < p2->n_value)
266: return(-rflg);
267: }
268: return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name));
269: }
270:
271: nextel(af)
272: FILE *af;
273: {
274: register char *cp;
275: register r;
276: long arsize;
277:
278: fseek(af, off, 0);
279: r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
280: if (r != sizeof(struct ar_hdr))
281: return(0);
282: for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
283: if (*cp == ' ')
284: *cp = '\0';
285: arsize = atol(archdr.ar_size);
286: if (arsize & 1)
287: ++arsize;
288: off = ftell(af) + arsize; /* beginning of next element */
289: return(1);
290: }
291:
292: error(n, s)
293: char *s;
294: {
295: fprintf(stderr, "nm: %s:", *xargv);
296: if (archive) {
297: fprintf(stderr, "(%s)", archdr.ar_name);
298: fprintf(stderr, ": ");
299: } else
300: fprintf(stderr, " ");
301: fprintf(stderr, "%s\n", s);
302: if (n)
303: exit(2);
304: errs = 1;
305: }
306:
307: struct stabnames {
308: int st_value;
309: char *st_name;
310: } stabnames[] ={
311: N_GSYM, "GSYM",
312: N_FNAME, "FNAME",
313: N_FUN, "FUN",
314: N_STSYM, "STSYM",
315: N_LCSYM, "LCSYM",
316: N_RSYM, "RSYM",
317: N_SLINE, "SLINE",
318: N_SSYM, "SSYM",
319: N_SO, "SO",
320: N_LSYM, "LSYM",
321: N_BINCL, "BINCL",
322: N_SOL, "SOL",
323: N_PSYM, "PSYM",
324: N_ENTRY, "ENTRY",
325: N_LBRAC, "LBRAC",
326: N_RBRAC, "RBRAC",
327: N_EXCL, "EXCL",
328: N_BCOMM, "BCOMM",
329: N_ECOMM, "ECOMM",
330: N_ECOML, "ECOML",
331: N_LENG, "LENG",
332: N_EINCL, "EINCL",
333: N_PC, "PC",
334: 0, 0
335: };
336:
337: char *
338: stab(val)
339: {
340: register struct stabnames *sp;
341: static char prbuf[32];
342:
343: for (sp = stabnames; sp->st_name; sp++)
344: if (sp->st_value == val)
345: return (sp->st_name);
346: sprintf(prbuf, "%02x", val);
347: return (prbuf);
348: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.