xref: /csrg-svn/usr.bin/nm/nm.c (revision 28296)
112672Ssam #ifndef lint
2*28296Skarels static	char sccsid[] = "@(#)nm.c 4.7 05/19/86";
312672Ssam #endif
4619Sbill /*
5619Sbill  * nm - print name list; VAX string table version
6619Sbill  */
7619Sbill #include <sys/types.h>
8653Sbill #include <ar.h>
9619Sbill #include <stdio.h>
10619Sbill #include <ctype.h>
11653Sbill #include <a.out.h>
12619Sbill #include <stab.h>
1313490Ssam #include <sys/stat.h>
14619Sbill 
15619Sbill #define	SELECT	archive ? archdr.ar_name : *xargv
16619Sbill 
17619Sbill int	aflg, gflg, nflg, oflg, pflg, uflg;
18619Sbill int	rflg = 1;
19619Sbill char	**xargv;
20619Sbill int	archive;
21619Sbill struct	ar_hdr	archdr;
22619Sbill union {
23619Sbill 	char	mag_armag[SARMAG+1];
24619Sbill 	struct	exec mag_exp;
25619Sbill } mag_un;
26619Sbill #define	OARMAG	0177545
27619Sbill FILE	*fi;
28619Sbill off_t	off;
29619Sbill off_t	ftell();
30619Sbill char	*malloc();
31619Sbill char	*realloc();
32619Sbill char	*strp;
33619Sbill char	*stab();
34619Sbill off_t	strsiz;
35619Sbill int	compare();
36619Sbill int	narg;
37619Sbill int	errs;
38619Sbill 
39619Sbill main(argc, argv)
40619Sbill char **argv;
41619Sbill {
42619Sbill 
43619Sbill 	if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
44619Sbill 		argv++;
45619Sbill 		while (*++*argv) switch (**argv) {
46619Sbill 
47619Sbill 		case 'n':
48619Sbill 			nflg++;
49619Sbill 			continue;
50619Sbill 		case 'g':
51619Sbill 			gflg++;
52619Sbill 			continue;
53619Sbill 		case 'u':
54619Sbill 			uflg++;
55619Sbill 			continue;
56619Sbill 		case 'r':
57619Sbill 			rflg = -1;
58619Sbill 			continue;
59619Sbill 		case 'p':
60619Sbill 			pflg++;
61619Sbill 			continue;
62619Sbill 		case 'o':
63619Sbill 			oflg++;
64619Sbill 			continue;
65619Sbill 		case 'a':
66619Sbill 			aflg++;
67619Sbill 			continue;
68619Sbill 		default:
69619Sbill 			fprintf(stderr, "nm: invalid argument -%c\n",
70619Sbill 			    *argv[0]);
71619Sbill 			exit(2);
72619Sbill 		}
73619Sbill 		argc--;
74619Sbill 	}
75619Sbill 	if (argc == 0) {
76619Sbill 		argc = 1;
77619Sbill 		argv[1] = "a.out";
78619Sbill 	}
79619Sbill 	narg = argc;
80619Sbill 	xargv = argv;
81619Sbill 	while (argc--) {
82619Sbill 		++xargv;
83619Sbill 		namelist();
84619Sbill 	}
85619Sbill 	exit(errs);
86619Sbill }
87619Sbill 
88619Sbill namelist()
89619Sbill {
90619Sbill 	register int j;
91619Sbill 
92619Sbill 	archive = 0;
93619Sbill 	fi = fopen(*xargv, "r");
94619Sbill 	if (fi == NULL) {
95619Sbill 		error(0, "cannot open");
96619Sbill 		return;
97619Sbill 	}
98619Sbill 	off = SARMAG;
99619Sbill 	fread((char *)&mag_un, 1, sizeof(mag_un), fi);
100619Sbill 	if (mag_un.mag_exp.a_magic == OARMAG) {
101619Sbill 		error(0, "old archive");
10217853Sralph 		goto out;
103619Sbill 	}
104619Sbill 	if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0)
105619Sbill 		archive++;
106619Sbill 	else if (N_BADMAG(mag_un.mag_exp)) {
107619Sbill 		error(0, "bad format");
10817853Sralph 		goto out;
109619Sbill 	}
110619Sbill 	fseek(fi, 0L, 0);
111619Sbill 	if (archive) {
112619Sbill 		nextel(fi);
113619Sbill 		if (narg > 1)
114619Sbill 			printf("\n%s:\n", *xargv);
115619Sbill 	}
116619Sbill 	do {
117619Sbill 		off_t o;
118619Sbill 		register i, n, c;
119619Sbill 		struct nlist *symp = NULL;
120619Sbill 		struct nlist sym;
121619Sbill 		struct stat stb;
122619Sbill 
123619Sbill 		fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi);
124619Sbill 		if (N_BADMAG(mag_un.mag_exp))
125619Sbill 			continue;
126619Sbill 		if (archive == 0)
127619Sbill 			fstat(fileno(fi), &stb);
128619Sbill 		o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec);
129619Sbill 		fseek(fi, o, 1);
130619Sbill 		n = mag_un.mag_exp.a_syms / sizeof(struct nlist);
131619Sbill 		if (n == 0) {
132619Sbill 			error(0, "no name list");
133619Sbill 			continue;
134619Sbill 		}
135619Sbill 		if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) >
13617424Sralph 		    (archive ? off : stb.st_size)) {
13717424Sralph 			error(0, "old format .o (no string table) or truncated file");
13817424Sralph 			continue;
13917424Sralph 		}
140619Sbill 		i = 0;
141619Sbill 		if (strp)
142619Sbill 			free(strp), strp = 0;
143619Sbill 		while (--n >= 0) {
144619Sbill 			fread((char *)&sym, 1, sizeof(sym), fi);
145619Sbill 			if (gflg && (sym.n_type&N_EXT)==0)
146619Sbill 				continue;
147619Sbill 			if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg))
148619Sbill 				continue;
149619Sbill 			if (symp==NULL)
150619Sbill 				symp = (struct nlist *)
151619Sbill 				    malloc(sizeof(struct nlist));
152619Sbill 			else
153619Sbill 				symp = (struct nlist *)
154619Sbill 				    realloc(symp,
155619Sbill 					(i+1)*sizeof(struct nlist));
156619Sbill 			if (symp == NULL)
157619Sbill 				error(1, "out of memory");
158619Sbill 			symp[i++] = sym;
159619Sbill 		}
160619Sbill 		if (archive && ftell(fi)+sizeof(off_t) >= off) {
161619Sbill 			error(0, "no string table (old format .o?)");
162619Sbill 			continue;
163619Sbill 		}
164619Sbill 		if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) {
165619Sbill 			error(0, "no string table (old format .o?)");
166619Sbill 			goto out;
167619Sbill 		}
168619Sbill 		strp = (char *)malloc(strsiz);
169619Sbill 		if (strp == NULL)
170619Sbill 			error(1, "ran out of memory");
171619Sbill 		if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1)
172619Sbill 			error(1, "error reading string table");
173619Sbill 		for (j = 0; j < i; j++)
174619Sbill 			if (symp[j].n_un.n_strx)
175619Sbill 				symp[j].n_un.n_name =
176619Sbill 				    symp[j].n_un.n_strx + strp;
177619Sbill 			else
178619Sbill 				symp[j].n_un.n_name = "";
179619Sbill 		if (pflg==0)
180619Sbill 			qsort(symp, i, sizeof(struct nlist), compare);
181619Sbill 		if ((archive || narg>1) && oflg==0)
182619Sbill 			printf("\n%s:\n", SELECT);
183619Sbill 		psyms(symp, i);
184619Sbill 		if (symp)
185619Sbill 			free((char *)symp), symp = 0;
186619Sbill 		if (strp)
187619Sbill 			free((char *)strp), strp = 0;
188619Sbill 	} while(archive && nextel(fi));
189619Sbill out:
190619Sbill 	fclose(fi);
191619Sbill }
192619Sbill 
193619Sbill psyms(symp, nsyms)
194619Sbill 	register struct nlist *symp;
195619Sbill 	int nsyms;
196619Sbill {
197619Sbill 	register int n, c;
198619Sbill 
199619Sbill 	for (n=0; n<nsyms; n++) {
200619Sbill 		c = symp[n].n_type;
201619Sbill 		if (c & N_STAB) {
202619Sbill 			if (oflg) {
203619Sbill 				if (archive)
204619Sbill 					printf("%s:", *xargv);
205619Sbill 				printf("%s:", SELECT);
206619Sbill 			}
207619Sbill 			printf("%08x - %02x %04x %5.5s %s\n",
208619Sbill 			    symp[n].n_value,
209619Sbill 			    symp[n].n_other & 0xff, symp[n].n_desc & 0xffff,
210619Sbill 			    stab(symp[n].n_type & 0xff),
211619Sbill 			    symp[n].n_un.n_name);
212619Sbill 			continue;
213619Sbill 		}
214*28296Skarels 		if (c == N_FN)
215*28296Skarels 			c = 'f';
216*28296Skarels 		else switch (c&N_TYPE) {
217619Sbill 
218619Sbill 		case N_UNDF:
219619Sbill 			c = 'u';
220619Sbill 			if (symp[n].n_value)
221619Sbill 				c = 'c';
222619Sbill 			break;
223619Sbill 		case N_ABS:
224619Sbill 			c = 'a';
225619Sbill 			break;
226619Sbill 		case N_TEXT:
227619Sbill 			c = 't';
228619Sbill 			break;
229619Sbill 		case N_DATA:
230619Sbill 			c = 'd';
231619Sbill 			break;
232619Sbill 		case N_BSS:
233619Sbill 			c = 'b';
234619Sbill 			break;
235*28296Skarels 		default:
236*28296Skarels 			c = '?';
237619Sbill 			break;
238619Sbill 		}
239619Sbill 		if (uflg && c!='u')
240619Sbill 			continue;
241619Sbill 		if (oflg) {
242619Sbill 			if (archive)
243619Sbill 				printf("%s:", *xargv);
244619Sbill 			printf("%s:", SELECT);
245619Sbill 		}
246619Sbill 		if (symp[n].n_type&N_EXT)
247619Sbill 			c = toupper(c);
248619Sbill 		if (!uflg) {
249619Sbill 			if (c=='u' || c=='U')
250619Sbill 				printf("        ");
251619Sbill 			else
252619Sbill 				printf(N_FORMAT, symp[n].n_value);
253619Sbill 			printf(" %c ", c);
254619Sbill 		}
255619Sbill 		printf("%s\n", symp[n].n_un.n_name);
256619Sbill l1:		;
257619Sbill 	}
258619Sbill }
259619Sbill 
260619Sbill compare(p1, p2)
261619Sbill struct nlist *p1, *p2;
262619Sbill {
263619Sbill 	register i;
264619Sbill 
265619Sbill 	if (nflg) {
266619Sbill 		if (p1->n_value > p2->n_value)
267619Sbill 			return(rflg);
268619Sbill 		if (p1->n_value < p2->n_value)
269619Sbill 			return(-rflg);
270619Sbill 	}
271619Sbill 	return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name));
272619Sbill }
273619Sbill 
274619Sbill nextel(af)
275619Sbill FILE *af;
276619Sbill {
277619Sbill 	register char *cp;
278619Sbill 	register r;
279619Sbill 	long arsize;
280619Sbill 
281619Sbill 	fseek(af, off, 0);
282619Sbill 	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
283619Sbill 	if (r != sizeof(struct ar_hdr))
284619Sbill 		return(0);
285619Sbill 	for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
286619Sbill 		if (*cp == ' ')
287619Sbill 			*cp = '\0';
288619Sbill 	arsize = atol(archdr.ar_size);
289619Sbill 	if (arsize & 1)
290619Sbill 		++arsize;
291619Sbill 	off = ftell(af) + arsize;	/* beginning of next element */
292619Sbill 	return(1);
293619Sbill }
294619Sbill 
295619Sbill error(n, s)
296619Sbill char *s;
297619Sbill {
298619Sbill 	fprintf(stderr, "nm: %s:", *xargv);
299619Sbill 	if (archive) {
300619Sbill 		fprintf(stderr, "(%s)", archdr.ar_name);
301619Sbill 		fprintf(stderr, ": ");
302619Sbill 	} else
303619Sbill 		fprintf(stderr, " ");
304619Sbill 	fprintf(stderr, "%s\n", s);
305619Sbill 	if (n)
306619Sbill 		exit(2);
307619Sbill 	errs = 1;
308619Sbill }
309619Sbill 
310619Sbill struct	stabnames {
311619Sbill 	int	st_value;
312619Sbill 	char	*st_name;
313619Sbill } stabnames[] ={
314619Sbill 	N_GSYM, "GSYM",
315619Sbill 	N_FNAME, "FNAME",
316619Sbill 	N_FUN, "FUN",
317619Sbill 	N_STSYM, "STSYM",
318619Sbill 	N_LCSYM, "LCSYM",
319619Sbill 	N_RSYM, "RSYM",
320619Sbill 	N_SLINE, "SLINE",
321619Sbill 	N_SSYM, "SSYM",
322619Sbill 	N_SO, "SO",
323619Sbill 	N_LSYM, "LSYM",
324619Sbill 	N_SOL, "SOL",
325619Sbill 	N_PSYM, "PSYM",
326619Sbill 	N_ENTRY, "ENTRY",
327619Sbill 	N_LBRAC, "LBRAC",
328619Sbill 	N_RBRAC, "RBRAC",
329619Sbill 	N_BCOMM, "BCOMM",
330619Sbill 	N_ECOMM, "ECOMM",
331619Sbill 	N_ECOML, "ECOML",
332619Sbill 	N_LENG, "LENG",
333859Sbill 	N_PC, "PC",
334619Sbill 	0, 0
335619Sbill };
336619Sbill 
337619Sbill char *
338619Sbill stab(val)
339619Sbill {
340619Sbill 	register struct stabnames *sp;
341619Sbill 	static char prbuf[32];
342619Sbill 
343619Sbill 	for (sp = stabnames; sp->st_name; sp++)
344619Sbill 		if (sp->st_value == val)
345619Sbill 			return (sp->st_name);
346619Sbill 	sprintf(prbuf, "%02x", val);
347619Sbill 	return (prbuf);
348619Sbill }
349