xref: /original-bsd/usr.sbin/kvm_mkdb/nlist.c (revision c3e32dec)
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
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
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