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