1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms is permitted 6 * provided that all copyright information, including this notice, 7 * is retained in all such forms, and that any documentation, 8 * advertising or other materials related to such distribution and 9 * use acknowledge that the software was 10 * developed by the University of California, Berkeley. The name 11 * of the University may not be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19 #ifndef lint 20 char copyright[] = 21 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 22 All rights reserved.\n"; 23 #endif /* not lint */ 24 25 /* 26 * kvm_mkdb -- Create kernel information database for running kernel. 27 */ 28 29 #ifndef lint 30 static char sccsid[] = "@(#)kvm_mkdb.c 5.2 (Berkeley) 05/15/90"; 31 #endif /* not lint */ 32 #include <sys/param.h> 33 #include <sys/file.h> 34 #include <ndbm.h> 35 #include <a.out.h> 36 #include <kvm.h> 37 #include <paths.h> 38 #include <limits.h> 39 #include <errno.h> 40 #include <string.h> 41 #include <stdio.h> 42 43 char *tmp; 44 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 45 #define USAGE "kvm_mkdb" 46 extern errno; 47 48 char *progname; 49 50 main(argc, argv) 51 char *argv[]; 52 { 53 DBM *db; 54 char *nlistpath, *nlistname; 55 char dbtemp[MAXPATHLEN]; 56 char dbname[MAXPATHLEN]; 57 extern char *optarg; 58 extern int optind; 59 int ch; 60 61 progname = argv[0]; 62 while ((ch = getopt(argc, argv, "")) != EOF) 63 switch((char)ch) { 64 case '?': 65 default: 66 fprintf(stderr, "usage: %s", progname, USAGE); 67 exit(1); 68 } 69 argc -= optind; 70 argv += optind; 71 72 nlistpath = argc > 1 ? argv[0] : _PATH_UNIX; 73 nlistname = basename(nlistpath); 74 sprintf(dbtemp, "%s/kvm_tmp%s", KVMDBDIR, nlistname); 75 sprintf(dbname, "%s/kvm_%s", KVMDBDIR, nlistname); 76 rmdb(dbtemp); 77 umask(0); 78 if ((db = dbm_open(dbtemp, O_CREAT|O_WRONLY|O_EXCL, 0644)) == NULL) 79 syserrexit("error opening dbmfile"); 80 if (create_knlist(nlistpath, db) == -1) 81 errexit("error creating kernel namelist"); 82 if (create_devnames(db) == -1) 83 errexit("error creating devnames"); 84 rmdb(dbname); 85 mvdb(dbtemp, dbname); 86 87 exit(0); 88 } 89 90 rmdb(file) 91 char *file; 92 { 93 int len = strlen(file); 94 95 if (len > (MAXPATHLEN - 5)) 96 errexit("pathname too long: %s", file); 97 strcpy(file+len, ".dir"); 98 if (unlink(file) < 0 && errno != ENOENT) 99 syserrexit("can't unlink %s", file); 100 strcpy(file+len, ".pag"); 101 if (unlink(file) < 0 && errno != ENOENT) 102 syserrexit("can't unlink %s", file); 103 *(file+len) = '\0'; 104 } 105 106 mvdb(from, to) 107 char *from; 108 char *to; 109 { 110 int flen = strlen(from); 111 int tlen = strlen(to); 112 113 if (flen > (MAXPATHLEN - 5) || tlen > (MAXPATHLEN - 5)) 114 errexit("pathname too long: %s or %s", from, to); 115 strcpy(from+flen, ".dir"); 116 strcpy(to+tlen, ".dir"); 117 if (rename(from, to) == -1) 118 syserrexit("rename %s to %s", from, to); 119 strcpy(from+flen, ".pag"); 120 strcpy(to+tlen, ".pag"); 121 if (rename(from, to) == -1) 122 syserrexit("rename %s to %s", from, to); 123 *(from+flen) = *(to+tlen) = '\0'; 124 } 125 126 /* from libc/nlist.c */ 127 #include <unistd.h> 128 129 typedef struct nlist NLIST; 130 #define _strx n_un.n_strx 131 #define _name n_un.n_name 132 #define ISVALID(p) (p->_name && p->_name[0]) 133 #define MAXSYMSIZE 256 134 135 create_knlist(name, db) 136 char *name; 137 DBM *db; 138 { 139 register NLIST *p, *s; 140 struct exec ebuf; 141 FILE *fstr, *fsym; 142 NLIST nbuf; 143 off_t strings_offset, symbol_offset, symbol_size, lseek(); 144 char sbuf[MAXSYMSIZE+1]; 145 register char *bp; 146 register int c, len; 147 datum key, data; 148 149 if (!(fsym = fopen(name, "r"))) 150 syserrexit("can't open %s", name); 151 if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 || 152 N_BADMAG(ebuf)) 153 syserrexit("can't read exec"); 154 155 symbol_offset = N_SYMOFF(ebuf); 156 symbol_size = ebuf.a_syms; 157 strings_offset = symbol_offset + symbol_size; 158 159 if (fseek(fsym, symbol_offset, SEEK_SET) == -1) 160 syserrexit("can't seek symbol table: %x", symbol_offset); 161 if ((fstr = fopen(name, "r")) == NULL) 162 syserrexit("can't open %s", name); 163 164 sbuf[0] = KVMDB_NLIST; 165 key.dptr = sbuf; 166 data.dptr = (char *)&nbuf; 167 data.dsize = sizeof (NLIST); 168 169 for (s = &nbuf; symbol_size; symbol_size -= sizeof (NLIST)) { 170 if (fread((char *)s, sizeof (NLIST), 1, fsym) != 1) 171 syserrexit("can't read nlist entry"); 172 if (!s->_strx || s->n_type&N_STAB) 173 continue; 174 if (fseek(fstr, strings_offset + s->_strx, SEEK_SET) == -1) 175 syserrexit("can't seek string: %x", 176 strings_offset + s->_strx); 177 /* 178 * read string 179 */ 180 bp = sbuf + 1; 181 len = 0; 182 while ((c = fgetc(fstr)) != EOF && c != '\0') { 183 if (++len == MAXSYMSIZE) 184 errexit("string too long"); 185 *bp++ = c; 186 } 187 *bp = '\0'; 188 /* 189 * and store it 190 */ 191 key.dsize = bp - sbuf; 192 if (dbm_store(db, key, data, DBM_INSERT) < 0) 193 syserrexit("dbm_store"); 194 if (strcmp(sbuf+1, "_version") == 0) { 195 /* 196 * store the value of version in VERSION 197 */ 198 datum vers; 199 char versbuf[LINE_MAX]; 200 long versoff; 201 long reloffset; 202 203 /* 204 * Offset relative to start of text image in VM. 205 * On tahoe, first 0x800 is reserved for 206 * communication with the console processor. 207 */ 208 #ifdef tahoe 209 reloffset = ((s->n_value & ~KERNBASE) - 0x800); 210 #endif 211 #ifdef vax 212 reloffset = (s->n_value & ~KERNBASE); 213 #endif 214 /* 215 * When loaded, data is rounded 216 * to next 1024 after text, but not in file. 217 */ 218 reloffset -= 1024 - (ebuf.a_text % 1024); 219 versoff = N_TXTOFF(ebuf) + reloffset; 220 if (fseek(fstr, versoff, SEEK_SET) == -1) 221 syserrexit("seek (version): %x", s->n_value); 222 /* 223 * Just read version string up to, and 224 * including newline. 225 */ 226 if (fgets(versbuf, LINE_MAX, fstr) == NULL) 227 syserrexit("can't read version"); 228 strcpy(sbuf+1, "VERSION"); 229 key.dsize = (sizeof ("VERSION") - 1) + 1; 230 vers.dptr = versbuf; 231 vers.dsize = strlen(versbuf); 232 if (dbm_store(db, key, vers, DBM_INSERT) < 0) 233 syserrexit("dbm_store: can't store VERSION"); 234 } 235 } 236 (void)fclose(fstr); 237 (void)fclose(fsym); 238 return (0); 239 } 240 241 create_devnames() {} 242 243 #include <varargs.h> 244 245 warning(va_alist) 246 va_dcl 247 { 248 char *fmt; 249 va_list ap; 250 251 fprintf(stderr, "%s: warning: ", progname); 252 va_start(ap); 253 fmt = va_arg(ap, char *); 254 (void) vfprintf(stderr, fmt, ap); 255 va_end(ap); 256 fprintf(stderr, "\n"); 257 } 258 259 260 errexit(va_alist) 261 va_dcl 262 { 263 char *fmt; 264 va_list ap; 265 266 fprintf(stderr, "%s: ", progname); 267 va_start(ap); 268 fmt = va_arg(ap, char *); 269 (void) vfprintf(stderr, fmt, ap); 270 va_end(ap); 271 fprintf(stderr, "\n"); 272 exit(1); 273 } 274 275 276 syserrexit(va_alist) 277 va_dcl 278 { 279 char *fmt; 280 va_list ap; 281 282 fprintf(stderr, "%s: ", progname); 283 va_start(ap); 284 fmt = va_arg(ap, char *); 285 (void) vfprintf(stderr, fmt, ap); 286 va_end(ap); 287 fprintf(stderr, ": %s\n", strerror(errno)); 288 exit(1); 289 } 290