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