xref: /original-bsd/lib/libc/gen/nlist.c (revision 237fdba6)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)nlist.c	5.7 (Berkeley) 06/01/90";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/types.h>
13 #include <sys/file.h>
14 #include <a.out.h>
15 #include <stdio.h>
16 #include <unistd.h>
17 
18 typedef struct nlist NLIST;
19 #define	_strx	n_un.n_strx
20 #define	_name	n_un.n_name
21 #define	ISVALID(p)	(p->_name && p->_name[0])
22 
23 nlist(name, list)
24 	char *name;
25 	NLIST *list;
26 {
27 	register NLIST *p, *s;
28 	struct exec ebuf;
29 	FILE *fstr, *fsym;
30 	NLIST nbuf;
31 	off_t strings_offset, symbol_offset, symbol_size, lseek();
32 	int entries, len, maxlen;
33 	char sbuf[256];
34 
35 	entries = -1;
36 
37 	if (!(fsym = fopen(name, "r")))
38 		return(-1);
39 	if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 ||
40 	    N_BADMAG(ebuf))
41 		goto done1;
42 
43 	symbol_offset = N_SYMOFF(ebuf);
44 	symbol_size = ebuf.a_syms;
45 	strings_offset = symbol_offset + symbol_size;
46 	if (fseek(fsym, symbol_offset, SEEK_SET))
47 		goto done1;
48 
49 	if (!(fstr = fopen(name, "r")))
50 		goto done1;
51 
52 	/*
53 	 * clean out any left-over information for all valid entries.
54 	 * Type and value defined to be 0 if not found; historical
55 	 * versions cleared other and desc as well.  Also figure out
56 	 * the largest string length so don't read any more of the
57 	 * string table than we have to.
58 	 */
59 	for (p = list, entries = maxlen = 0; ISVALID(p); ++p, ++entries) {
60 		p->n_type = 0;
61 		p->n_other = 0;
62 		p->n_desc = 0;
63 		p->n_value = 0;
64 		if ((len = strlen(p->_name)) > maxlen)
65 			maxlen = len;
66 	}
67 	if (++maxlen > sizeof(sbuf)) {		/* for the NULL */
68 		(void)fprintf(stderr, "nlist: symbol too large.\n");
69 		entries = -1;
70 		goto done2;
71 	}
72 
73 	for (s = &nbuf; symbol_size; symbol_size -= sizeof(NLIST)) {
74 		if (fread((char *)s, sizeof(NLIST), 1, fsym) != 1)
75 			goto done2;
76 		if (!s->_strx || s->n_type&N_STAB)
77 			continue;
78 		if (fseek(fstr, strings_offset + s->_strx, SEEK_SET))
79 			goto done2;
80 		(void)fread(sbuf, sizeof(sbuf[0]), maxlen, fstr);
81 		for (p = list; ISVALID(p); p++)
82 			if (!strcmp(p->_name, sbuf)) {
83 				p->n_value = s->n_value;
84 				p->n_type = s->n_type;
85 				p->n_desc = s->n_desc;
86 				p->n_other = s->n_other;
87 				if (!--entries)
88 					goto done2;
89 			}
90 	}
91 done2:	(void)fclose(fstr);
92 done1:	(void)fclose(fsym);
93 	return(entries);
94 }
95