1 /*- 2 * Copyright (c) 1989, 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software developed by the Computer Systems 6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7 * BG 91-66 and contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 #if defined(LIBC_SCCS) && !defined(lint) 13 static char sccsid[] = "@(#)kvm.c 5.32 (Berkeley) 10/17/92"; 14 #endif /* LIBC_SCCS and not lint */ 15 16 #include <sys/param.h> 17 #include <sys/user.h> 18 #include <sys/proc.h> 19 #include <sys/ioctl.h> 20 #include <sys/stat.h> 21 #include <machine/vmparam.h> 22 #include <fcntl.h> 23 #include <nlist.h> 24 #include <kvm.h> 25 #include <db.h> 26 #include <paths.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <ctype.h> 32 33 #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/ 34 #include <vm/vm_param.h> 35 #include <vm/swap_pager.h> 36 #include <sys/kinfo_proc.h> 37 38 #include <limits.h> 39 40 #include "kvm_private.h" 41 42 static int kvm_dbopen(kvm_t *, const char *); 43 44 char * 45 kvm_geterr(kvm_t *kd) 46 { 47 return (kd->errbuf); 48 } 49 50 #if __STDC__ 51 #include <stdarg.h> 52 #else 53 #include <varargs.h> 54 #endif 55 56 /* 57 * Report an error using printf style arguments. "program" is kd->program 58 * on hard errors, and 0 on soft errors, so that under sun error emulation, 59 * only hard errors are printed out (otherwise, programs like gdb will 60 * generate tons of error messages when trying to access bogus pointers). 61 */ 62 void 63 #if __STDC__ 64 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 65 #else 66 _kvm_err(kd, program, fmt, va_alist) 67 kvm_t *kd; 68 char *program, *fmt; 69 va_dcl 70 #endif 71 { 72 va_list ap; 73 74 #ifdef __STDC__ 75 va_start(ap, fmt); 76 #else 77 va_start(ap); 78 #endif 79 if (program != NULL) { 80 (void)fprintf(stderr, "%s: ", program); 81 (void)vfprintf(stderr, fmt, ap); 82 (void)fputc('\n', stderr); 83 } else 84 (void)vsnprintf(kd->errbuf, 85 sizeof(kd->errbuf), (char *)fmt, ap); 86 87 va_end(ap); 88 } 89 90 void 91 #if __STDC__ 92 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 93 #else 94 _kvm_syserr(kd, program, fmt, va_alist) 95 kvm_t *kd; 96 char *program, *fmt; 97 va_dcl 98 #endif 99 { 100 va_list ap; 101 register int n; 102 103 #if __STDC__ 104 va_start(ap, fmt); 105 #else 106 va_start(ap); 107 #endif 108 if (program != NULL) { 109 (void)fprintf(stderr, "%s: ", program); 110 (void)vfprintf(stderr, fmt, ap); 111 (void)fprintf(stderr, ": %s\n", strerror(errno)); 112 } else { 113 register char *cp = kd->errbuf; 114 115 (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 116 n = strlen(cp); 117 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 118 strerror(errno)); 119 } 120 va_end(ap); 121 } 122 123 void * 124 _kvm_malloc(kd, n) 125 register kvm_t *kd; 126 register size_t n; 127 { 128 void *p; 129 130 if ((p = malloc(n)) == NULL) 131 _kvm_err(kd, kd->program, strerror(errno)); 132 return (p); 133 } 134 135 static kvm_t * 136 _kvm_open(kd, uf, mf, sf, flag, errout) 137 register kvm_t *kd; 138 const char *uf; 139 const char *mf; 140 const char *sf; 141 int flag; 142 char *errout; 143 { 144 struct stat st; 145 146 kd->vmfd = -1; 147 kd->pmfd = -1; 148 kd->swfd = -1; 149 kd->nlfd = -1; 150 kd->vmst = 0; 151 kd->db = 0; 152 kd->procbase = 0; 153 kd->argspc = 0; 154 kd->argv = 0; 155 156 if (uf == 0) 157 uf = _PATH_UNIX; 158 else if (strlen(uf) >= MAXPATHLEN) { 159 _kvm_err(kd, kd->program, "exec file name too long"); 160 goto failed; 161 } 162 if (flag & ~O_RDWR) { 163 _kvm_err(kd, kd->program, "bad flags arg"); 164 goto failed; 165 } 166 if (mf == 0) 167 mf = _PATH_MEM; 168 if (sf == 0) 169 sf = _PATH_DRUM; 170 171 if ((kd->pmfd = open(mf, flag, 0)) < 0) { 172 _kvm_syserr(kd, kd->program, "%s", mf); 173 goto failed; 174 } 175 if (fstat(kd->pmfd, &st) < 0) { 176 _kvm_syserr(kd, kd->program, "%s", mf); 177 goto failed; 178 } 179 if (S_ISCHR(st.st_mode)) { 180 /* 181 * If this is a character special device, then check that 182 * it's /dev/mem. If so, open kmem too. (Maybe we should 183 * make it work for either /dev/mem or /dev/kmem -- in either 184 * case you're working with a live kernel.) 185 */ 186 if (strcmp(mf, _PATH_MEM) != 0) { /* XXX */ 187 _kvm_err(kd, kd->program, 188 "%s: not physical memory device", mf); 189 goto failed; 190 } 191 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 192 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 193 goto failed; 194 } 195 if ((kd->swfd = open(sf, flag, 0)) < 0) { 196 _kvm_syserr(kd, kd->program, "%s", sf); 197 goto failed; 198 } 199 /* 200 * Open kvm nlist database. We go ahead and do this 201 * here so that we don't have to hold on to the vmunix 202 * path name. Since a kvm application will surely do 203 * a kvm_nlist(), this probably won't be a wasted effort. 204 * If the database cannot be opened, open the namelist 205 * argument so we revert to slow nlist() calls. 206 */ 207 if (kvm_dbopen(kd, uf) < 0 && 208 (kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 209 _kvm_syserr(kd, kd->program, "%s", uf); 210 goto failed; 211 } 212 } else { 213 /* 214 * This is a crash dump. 215 * Initalize the virtual address translation machinery, 216 * but first setup the namelist fd. 217 */ 218 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 219 _kvm_syserr(kd, kd->program, "%s", uf); 220 goto failed; 221 } 222 if (_kvm_initvtop(kd) < 0) 223 goto failed; 224 } 225 return (kd); 226 failed: 227 /* 228 * Copy out the error if doing sane error semantics. 229 */ 230 if (errout != 0) 231 strcpy(errout, kd->errbuf); 232 (void)kvm_close(kd); 233 return (0); 234 } 235 236 kvm_t * 237 kvm_openfiles(uf, mf, sf, flag, errout) 238 const char *uf; 239 const char *mf; 240 const char *sf; 241 int flag; 242 char *errout; 243 { 244 register kvm_t *kd; 245 246 if ((kd = malloc(sizeof(*kd))) == NULL) { 247 (void)strcpy(errout, strerror(errno)); 248 return (0); 249 } 250 kd->program = 0; 251 return (_kvm_open(kd, uf, mf, sf, flag, errout)); 252 } 253 254 kvm_t * 255 kvm_open(uf, mf, sf, flag, program) 256 const char *uf; 257 const char *mf; 258 const char *sf; 259 int flag; 260 const char *program; 261 { 262 register kvm_t *kd; 263 264 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) { 265 (void)fprintf(stderr, "%s: %s\n", strerror(errno)); 266 return (0); 267 } 268 kd->program = program; 269 return (_kvm_open(kd, uf, mf, sf, flag, NULL)); 270 } 271 272 int 273 kvm_close(kd) 274 kvm_t *kd; 275 { 276 register int error = 0; 277 278 if (kd->pmfd >= 0) 279 error |= close(kd->pmfd); 280 if (kd->vmfd >= 0) 281 error |= close(kd->vmfd); 282 if (kd->nlfd >= 0) 283 error |= close(kd->nlfd); 284 if (kd->swfd >= 0) 285 error |= close(kd->swfd); 286 if (kd->db != 0) 287 error |= (kd->db->close)(kd->db); 288 if (kd->vmst) 289 _kvm_freevtop(kd); 290 if (kd->procbase != 0) 291 free((void *)kd->procbase); 292 if (kd->argv != 0) 293 free((void *)kd->argv); 294 free((void *)kd); 295 296 return (0); 297 } 298 299 /* 300 * Set up state necessary to do queries on the kernel namelist 301 * data base. If the data base is out-of-data/incompatible with 302 * given executable, set up things so we revert to standard nlist call. 303 * Only called for live kernels. Return 0 on success, -1 on failure. 304 */ 305 static int 306 kvm_dbopen(kd, uf) 307 kvm_t *kd; 308 const char *uf; 309 { 310 char *cp; 311 DBT rec; 312 int dbversionlen; 313 struct nlist nitem; 314 char dbversion[_POSIX2_LINE_MAX]; 315 char kversion[_POSIX2_LINE_MAX]; 316 char dbname[MAXPATHLEN]; 317 318 if ((cp = rindex(uf, '/')) != 0) 319 uf = cp + 1; 320 321 (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf); 322 kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL); 323 if (kd->db == 0) 324 return (-1); 325 /* 326 * read version out of database 327 */ 328 rec.data = VRS_KEY; 329 rec.size = sizeof(VRS_KEY) - 1; 330 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 331 goto close; 332 if (rec.data == 0 || rec.size > sizeof(dbversion)) 333 goto close; 334 335 bcopy(rec.data, dbversion, rec.size); 336 dbversionlen = rec.size; 337 /* 338 * Read version string from kernel memory. 339 * Since we are dealing with a live kernel, we can call kvm_read() 340 * at this point. 341 */ 342 rec.data = VRS_SYM; 343 rec.size = sizeof(VRS_SYM) - 1; 344 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 345 goto close; 346 if (rec.data == 0 || rec.size != sizeof(struct nlist)) 347 goto close; 348 bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem)); 349 if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) != 350 dbversionlen) 351 goto close; 352 /* 353 * If they match, we win - otherwise clear out kd->db so 354 * we revert to slow nlist(). 355 */ 356 if (bcmp(dbversion, kversion, dbversionlen) == 0) 357 return (0); 358 close: 359 (void)(kd->db->close)(kd->db); 360 kd->db = 0; 361 362 return (-1); 363 } 364 365 int 366 kvm_nlist(kd, nl) 367 kvm_t *kd; 368 struct nlist *nl; 369 { 370 register struct nlist *p; 371 register int nvalid; 372 373 /* 374 * If we can't use the data base, revert to the 375 * slow library call. 376 */ 377 if (kd->db == 0) 378 return (__fdnlist(kd->nlfd, nl)); 379 380 /* 381 * We can use the kvm data base. Go through each nlist entry 382 * and look it up with a db query. 383 */ 384 nvalid = 0; 385 for (p = nl; p->n_name && p->n_name[0]; ++p) { 386 register int len; 387 DBT rec; 388 389 if ((len = strlen(p->n_name)) > 4096) { 390 /* sanity */ 391 _kvm_err(kd, kd->program, "symbol too large"); 392 return (-1); 393 } 394 rec.data = p->n_name; 395 rec.size = len; 396 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 397 continue; 398 if (rec.data == 0 || rec.size != sizeof(struct nlist)) 399 continue; 400 ++nvalid; 401 /* 402 * Avoid alignment issues. 403 */ 404 bcopy((char *)&((struct nlist *)rec.data)->n_type, 405 (char *)&p->n_type, 406 sizeof(p->n_type)); 407 bcopy((char *)&((struct nlist *)rec.data)->n_value, 408 (char *)&p->n_value, 409 sizeof(p->n_value)); 410 } 411 /* 412 * Return the number of entries that weren't found. 413 */ 414 return ((p - nl) - nvalid); 415 } 416 417 ssize_t 418 kvm_read(kd, kva, buf, len) 419 kvm_t *kd; 420 register u_long kva; 421 register void *buf; 422 register size_t len; 423 { 424 register int cc; 425 register void *cp; 426 427 if (ISALIVE(kd)) { 428 /* 429 * We're using /dev/kmem. Just read straight from the 430 * device and let the active kernel do the address translation. 431 */ 432 errno = 0; 433 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 434 _kvm_err(kd, 0, "invalid address (%x)", kva); 435 return (0); 436 } 437 cc = read(kd->vmfd, buf, len); 438 if (cc < 0) { 439 _kvm_syserr(kd, 0, "kvm_read"); 440 return (0); 441 } else if (cc < len) 442 _kvm_err(kd, kd->program, "short read"); 443 return (cc); 444 } else { 445 cp = buf; 446 while (len > 0) { 447 u_long pa; 448 449 cc = _kvm_kvatop(kd, kva, &pa); 450 if (cc == 0) 451 return (0); 452 if (cc > len) 453 cc = len; 454 errno = 0; 455 if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { 456 _kvm_syserr(kd, 0, _PATH_MEM); 457 break; 458 } 459 cc = read(kd->pmfd, cp, cc); 460 if (cc < 0) { 461 _kvm_syserr(kd, kd->program, "kvm_read"); 462 break; 463 } 464 (char *)cp += cc; 465 kva += cc; 466 len -= cc; 467 } 468 return ((char *)cp - (char *)buf); 469 } 470 /* NOTREACHED */ 471 } 472 473 ssize_t 474 kvm_write(kd, kva, buf, len) 475 kvm_t *kd; 476 register u_long kva; 477 register const void *buf; 478 register size_t len; 479 { 480 register int cc; 481 482 if (ISALIVE(kd)) { 483 /* 484 * Just like kvm_read, only we write. 485 */ 486 errno = 0; 487 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 488 _kvm_err(kd, 0, "invalid address (%x)", kva); 489 return (0); 490 } 491 cc = write(kd->vmfd, buf, len); 492 if (cc < 0) { 493 _kvm_syserr(kd, 0, "kvm_write"); 494 return (0); 495 } else if (cc < len) 496 _kvm_err(kd, kd->program, "short write"); 497 return (cc); 498 } else { 499 _kvm_err(kd, kd->program, 500 "kvm_write not implemented for dead kernels"); 501 return (0); 502 } 503 /* NOTREACHED */ 504 } 505