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