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