1 /* 2 * Copyright 1987 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1980 Regents of the University of California. 8 * All rights reserved. The Berkeley software License Agreement 9 * specifies the terms and conditions for redistribution. 10 */ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 #include <sys/types.h> 15 #include <sys/param.h> 16 #include <a.out.h> 17 18 #define BSIZ 8*1024 /* size of local buffers */ 19 20 /* 21 * _nlist - retreive attributes from name list (string table version) 22 * 23 * Note: This is a modified form of the original nlist() function. 24 * It takes a file descriptor instead of a filename argument 25 * and is intended to be called by nlist(3) and kvmnlist(3K). 26 * The algorithm has been modified from the original to use local 27 * (rather than stdio) buffering and issues considerably fewer lseeks. 28 */ 29 int 30 _nlist(int fd, struct nlist *list) 31 { 32 struct nlist *p, *q; 33 char *s1, *s2; 34 int soff; 35 int stroff = 0; 36 int n, m; 37 int maxlen, nreq; 38 long sa; /* symbol address */ 39 long ss; /* start of strings */ 40 struct exec buf; 41 struct nlist space[BSIZ/sizeof (struct nlist)]; 42 char strs[BSIZ]; 43 44 maxlen = 0; 45 for (q = list, nreq = 0; q->n_un.n_name && q->n_un.n_name[0]; 46 q++, nreq++) { 47 q->n_type = 0; 48 q->n_value = 0; 49 q->n_desc = 0; 50 q->n_other = 0; 51 n = strlen(q->n_un.n_name); 52 if (n > maxlen) 53 maxlen = n; 54 } 55 if ((fd == -1) || (lseek(fd, 0L, 0) == -1) || 56 (read(fd, (char*)&buf, sizeof buf) != sizeof buf) || N_BADMAG(buf)) 57 return (-1); 58 sa = N_SYMOFF(buf); 59 ss = sa + buf.a_syms; 60 n = buf.a_syms; 61 while (n) { 62 m = MIN(n, sizeof (space)); 63 lseek(fd, sa, 0); 64 if (read(fd, (char *)space, m) != m) 65 break; 66 sa += m; 67 n -= m; 68 for (q = space; (m -= sizeof (struct nlist)) >= 0; q++) { 69 soff = q->n_un.n_strx; 70 if (soff == 0 || q->n_type & N_STAB) 71 continue; 72 if ((soff + maxlen + 1) >= stroff) { 73 /* 74 * Read strings into local cache. 75 * Assumes (maxlen < sizeof (strs)). 76 */ 77 lseek(fd, ss+soff, 0); 78 read(fd, strs, sizeof strs); 79 stroff = soff + sizeof (strs); 80 } 81 for (p = list; 82 p->n_un.n_name && p->n_un.n_name[0]; 83 p++) { 84 if (p->n_type != 0) 85 continue; 86 s1 = p->n_un.n_name; 87 s2 = &strs[soff-(stroff-sizeof (strs))]; 88 while (*s1) { 89 if (*s1++ != *s2++) 90 goto cont; 91 } 92 if (*s2) 93 goto cont; 94 p->n_value = q->n_value; 95 p->n_type = q->n_type; 96 p->n_desc = q->n_desc; 97 p->n_other = q->n_other; 98 if (--nreq == 0) 99 goto alldone; 100 break; 101 cont: ; 102 } 103 } 104 } 105 alldone: 106 return (nreq); 107 } 108