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*53113Smckusick static char sccsid[] = "@(#)nlist.c 5.10 (Berkeley) 04/01/92"; 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> 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; 2453106Storek struct nlist *list; 251972Swnj { 2653106Storek int fd, n; 271972Swnj 2853106Storek fd = open(name, O_RDONLY, 0); 2953106Storek if (fd < 0) 3053106Storek return (-1); 31*53113Smckusick n = __fdnlist(fd, list); 3253106Storek (void)close(fd); 3353106Storek return (n); 3453106Storek } 3539649Sbostic 3653106Storek #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) 3739649Sbostic 3853106Storek int 3953106Storek __fdnlist(fd, list) 4053106Storek register int fd; 4153106Storek register struct nlist *list; 4253106Storek { 4353106Storek register struct nlist *p, *s; 4453106Storek register caddr_t strtab; 4553106Storek register off_t stroff, symoff; 4653106Storek register u_long symsize; 4753106Storek register int nent, strsize, cc; 4853106Storek struct nlist nbuf[1024]; 4953106Storek struct exec exec; 5053106Storek struct stat st; 5139649Sbostic 5253106Storek if (lseek(fd, (off_t)0, SEEK_SET) == -1 || 5353106Storek read(fd, &exec, sizeof(exec)) != sizeof(exec) || 5453106Storek N_BADMAG(exec) || fstat(fd, &st) < 0) 5553106Storek return (-1); 5639649Sbostic 5753106Storek symoff = N_SYMOFF(exec); 5853106Storek symsize = exec.a_syms; 5953106Storek stroff = symoff + symsize; 6053106Storek strsize = st.st_size - stroff; 6139649Sbostic /* 6253106Storek * Map string table into our address space. This gives us 6353106Storek * an easy way to randomly access all the strings, without 6453106Storek * making the memory allocation permanent as with malloc/free 6553106Storek * (i.e., munmap will return it to the system). 6653106Storek */ 6753106Storek strtab = mmap(0, strsize, PROT_READ, MAP_FILE, fd, stroff); 6853106Storek if (strtab == (char *)-1) 6953106Storek return (-1); 7053106Storek /* 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. 7653106Storek * 7753106Storek * XXX clearing anything other than n_type and n_value violates 7853106Storek * the semantics given in the man page. 7939649Sbostic */ 8053106Storek nent = 0; 8153106Storek 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; 8653106Storek ++nent; 871972Swnj } 8853106Storek if (lseek(fd, symoff, SEEK_SET) == -1) 8953106Storek return (-1); 901972Swnj 9153106Storek while (symsize > 0) { 9253106Storek cc = MIN(symsize, sizeof(nbuf)); 9353106Storek if (read(fd, nbuf, cc) != cc) 9453106Storek break; 9553106Storek symsize -= cc; 9653106Storek for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) { 9753106Storek register int soff = s->n_un.n_strx; 9853106Storek 9953106Storek if (soff == 0 || (s->n_type & N_STAB) != 0) 10053106Storek continue; 10153106Storek for (p = list; !ISLAST(p); p++) 10253106Storek if (!strcmp(&strtab[soff], p->n_un.n_name)) { 10353106Storek p->n_value = s->n_value; 10453106Storek p->n_type = s->n_type; 10553106Storek p->n_desc = s->n_desc; 10653106Storek p->n_other = s->n_other; 10753106Storek if (--nent <= 0) 10853106Storek break; 10953106Storek } 11053106Storek } 1111972Swnj } 11253106Storek munmap(strtab, strsize); 11353106Storek return (nent); 1141972Swnj } 115