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
_nlist(int fd,struct nlist * list)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