xref: /csrg-svn/lib/libc/mips/gen/nlist.c (revision 53106)
121349Sdist /*
239649Sbostic  * Copyright (c) 1989 The Regents of the University of California.
339649Sbostic  * All rights reserved.
439649Sbostic  *
542625Sbostic  * %sccs.include.redist.c%
621349Sdist  */
716668Sralph 
826572Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*53106Storek static char sccsid[] = "@(#)nlist.c	5.9 (Berkeley) 04/01/92";
1039649Sbostic #endif /* LIBC_SCCS and not lint */
1121349Sdist 
12*53106Storek #include <sys/param.h>
13*53106Storek #include <sys/mman.h>
14*53106Storek #include <sys/stat.h>
1539649Sbostic #include <sys/file.h>
161972Swnj #include <a.out.h>
171972Swnj #include <stdio.h>
1846597Sdonn #include <string.h>
1939649Sbostic #include <unistd.h>
201972Swnj 
2146597Sdonn int
221972Swnj nlist(name, list)
2346597Sdonn 	const char *name;
24*53106Storek 	struct nlist *list;
251972Swnj {
26*53106Storek 	int fd, n;
271972Swnj 
28*53106Storek 	fd = open(name, O_RDONLY, 0);
29*53106Storek 	if (fd < 0)
30*53106Storek 		return (-1);
31*53106Storek 	n = _fdnlist(fd, list);
32*53106Storek 	(void)close(fd);
33*53106Storek 	return (n);
34*53106Storek }
3539649Sbostic 
36*53106Storek #define	ISLAST(p)	(p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
3739649Sbostic 
38*53106Storek int
39*53106Storek __fdnlist(fd, list)
40*53106Storek 	register int fd;
41*53106Storek 	register struct nlist *list;
42*53106Storek {
43*53106Storek 	register struct nlist *p, *s;
44*53106Storek 	register caddr_t strtab;
45*53106Storek 	register off_t stroff, symoff;
46*53106Storek 	register u_long symsize;
47*53106Storek 	register int nent, strsize, cc;
48*53106Storek 	struct nlist nbuf[1024];
49*53106Storek 	struct exec exec;
50*53106Storek 	struct stat st;
5139649Sbostic 
52*53106Storek 	if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
53*53106Storek 	    read(fd, &exec, sizeof(exec)) != sizeof(exec) ||
54*53106Storek 	    N_BADMAG(exec) || fstat(fd, &st) < 0)
55*53106Storek 		return (-1);
5639649Sbostic 
57*53106Storek 	symoff = N_SYMOFF(exec);
58*53106Storek 	symsize = exec.a_syms;
59*53106Storek 	stroff = symoff + symsize;
60*53106Storek 	strsize = st.st_size - stroff;
6139649Sbostic 	/*
62*53106Storek 	 * Map string table into our address space.  This gives us
63*53106Storek 	 * an easy way to randomly access all the strings, without
64*53106Storek 	 * making the memory allocation permanent as with malloc/free
65*53106Storek 	 * (i.e., munmap will return it to the system).
66*53106Storek 	 */
67*53106Storek 	strtab = mmap(0, strsize, PROT_READ, MAP_FILE, fd, stroff);
68*53106Storek 	if (strtab == (char *)-1)
69*53106Storek 		return (-1);
70*53106Storek 	/*
7139649Sbostic 	 * clean out any left-over information for all valid entries.
7239649Sbostic 	 * Type and value defined to be 0 if not found; historical
7339649Sbostic 	 * versions cleared other and desc as well.  Also figure out
7439649Sbostic 	 * the largest string length so don't read any more of the
7539649Sbostic 	 * string table than we have to.
76*53106Storek 	 *
77*53106Storek 	 * XXX clearing anything other than n_type and n_value violates
78*53106Storek 	 * the semantics given in the man page.
7939649Sbostic 	 */
80*53106Storek 	nent = 0;
81*53106Storek 	for (p = list; !ISLAST(p); ++p) {
8239649Sbostic 		p->n_type = 0;
8339649Sbostic 		p->n_other = 0;
8439649Sbostic 		p->n_desc = 0;
8539649Sbostic 		p->n_value = 0;
86*53106Storek 		++nent;
871972Swnj 	}
88*53106Storek 	if (lseek(fd, symoff, SEEK_SET) == -1)
89*53106Storek 		return (-1);
901972Swnj 
91*53106Storek 	while (symsize > 0) {
92*53106Storek 		cc = MIN(symsize, sizeof(nbuf));
93*53106Storek 		if (read(fd, nbuf, cc) != cc)
94*53106Storek 			break;
95*53106Storek 		symsize -= cc;
96*53106Storek 		for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
97*53106Storek 			register int soff = s->n_un.n_strx;
98*53106Storek 
99*53106Storek 			if (soff == 0 || (s->n_type & N_STAB) != 0)
100*53106Storek 				continue;
101*53106Storek 			for (p = list; !ISLAST(p); p++)
102*53106Storek 				if (!strcmp(&strtab[soff], p->n_un.n_name)) {
103*53106Storek 					p->n_value = s->n_value;
104*53106Storek 					p->n_type = s->n_type;
105*53106Storek 					p->n_desc = s->n_desc;
106*53106Storek 					p->n_other = s->n_other;
107*53106Storek 					if (--nent <= 0)
108*53106Storek 						break;
109*53106Storek 				}
110*53106Storek 		}
1111972Swnj 	}
112*53106Storek 	munmap(strtab, strsize);
113*53106Storek 	return (nent);
1141972Swnj }
115