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