1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)nlist.c 5.10 (Berkeley) 04/01/92"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/param.h> 13 #include <sys/mman.h> 14 #include <sys/stat.h> 15 #include <sys/file.h> 16 #include <a.out.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 int 22 nlist(name, list) 23 const char *name; 24 struct nlist *list; 25 { 26 int fd, n; 27 28 fd = open(name, O_RDONLY, 0); 29 if (fd < 0) 30 return (-1); 31 n = __fdnlist(fd, list); 32 (void)close(fd); 33 return (n); 34 } 35 36 #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0) 37 38 int 39 __fdnlist(fd, list) 40 register int fd; 41 register struct nlist *list; 42 { 43 register struct nlist *p, *s; 44 register caddr_t strtab; 45 register off_t stroff, symoff; 46 register u_long symsize; 47 register int nent, strsize, cc; 48 struct nlist nbuf[1024]; 49 struct exec exec; 50 struct stat st; 51 52 if (lseek(fd, (off_t)0, SEEK_SET) == -1 || 53 read(fd, &exec, sizeof(exec)) != sizeof(exec) || 54 N_BADMAG(exec) || fstat(fd, &st) < 0) 55 return (-1); 56 57 symoff = N_SYMOFF(exec); 58 symsize = exec.a_syms; 59 stroff = symoff + symsize; 60 strsize = st.st_size - stroff; 61 /* 62 * Map string table into our address space. This gives us 63 * an easy way to randomly access all the strings, without 64 * making the memory allocation permanent as with malloc/free 65 * (i.e., munmap will return it to the system). 66 */ 67 strtab = mmap(0, strsize, PROT_READ, MAP_FILE, fd, stroff); 68 if (strtab == (char *)-1) 69 return (-1); 70 /* 71 * clean out any left-over information for all valid entries. 72 * Type and value defined to be 0 if not found; historical 73 * versions cleared other and desc as well. Also figure out 74 * the largest string length so don't read any more of the 75 * string table than we have to. 76 * 77 * XXX clearing anything other than n_type and n_value violates 78 * the semantics given in the man page. 79 */ 80 nent = 0; 81 for (p = list; !ISLAST(p); ++p) { 82 p->n_type = 0; 83 p->n_other = 0; 84 p->n_desc = 0; 85 p->n_value = 0; 86 ++nent; 87 } 88 if (lseek(fd, symoff, SEEK_SET) == -1) 89 return (-1); 90 91 while (symsize > 0) { 92 cc = MIN(symsize, sizeof(nbuf)); 93 if (read(fd, nbuf, cc) != cc) 94 break; 95 symsize -= cc; 96 for (s = nbuf; cc > 0; ++s, cc -= sizeof(*s)) { 97 register int soff = s->n_un.n_strx; 98 99 if (soff == 0 || (s->n_type & N_STAB) != 0) 100 continue; 101 for (p = list; !ISLAST(p); p++) 102 if (!strcmp(&strtab[soff], p->n_un.n_name)) { 103 p->n_value = s->n_value; 104 p->n_type = s->n_type; 105 p->n_desc = s->n_desc; 106 p->n_other = s->n_other; 107 if (--nent <= 0) 108 break; 109 } 110 } 111 } 112 munmap(strtab, strsize); 113 return (nent); 114 } 115