xref: /original-bsd/usr.bin/nm/nm.c (revision 5998a314)
1 static	char sccsid[] = "@(#)nm.c 4.1 10/01/80";
2 /*
3  * nm - print name list; VAX string table version
4  */
5 #include <sys/types.h>
6 #include <ar.h>
7 #include <stdio.h>
8 #include <ctype.h>
9 #include <a.out.h>
10 #include <stab.h>
11 #include <pagsiz.h>
12 #include <stat.h>
13 
14 #define	SELECT	archive ? archdr.ar_name : *xargv
15 
16 int	aflg, gflg, nflg, oflg, pflg, uflg;
17 int	rflg = 1;
18 char	**xargv;
19 int	archive;
20 struct	ar_hdr	archdr;
21 union {
22 	char	mag_armag[SARMAG+1];
23 	struct	exec mag_exp;
24 } mag_un;
25 #define	OARMAG	0177545
26 FILE	*fi;
27 off_t	off;
28 off_t	ftell();
29 char	*malloc();
30 char	*realloc();
31 char	*strp;
32 char	*stab();
33 off_t	strsiz;
34 int	compare();
35 int	narg;
36 int	errs;
37 
38 main(argc, argv)
39 char **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 
87 namelist()
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) >
135 		    (archive ? off : stb.st_size))
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));
186 out:
187 	fclose(fi);
188 }
189 
190 psyms(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);
251 l1:		;
252 	}
253 }
254 
255 compare(p1, p2)
256 struct 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 
269 nextel(af)
270 FILE *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 
290 error(n, s)
291 char *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 
305 struct	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",
328 	N_PC, "PC",
329 	0, 0
330 };
331 
332 char *
333 stab(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 }
344