1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 #include <sys/param.h>
13
14 #include <a.out.h>
15 #include <db.h>
16 #include <err.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <kvm.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "extern.h"
27
28 typedef struct nlist NLIST;
29 #define _strx n_un.n_strx
30 #define _name n_un.n_name
31
32 #define badfmt(str) errx(1, "%s: %s: %s", kfile, str, strerror(EFTYPE))
33
34 static void badread __P((int, char *));
35
36 static char *kfile;
37
38 void
create_knlist(name,db)39 create_knlist(name, db)
40 char *name;
41 DB *db;
42 {
43 register int nsyms;
44 struct exec ebuf;
45 FILE *fp;
46 NLIST nbuf;
47 DBT data, key;
48 int fd, nr, strsize;
49 char *strtab, buf[1024];
50
51 kfile = name;
52 if ((fd = open(name, O_RDONLY, 0)) < 0)
53 err(1, "%s", name);
54
55 /* Read in exec structure. */
56 nr = read(fd, &ebuf, sizeof(struct exec));
57 if (nr != sizeof(struct exec))
58 badfmt("no exec header");
59
60 /* Check magic number and symbol count. */
61 if (N_BADMAG(ebuf))
62 badfmt("bad magic number");
63 if (!ebuf.a_syms)
64 badfmt("stripped");
65
66 /* Seek to string table. */
67 if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1)
68 badfmt("corrupted string table");
69
70 /* Read in the size of the symbol table. */
71 nr = read(fd, (char *)&strsize, sizeof(strsize));
72 if (nr != sizeof(strsize))
73 badread(nr, "no symbol table");
74
75 /* Read in the string table. */
76 strsize -= sizeof(strsize);
77 if (!(strtab = malloc(strsize)))
78 err(1, NULL);
79 if ((nr = read(fd, strtab, strsize)) != strsize)
80 badread(nr, "corrupted symbol table");
81
82 /* Seek to symbol table. */
83 if (!(fp = fdopen(fd, "r")))
84 err(1, "%s", name);
85 if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1)
86 err(1, "%s", name);
87
88 data.data = (u_char *)&nbuf;
89 data.size = sizeof(NLIST);
90
91 /* Read each symbol and enter it into the database. */
92 nsyms = ebuf.a_syms / sizeof(struct nlist);
93 while (nsyms--) {
94 if (fread((char *)&nbuf, sizeof (NLIST), 1, fp) != 1) {
95 if (feof(fp))
96 badfmt("corrupted symbol table");
97 err(1, "%s", name);
98 }
99 if (!nbuf._strx || nbuf.n_type&N_STAB)
100 continue;
101
102 key.data = (u_char *)strtab + nbuf._strx - sizeof(long);
103 key.size = strlen((char *)key.data);
104 if (db->put(db, &key, &data, 0))
105 err(1, "record enter");
106
107 if (strcmp((char *)key.data, VRS_SYM) == 0) {
108 long cur_off, voff;
109 #ifndef KERNTEXTOFF
110 #define KERNTEXTOFF KERNBASE
111 #endif
112 /*
113 * Calculate offset relative to a normal (non-kernel)
114 * a.out. KERNTEXTOFF is where the kernel is really
115 * loaded; N_TXTADDR is where a normal file is loaded.
116 * From there, locate file offset in text or data.
117 */
118 voff = nbuf.n_value - KERNTEXTOFF + N_TXTADDR(ebuf);
119 if ((nbuf.n_type & N_TYPE) == N_TEXT)
120 voff += N_TXTOFF(ebuf) - N_TXTADDR(ebuf);
121 else
122 voff += N_DATOFF(ebuf) - N_DATADDR(ebuf);
123 cur_off = ftell(fp);
124 if (fseek(fp, voff, SEEK_SET) == -1)
125 badfmt("corrupted string table");
126
127 /*
128 * Read version string up to, and including newline.
129 * This code assumes that a newline terminates the
130 * version line.
131 */
132 if (fgets(buf, sizeof(buf), fp) == NULL)
133 badfmt("corrupted string table");
134
135 key.data = (u_char *)VRS_KEY;
136 key.size = sizeof(VRS_KEY) - 1;
137 data.data = (u_char *)buf;
138 data.size = strlen(buf);
139 if (db->put(db, &key, &data, 0))
140 err(1, "record enter");
141
142 /* Restore to original values. */
143 data.data = (u_char *)&nbuf;
144 data.size = sizeof(NLIST);
145 if (fseek(fp, cur_off, SEEK_SET) == -1)
146 badfmt("corrupted string table");
147 }
148 }
149 (void)fclose(fp);
150 }
151
152 static void
badread(nr,p)153 badread(nr, p)
154 int nr;
155 char *p;
156 {
157 if (nr < 0)
158 err(1, "%s", kfile);
159 badfmt(p);
160 }
161