xref: /csrg-svn/lib/libc/gen/nlist.c (revision 39649)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)nlist.c	5.3 (Berkeley) 11/28/89";
20 #endif /* LIBC_SCCS and not lint */
21 
22 #include <sys/types.h>
23 #include <sys/file.h>
24 #include <a.out.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 
28 typedef struct nlist NLIST;
29 #define	_strx	n_un.n_strx
30 #define	_name	n_un.n_name
31 #define	ISVALID(p)	(p->_name && p->_name[0])
32 
33 nlist(name, list)
34 	char *name;
35 	NLIST *list;
36 {
37 	register NLIST *p, *s;
38 	struct exec ebuf;
39 	FILE *fstr, *fsym;
40 	NLIST nbuf;
41 	off_t curoff, strings_offset, symbol_offset, symbol_size, lseek();
42 	int entries, len, maxlen;
43 	char sbuf[256];
44 
45 	entries = -1;
46 
47 	if (!(fsym = fopen(name, "r")))
48 		return(-1);
49 	if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 ||
50 	    N_BADMAG(ebuf))
51 		goto done1;
52 
53 	symbol_offset = N_SYMOFF(ebuf);
54 	symbol_size = ebuf.a_syms;
55 	strings_offset = symbol_offset + symbol_size;
56 	if (fseek(fsym, symbol_offset, SEEK_SET))
57 		goto done1;
58 
59 	/*
60 	 * some versions of stdio do lseek's on every fseek call relative
61 	 * to the beginning of the file.  For this reason, all string seeks
62 	 * are made relative to the beginning of the symbol table.
63 	 */
64 	curoff = 0;
65 	if (!(fstr = fopen(name, "r")))
66 		goto done1;
67 	if (fseek(fstr, strings_offset, SEEK_SET))
68 		goto done2;
69 
70 	/*
71 	 * clean out any left-over information for all valid entries.
72 	 * Type and value defined to be 0 if not found; historical
73 	 * versions cleared other and desc as well.  Also figure out
74 	 * the largest string length so don't read any more of the
75 	 * string table than we have to.
76 	 */
77 	for (p = list, entries = maxlen = 0; ISVALID(p); ++p, ++entries) {
78 		p->n_type = 0;
79 		p->n_other = 0;
80 		p->n_desc = 0;
81 		p->n_value = 0;
82 		if ((len = strlen(p->_name)) > maxlen)
83 			maxlen = len;
84 	}
85 	if (++maxlen > sizeof(sbuf)) {		/* for the NULL */
86 		(void)fprintf(stderr, "nlist: symbol too large.\n");
87 		entries = -1;
88 		goto done2;
89 	}
90 
91 	for (s = &nbuf; symbol_size--;) {
92 		if (fread((char *)s, sizeof(NLIST), 1, fsym) != 1)
93 			goto done2;
94 		if (!s->_strx || s->n_type&N_STAB)
95 			continue;
96 		if (fseek(fstr, s->_strx - curoff, SEEK_CUR))
97 			goto done2;
98 		curoff = s->_strx +
99 		    fread(sbuf, sizeof(sbuf[0]), maxlen, fstr);
100 		for (p = list; ISVALID(p); p++)
101 			if (!strcmp(p->_name, sbuf)) {
102 				p->n_value = s->n_value;
103 				p->n_type = s->n_type;
104 				p->n_desc = s->n_desc;
105 				p->n_other = s->n_other;
106 				if (!--entries)
107 					goto done2;
108 			}
109 	}
110 done2:	(void)fclose(fstr);
111 done1:	(void)fclose(fsym);
112 	return(entries);
113 }
114