new version from scratch; this version uses relative offsets from the
[unix-history] / usr / src / lib / libc / gen / nlist.c
CommitLineData
bb0cfa24 1/*
4142a2c4
KB
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
bb0cfa24
DF
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
4142a2c4
KB
19static char sccsid[] = "@(#)nlist.c 5.3 (Berkeley) %G%";
20#endif /* LIBC_SCCS and not lint */
329a2d40 21
8fb9f90e 22#include <sys/types.h>
4142a2c4 23#include <sys/file.h>
8fb9f90e
BJ
24#include <a.out.h>
25#include <stdio.h>
4142a2c4
KB
26#include <unistd.h>
27
28typedef struct nlist NLIST;
29#define _strx n_un.n_strx
30#define _name n_un.n_name
31#define ISVALID(p) (p->_name && p->_name[0])
8fb9f90e 32
8fb9f90e
BJ
33nlist(name, list)
34 char *name;
4142a2c4 35 NLIST *list;
8fb9f90e 36{
4142a2c4
KB
37 register NLIST *p, *s;
38 struct exec ebuf;
39 FILE *fstr, *fsym;
40 NLIST nbuf;
41 off_t curoff, strings_offset, symbol_offset, symbol_size, lseek();
42 int entries, len, maxlen;
43 char sbuf[256];
8fb9f90e 44
4142a2c4
KB
45 entries = -1;
46
47 if (!(fsym = fopen(name, "r")))
329a2d40 48 return(-1);
4142a2c4
KB
49 if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 ||
50 N_BADMAG(ebuf))
51 goto done1;
52
53 symbol_offset = N_SYMOFF(ebuf);
54 symbol_size = ebuf.a_syms;
55 strings_offset = symbol_offset + symbol_size;
56 if (fseek(fsym, symbol_offset, SEEK_SET))
57 goto done1;
58
59 /*
60 * some versions of stdio do lseek's on every fseek call relative
61 * to the beginning of the file. For this reason, all string seeks
62 * are made relative to the beginning of the symbol table.
63 */
64 curoff = 0;
65 if (!(fstr = fopen(name, "r")))
66 goto done1;
67 if (fseek(fstr, strings_offset, SEEK_SET))
68 goto done2;
69
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 for (p = list, entries = maxlen = 0; ISVALID(p); ++p, ++entries) {
78 p->n_type = 0;
79 p->n_other = 0;
80 p->n_desc = 0;
81 p->n_value = 0;
82 if ((len = strlen(p->_name)) > maxlen)
83 maxlen = len;
84 }
85 if (++maxlen > sizeof(sbuf)) { /* for the NULL */
86 (void)fprintf(stderr, "nlist: symbol too large.\n");
87 entries = -1;
88 goto done2;
329a2d40 89 }
8fb9f90e 90
4142a2c4
KB
91 for (s = &nbuf; symbol_size--;) {
92 if (fread((char *)s, sizeof(NLIST), 1, fsym) != 1)
93 goto done2;
94 if (!s->_strx || s->n_type&N_STAB)
95 continue;
96 if (fseek(fstr, s->_strx - curoff, SEEK_CUR))
97 goto done2;
98 curoff = s->_strx +
99 fread(sbuf, sizeof(sbuf[0]), maxlen, fstr);
100 for (p = list; ISVALID(p); p++)
101 if (!strcmp(p->_name, sbuf)) {
102 p->n_value = s->n_value;
103 p->n_type = s->n_type;
104 p->n_desc = s->n_desc;
105 p->n_other = s->n_other;
106 if (!--entries)
107 goto done2;
8fb9f90e 108 }
8fb9f90e 109 }
4142a2c4
KB
110done2: (void)fclose(fstr);
111done1: (void)fclose(fsym);
112 return(entries);
8fb9f90e 113}