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