Home | History | Annotate | Line # | Download | only in kvm_mkdb
      1 /* $NetBSD: nlist_aout.c,v 1.10 2018/01/23 21:06:25 sevan Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 /*-
     33  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
     34  *
     35  * Redistribution and use in source and binary forms, with or without
     36  * modification, are permitted provided that the following conditions
     37  * are met:
     38  * 1. Redistributions of source code must retain the above copyright
     39  *    notice, this list of conditions and the following disclaimer.
     40  * 2. Redistributions in binary form must reproduce the above copyright
     41  *    notice, this list of conditions and the following disclaimer in the
     42  *    documentation and/or other materials provided with the distribution.
     43  * 3. All advertising materials mentioning features or use of this software
     44  *    must display the following acknowledgement:
     45  *	This product includes software developed by the University of
     46  *	California, Berkeley and its contributors.
     47  * 4. Neither the name of the University nor the names of its contributors
     48  *    may be used to endorse or promote products derived from this software
     49  *    without specific prior written permission.
     50  *
     51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61  * SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 #if 0
     67 static char sccsid[] = "from: @(#)nlist.c	8.1 (Berkeley) 6/6/93";
     68 #else
     69 __RCSID("$NetBSD: nlist_aout.c,v 1.10 2018/01/23 21:06:25 sevan Exp $");
     70 #endif
     71 #endif /* not lint */
     72 
     73 #include <sys/param.h>
     74 
     75 #include <a.out.h>
     76 #include <db.h>
     77 #include <err.h>
     78 #include <errno.h>
     79 #include <fcntl.h>
     80 #include <kvm.h>
     81 #include <limits.h>
     82 #include <stdio.h>
     83 #include <stdlib.h>
     84 #include <string.h>
     85 #include <unistd.h>
     86 
     87 #include "extern.h"
     88 
     89 #ifdef NLIST_AOUT
     90 
     91 typedef struct nlist NLIST;
     92 #define	_strx	n_un.n_strx
     93 #define	_name	n_un.n_name
     94 
     95 #define	badfmt(str)							\
     96 	do {								\
     97 		warnx("%s: %s: %s", kfile, str, strerror(EFTYPE));	\
     98 		punt();							\
     99 	} while (0)
    100 
    101 static void	badread(int, char *);
    102 static u_long	get_kerntext(const char *kfn);
    103 
    104 static const char *kfile;
    105 
    106 int
    107 create_knlist_aout(const char *name, DB *db)
    108 {
    109 	int nsyms;
    110 	struct exec ebuf;
    111 	FILE *fp;
    112 	NLIST nbuf;
    113 	DBT data, key;
    114 	int fd, nr, strsize;
    115 	u_long kerntextoff;
    116 	char *strtab, buf[1024];
    117 
    118 	kfile = name;
    119 	if ((fd = open(name, O_RDONLY, 0)) < 0) {
    120 		warn("%s", kfile);
    121 		punt();
    122 	}
    123 
    124 	/* Read in exec structure. */
    125 	nr = read(fd, &ebuf, sizeof(struct exec));
    126 	if (nr != sizeof(struct exec)) {
    127 		(void)close(fd);
    128 		return (-1);
    129 	}
    130 
    131 	/* Check magic number. */
    132 	if (N_BADMAG(ebuf)) {
    133 		(void)close(fd);
    134 		return (-1);
    135 	}
    136 
    137 	/*
    138 	 * We've recognized it as an a.out binary.  From here
    139 	 * on out, all errors are fatal.
    140 	 */
    141 
    142 	/* Check symbol count. */
    143 	if (!ebuf.a_syms)
    144 		badfmt("stripped");
    145 
    146 	/* Seek to string table. */
    147 	if (lseek(fd, N_STROFF(ebuf), SEEK_SET) == -1)
    148 		badfmt("corrupted string table");
    149 
    150 	/* Read in the size of the symbol table. */
    151 	nr = read(fd, (char *)&strsize, sizeof(strsize));
    152 	if (nr != sizeof(strsize))
    153 		badread(nr, "no symbol table");
    154 
    155 	/* Read in the string table. */
    156 	strsize -= sizeof(strsize);
    157 	if (!(strtab = malloc(strsize))) {
    158 		warn("malloc");
    159 		punt();
    160 	}
    161 	if ((nr = read(fd, strtab, strsize)) != strsize)
    162 		badread(nr, "corrupted symbol table");
    163 
    164 	/* Seek to symbol table. */
    165 	if (!(fp = fdopen(fd, "r"))) {
    166 		warn("%s", name);
    167 		punt();
    168 	}
    169 	if (fseek(fp, N_SYMOFF(ebuf), SEEK_SET) == -1) {
    170 		warn("%s", name);
    171 		punt();
    172 	}
    173 
    174 	data.data = (u_char *)&nbuf;
    175 	data.size = sizeof(NLIST);
    176 
    177 	kerntextoff = get_kerntext(name);
    178 
    179 	/* Read each symbol and enter it into the database. */
    180 	nsyms = ebuf.a_syms / sizeof(struct nlist);
    181 	while (nsyms--) {
    182 		if (fread((char *)&nbuf, sizeof (NLIST), 1, fp) != 1) {
    183 			if (feof(fp))
    184 				badfmt("corrupted symbol table");
    185 			warn("%s", name);
    186 			punt();
    187 		}
    188 		if (!nbuf._strx || nbuf.n_type&N_STAB)
    189 			continue;
    190 
    191 		key.data = (u_char *)strtab + nbuf._strx - sizeof(long);
    192 		key.size = strlen((char *)key.data);
    193 		if (db->put(db, &key, &data, 0)) {
    194 			warn("record enter");
    195 			punt();
    196 		}
    197 
    198 		if (strcmp((char *)key.data, VRS_SYM) == 0) {
    199 			long cur_off, voff;
    200 			/*
    201 			 * Calculate offset relative to a normal (non-kernel)
    202 			 * a.out.  Kerntextoff is where the kernel is really
    203 			 * loaded; N_TXTADDR is where a normal file is loaded.
    204 			 * From there, locate file offset in text or data.
    205 			 */
    206 			voff = nbuf.n_value - kerntextoff + N_TXTADDR(ebuf);
    207 			if ((nbuf.n_type & N_TYPE) == N_TEXT)
    208 				voff += N_TXTOFF(ebuf) - N_TXTADDR(ebuf);
    209 			else
    210 				voff += N_DATOFF(ebuf) - N_DATADDR(ebuf);
    211 			cur_off = ftell(fp);
    212 			if (fseek(fp, voff, SEEK_SET) == -1)
    213 				badfmt("corrupted string table");
    214 
    215 			/*
    216 			 * Read version string up to, and including newline.
    217 			 * This code assumes that a newline terminates the
    218 			 * version line.
    219 			 */
    220 			if (fgets(buf, sizeof(buf), fp) == NULL)
    221 				badfmt("corrupted string table");
    222 
    223 			key.data = (u_char *)VRS_KEY;
    224 			key.size = sizeof(VRS_KEY) - 1;
    225 			data.data = (u_char *)buf;
    226 			data.size = strlen(buf);
    227 			if (db->put(db, &key, &data, 0)) {
    228 				warn("record enter");
    229 				punt();
    230 			}
    231 
    232 			/* Restore to original values. */
    233 			data.data = (u_char *)&nbuf;
    234 			data.size = sizeof(NLIST);
    235 			if (fseek(fp, cur_off, SEEK_SET) == -1)
    236 				badfmt("corrupted string table");
    237 		}
    238 	}
    239 	(void)fclose(fp);
    240 
    241 	return (0);
    242 }
    243 
    244 static void
    245 badread(int nr, char *p)
    246 {
    247 	if (nr < 0) {
    248 		warn("%s", kfile);
    249 		punt();
    250 	}
    251 	badfmt(p);
    252 }
    253 
    254 /*
    255  * Instead of compiling in KERNTEXTOFF or KERNBASE, try to
    256  * determine the text start address from a standard symbol.
    257  * For backward compatibility, use the old compiled-in way
    258  * when the standard symbol name is not found.
    259  */
    260 static u_long
    261 get_kerntext(const char *name)
    262 {
    263 	struct nlist nl[2];
    264 
    265 	memset((caddr_t)nl, 0, sizeof(nl));
    266 	nl[0].n_un.n_name = "_kernel_text";
    267 
    268 	if (nlist(name, nl) != 0) {
    269 		warnx("%s: %s symbol missing",
    270 		    name, nl[0].n_un.n_name);
    271 		punt();
    272 	}
    273 
    274 	return (nl[0].n_value);
    275 }
    276 #endif /* NLIST_AOUT */
    277