Home | History | Annotate | Download | only in common
      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