121349Sdist /*
2*61111Sbostic * Copyright (c) 1989, 1993
3*61111Sbostic * The Regents of the University of California. All rights reserved.
439649Sbostic *
542625Sbostic * %sccs.include.redist.c%
621349Sdist */
716668Sralph
826572Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*61111Sbostic static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 06/04/93";
1039649Sbostic #endif /* LIBC_SCCS and not lint */
1121349Sdist
1253106Storek #include <sys/param.h>
1353106Storek #include <sys/mman.h>
1453106Storek #include <sys/stat.h>
1539649Sbostic #include <sys/file.h>
1654371Sbostic
1754371Sbostic #include <errno.h>
181972Swnj #include <a.out.h>
191972Swnj #include <stdio.h>
2046597Sdonn #include <string.h>
2139649Sbostic #include <unistd.h>
221972Swnj
2346597Sdonn int
nlist(name,list)241972Swnj nlist(name, list)
2546597Sdonn const char *name;
2653106Storek struct nlist *list;
271972Swnj {
2853106Storek int fd, n;
291972Swnj
3053106Storek fd = open(name, O_RDONLY, 0);
3153106Storek if (fd < 0)
3253106Storek return (-1);
3353113Smckusick n = __fdnlist(fd, list);
3453106Storek (void)close(fd);
3553106Storek return (n);
3653106Storek }
3739649Sbostic
3853106Storek #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
3939649Sbostic
4053106Storek int
__fdnlist(fd,list)4153106Storek __fdnlist(fd, list)
4253106Storek register int fd;
4353106Storek register struct nlist *list;
4453106Storek {
4553106Storek register struct nlist *p, *s;
4653106Storek register caddr_t strtab;
4753106Storek register off_t stroff, symoff;
4853106Storek register u_long symsize;
4954371Sbostic register int nent, cc;
5054371Sbostic size_t strsize;
5153106Storek struct nlist nbuf[1024];
5253106Storek struct exec exec;
5353106Storek struct stat st;
5439649Sbostic
5553106Storek if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
5653106Storek read(fd, &exec, sizeof(exec)) != sizeof(exec) ||
5753106Storek N_BADMAG(exec) || fstat(fd, &st) < 0)
5853106Storek return (-1);
5939649Sbostic
6053106Storek symoff = N_SYMOFF(exec);
6153106Storek symsize = exec.a_syms;
6253106Storek stroff = symoff + symsize;
6354371Sbostic
6454371Sbostic /* Check for files too large to mmap. */
6554371Sbostic if (st.st_size - stroff > SIZE_T_MAX) {
6654371Sbostic errno = EFBIG;
6754371Sbostic return (-1);
6854371Sbostic }
6939649Sbostic /*
7053106Storek * Map string table into our address space. This gives us
7153106Storek * an easy way to randomly access all the strings, without
7253106Storek * making the memory allocation permanent as with malloc/free
7353106Storek * (i.e., munmap will return it to the system).
7453106Storek */
7554371Sbostic strsize = st.st_size - stroff;
7654371Sbostic strtab = mmap(NULL, (size_t)strsize, PROT_READ, 0, fd, stroff);
7753106Storek if (strtab == (char *)-1)
7853106Storek return (-1);
7953106Storek /*
8039649Sbostic * clean out any left-over information for all valid entries.
8139649Sbostic * Type and value defined to be 0 if not found; historical
8239649Sbostic * versions cleared other and desc as well. Also figure out
8339649Sbostic * the largest string length so don't read any more of the
8439649Sbostic * string table than we have to.
8553106Storek *
8653106Storek * XXX clearing anything other than n_type and n_value violates
8753106Storek * the semantics given in the man page.
8839649Sbostic */
8953106Storek nent = 0;
9053106Storek for (p = list; !ISLAST(p); ++p) {
9139649Sbostic p->n_type = 0;
9239649Sbostic p->n_other = 0;
9339649Sbostic p->n_desc = 0;
9439649Sbostic p->n_value = 0;
9553106Storek ++nent;
961972Swnj }
9753106Storek if (lseek(fd, symoff, SEEK_SET) == -1)
9853106Storek return (-1);
991972Swnj
10053106Storek while (symsize > 0) {
10153106Storek cc = MIN(symsize, sizeof(nbuf));
10253106Storek if (read(fd, nbuf, cc) != cc)
10353106Storek break;
10453106Storek symsize -= cc;
10553106Storek for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) {
10653106Storek register int soff = s->n_un.n_strx;
10753106Storek
10853106Storek if (soff == 0 || (s->n_type & N_STAB) != 0)
10953106Storek continue;
11053106Storek for (p = list; !ISLAST(p); p++)
11153106Storek if (!strcmp(&strtab[soff], p->n_un.n_name)) {
11253106Storek p->n_value = s->n_value;
11353106Storek p->n_type = s->n_type;
11453106Storek p->n_desc = s->n_desc;
11553106Storek p->n_other = s->n_other;
11653106Storek if (--nent <= 0)
11753106Storek break;
11853106Storek }
11953106Storek }
1201972Swnj }
12153106Storek munmap(strtab, strsize);
12253106Storek return (nent);
1231972Swnj }
124