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