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