help updated for 'buffer' and new argument to 'window'
[unix-history] / usr / src / usr.bin / nm / nm.c
CommitLineData
7ea0db89 1#ifndef lint
7afd0a98 2static char sccsid[] = "@(#)nm.c 4.4 %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");
102 return;
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");
108 return;
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) >
9789d1cb 136 (archive ? off : stb.st_size))
c0bc0330
BJ
137 error(1, "old format .o (no string table) or truncated file");
138 i = 0;
139 if (strp)
140 free(strp), strp = 0;
141 while (--n >= 0) {
142 fread((char *)&sym, 1, sizeof(sym), fi);
143 if (gflg && (sym.n_type&N_EXT)==0)
144 continue;
145 if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg))
146 continue;
147 if (symp==NULL)
148 symp = (struct nlist *)
149 malloc(sizeof(struct nlist));
150 else
151 symp = (struct nlist *)
152 realloc(symp,
153 (i+1)*sizeof(struct nlist));
154 if (symp == NULL)
155 error(1, "out of memory");
156 symp[i++] = sym;
157 }
158 if (archive && ftell(fi)+sizeof(off_t) >= off) {
159 error(0, "no string table (old format .o?)");
160 continue;
161 }
162 if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) {
163 error(0, "no string table (old format .o?)");
164 goto out;
165 }
166 strp = (char *)malloc(strsiz);
167 if (strp == NULL)
168 error(1, "ran out of memory");
169 if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1)
170 error(1, "error reading string table");
171 for (j = 0; j < i; j++)
172 if (symp[j].n_un.n_strx)
173 symp[j].n_un.n_name =
174 symp[j].n_un.n_strx + strp;
175 else
176 symp[j].n_un.n_name = "";
177 if (pflg==0)
178 qsort(symp, i, sizeof(struct nlist), compare);
179 if ((archive || narg>1) && oflg==0)
180 printf("\n%s:\n", SELECT);
181 psyms(symp, i);
182 if (symp)
183 free((char *)symp), symp = 0;
184 if (strp)
185 free((char *)strp), strp = 0;
186 } while(archive && nextel(fi));
187out:
188 fclose(fi);
189}
190
191psyms(symp, nsyms)
192 register struct nlist *symp;
193 int nsyms;
194{
195 register int n, c;
196
197 for (n=0; n<nsyms; n++) {
198 c = symp[n].n_type;
199 if (c & N_STAB) {
200 if (oflg) {
201 if (archive)
202 printf("%s:", *xargv);
203 printf("%s:", SELECT);
204 }
205 printf("%08x - %02x %04x %5.5s %s\n",
206 symp[n].n_value,
207 symp[n].n_other & 0xff, symp[n].n_desc & 0xffff,
208 stab(symp[n].n_type & 0xff),
209 symp[n].n_un.n_name);
210 continue;
211 }
212 switch (c&N_TYPE) {
213
214 case N_UNDF:
215 c = 'u';
216 if (symp[n].n_value)
217 c = 'c';
218 break;
219 case N_ABS:
220 c = 'a';
221 break;
222 case N_TEXT:
223 c = 't';
224 break;
225 case N_DATA:
226 c = 'd';
227 break;
228 case N_BSS:
229 c = 'b';
230 break;
231 case N_FN:
232 c = 'f';
233 break;
234 }
235 if (uflg && c!='u')
236 continue;
237 if (oflg) {
238 if (archive)
239 printf("%s:", *xargv);
240 printf("%s:", SELECT);
241 }
242 if (symp[n].n_type&N_EXT)
243 c = toupper(c);
244 if (!uflg) {
245 if (c=='u' || c=='U')
246 printf(" ");
247 else
248 printf(N_FORMAT, symp[n].n_value);
249 printf(" %c ", c);
250 }
251 printf("%s\n", symp[n].n_un.n_name);
252l1: ;
253 }
254}
255
256compare(p1, p2)
257struct nlist *p1, *p2;
258{
259 register i;
260
261 if (nflg) {
262 if (p1->n_value > p2->n_value)
263 return(rflg);
264 if (p1->n_value < p2->n_value)
265 return(-rflg);
266 }
267 return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name));
268}
269
270nextel(af)
271FILE *af;
272{
273 register char *cp;
274 register r;
275 long arsize;
276
277 fseek(af, off, 0);
278 r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
279 if (r != sizeof(struct ar_hdr))
280 return(0);
281 for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
282 if (*cp == ' ')
283 *cp = '\0';
284 arsize = atol(archdr.ar_size);
285 if (arsize & 1)
286 ++arsize;
287 off = ftell(af) + arsize; /* beginning of next element */
288 return(1);
289}
290
291error(n, s)
292char *s;
293{
294 fprintf(stderr, "nm: %s:", *xargv);
295 if (archive) {
296 fprintf(stderr, "(%s)", archdr.ar_name);
297 fprintf(stderr, ": ");
298 } else
299 fprintf(stderr, " ");
300 fprintf(stderr, "%s\n", s);
301 if (n)
302 exit(2);
303 errs = 1;
304}
305
306struct stabnames {
307 int st_value;
308 char *st_name;
309} stabnames[] ={
310 N_GSYM, "GSYM",
311 N_FNAME, "FNAME",
312 N_FUN, "FUN",
313 N_STSYM, "STSYM",
314 N_LCSYM, "LCSYM",
315 N_RSYM, "RSYM",
316 N_SLINE, "SLINE",
317 N_SSYM, "SSYM",
318 N_SO, "SO",
319 N_LSYM, "LSYM",
320 N_SOL, "SOL",
321 N_PSYM, "PSYM",
322 N_ENTRY, "ENTRY",
323 N_LBRAC, "LBRAC",
324 N_RBRAC, "RBRAC",
325 N_BCOMM, "BCOMM",
326 N_ECOMM, "ECOMM",
327 N_ECOML, "ECOML",
328 N_LENG, "LENG",
6e8de00f 329 N_PC, "PC",
c0bc0330
BJ
330 0, 0
331};
332
333char *
334stab(val)
335{
336 register struct stabnames *sp;
337 static char prbuf[32];
338
339 for (sp = stabnames; sp->st_name; sp++)
340 if (sp->st_value == val)
341 return (sp->st_name);
342 sprintf(prbuf, "%02x", val);
343 return (prbuf);
344}