1 /* $OpenBSD: kvm.c,v 1.26 2001/11/21 20:16:16 drahn Exp $ */ 2 /* $NetBSD: kvm.c,v 1.43 1996/05/05 04:31:59 gwr Exp $ */ 3 4 /*- 5 * Copyright (c) 1989, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software developed by the Computer Systems 9 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 10 * BG 91-66 and contributed to Berkeley. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #if defined(LIBC_SCCS) && !defined(lint) 42 #if 0 43 static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 44 #else 45 static char *rcsid = "$OpenBSD: kvm.c,v 1.26 2001/11/21 20:16:16 drahn Exp $"; 46 #endif 47 #endif /* LIBC_SCCS and not lint */ 48 49 #include <sys/param.h> 50 #include <sys/user.h> 51 #include <sys/proc.h> 52 #include <sys/ioctl.h> 53 #include <sys/stat.h> 54 #include <sys/sysctl.h> 55 56 #include <sys/core.h> 57 #include <sys/exec_aout.h> 58 #include <sys/kcore.h> 59 60 #include <ctype.h> 61 #include <db.h> 62 #include <fcntl.h> 63 #include <libgen.h> 64 #include <limits.h> 65 #include <nlist.h> 66 #include <paths.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <unistd.h> 71 #include <kvm.h> 72 73 #include "kvm_private.h" 74 75 static int kvm_dbopen __P((kvm_t *, const char *)); 76 static int _kvm_get_header __P((kvm_t *)); 77 static kvm_t *_kvm_open __P((kvm_t *, const char *, const char *, 78 const char *, int, char *)); 79 static int clear_gap __P((kvm_t *, FILE *, int)); 80 81 char * 82 kvm_geterr(kd) 83 kvm_t *kd; 84 { 85 return (kd->errbuf); 86 } 87 88 #ifdef __STDC__ 89 #include <stdarg.h> 90 #else 91 #include <varargs.h> 92 #endif 93 94 /* 95 * Wrapper around pread. 96 */ 97 ssize_t 98 #ifdef __STDC__ 99 _kvm_pread(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset) 100 #else 101 _kvm_pread(kd, fd, buf, nbytes, offset) 102 kvm_t *kd; 103 int fd; 104 void *buf; 105 size_t nbytes; 106 off_t offset; 107 #endif 108 { 109 ssize_t rval; 110 111 errno = 0; 112 rval = pread(fd, buf, nbytes, offset); 113 if (rval == -1 || errno != 0) { 114 _kvm_syserr(kd, kd->program, "pread"); 115 } 116 return(rval); 117 } 118 119 /* 120 * Wrapper around pwrite. 121 */ 122 ssize_t 123 #ifdef __STDC__ 124 _kvm_pwrite(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset) 125 #else 126 _kvm_pwrite(kd, fd, buf, nbytes, offset) 127 kvm_t *kd; 128 int fd; 129 void *buf; 130 size_t nbytes; 131 off_t offset; 132 #endif 133 { 134 ssize_t rval; 135 136 errno = 0; 137 rval = pwrite(fd, buf, nbytes, offset); 138 if (rval == -1 || errno != 0) { 139 _kvm_syserr(kd, kd->program, "pwrite"); 140 } 141 return(rval); 142 } 143 144 /* 145 * Report an error using printf style arguments. "program" is kd->program 146 * on hard errors, and 0 on soft errors, so that under sun error emulation, 147 * only hard errors are printed out (otherwise, programs like gdb will 148 * generate tons of error messages when trying to access bogus pointers). 149 */ 150 void 151 #ifdef __STDC__ 152 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 153 #else 154 _kvm_err(kd, program, fmt, va_alist) 155 kvm_t *kd; 156 char *program, *fmt; 157 va_dcl 158 #endif 159 { 160 va_list ap; 161 162 #ifdef __STDC__ 163 va_start(ap, fmt); 164 #else 165 va_start(ap); 166 #endif 167 if (program != NULL) { 168 (void)fprintf(stderr, "%s: ", program); 169 (void)vfprintf(stderr, fmt, ap); 170 (void)fputc('\n', stderr); 171 } else 172 (void)vsnprintf(kd->errbuf, 173 sizeof(kd->errbuf), (char *)fmt, ap); 174 175 va_end(ap); 176 } 177 178 void 179 #ifdef __STDC__ 180 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 181 #else 182 _kvm_syserr(kd, program, fmt, va_alist) 183 kvm_t *kd; 184 char *program, *fmt; 185 va_dcl 186 #endif 187 { 188 va_list ap; 189 register int n; 190 191 #ifdef __STDC__ 192 va_start(ap, fmt); 193 #else 194 va_start(ap); 195 #endif 196 if (program != NULL) { 197 (void)fprintf(stderr, "%s: ", program); 198 (void)vfprintf(stderr, fmt, ap); 199 (void)fprintf(stderr, ": %s\n", strerror(errno)); 200 } else { 201 register char *cp = kd->errbuf; 202 203 (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 204 n = strlen(cp); 205 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 206 strerror(errno)); 207 } 208 va_end(ap); 209 } 210 211 void * 212 _kvm_malloc(kd, n) 213 register kvm_t *kd; 214 register size_t n; 215 { 216 void *p; 217 218 if ((p = malloc(n)) == NULL) 219 _kvm_err(kd, kd->program, "%s", strerror(errno)); 220 return (p); 221 } 222 223 static kvm_t * 224 _kvm_open(kd, uf, mf, sf, flag, errout) 225 register kvm_t *kd; 226 const char *uf; 227 const char *mf; 228 const char *sf; 229 int flag; 230 char *errout; 231 { 232 struct stat st; 233 234 kd->db = 0; 235 kd->pmfd = -1; 236 kd->vmfd = -1; 237 kd->swfd = -1; 238 kd->nlfd = -1; 239 kd->procbase = 0; 240 kd->nbpg = getpagesize(); 241 kd->swapspc = 0; 242 kd->argspc = 0; 243 kd->argbuf = 0; 244 kd->argv = 0; 245 kd->vmst = 0; 246 kd->vm_page_buckets = 0; 247 kd->kcore_hdr = 0; 248 kd->cpu_dsize = 0; 249 kd->cpu_data = 0; 250 kd->dump_off = 0; 251 252 if (uf && strlen(uf) >= MAXPATHLEN) { 253 _kvm_err(kd, kd->program, "exec file name too long"); 254 goto failed; 255 } 256 if (flag & ~O_ACCMODE) { 257 _kvm_err(kd, kd->program, "bad flags arg"); 258 goto failed; 259 } 260 if (mf == 0) 261 mf = _PATH_MEM; 262 if (sf == 0) 263 sf = _PATH_DRUM; 264 265 if ((kd->pmfd = open(mf, flag, 0)) < 0) { 266 _kvm_syserr(kd, kd->program, "%s", mf); 267 goto failed; 268 } 269 if (fstat(kd->pmfd, &st) < 0) { 270 _kvm_syserr(kd, kd->program, "%s", mf); 271 goto failed; 272 } 273 if (S_ISCHR(st.st_mode)) { 274 /* 275 * If this is a character special device, then check that 276 * it's /dev/mem. If so, open kmem too. (Maybe we should 277 * make it work for either /dev/mem or /dev/kmem -- in either 278 * case you're working with a live kernel.) 279 */ 280 if (strcmp(mf, _PATH_MEM) != 0) { /* XXX */ 281 _kvm_err(kd, kd->program, 282 "%s: not physical memory device", mf); 283 goto failed; 284 } 285 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 286 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 287 goto failed; 288 } 289 if ((kd->swfd = open(sf, flag, 0)) < 0) { 290 _kvm_syserr(kd, kd->program, "%s", sf); 291 goto failed; 292 } 293 /* 294 * Open kvm nlist database. We only try to use 295 * the pre-built database if the namelist file name 296 * pointer is NULL. If the database cannot or should 297 * not be opened, open the namelist argument so we 298 * revert to slow nlist() calls. 299 * If no file is specified, try opening _PATH_KSYMS and 300 * fall back to _PATH_UNIX. 301 */ 302 if (kvm_dbopen(kd, uf ? uf : _PATH_UNIX) == -1 && 303 ((uf && (kd->nlfd = open(uf, O_RDONLY)) == -1) || (!uf && 304 (kd->nlfd = open((uf = _PATH_KSYMS), O_RDONLY)) == -1 && 305 (kd->nlfd = open((uf = _PATH_UNIX), O_RDONLY)) == -1))) { 306 _kvm_syserr(kd, kd->program, "%s", uf); 307 goto failed; 308 } 309 } else { 310 /* 311 * This is a crash dump. 312 * Initialize the virtual address translation machinery, 313 * but first setup the namelist fd. 314 * If no file is specified, try opening _PATH_KSYMS and 315 * fall back to _PATH_UNIX. 316 */ 317 if ((uf && (kd->nlfd = open(uf, O_RDONLY)) == -1) || (!uf && 318 (kd->nlfd = open((uf = _PATH_KSYMS), O_RDONLY)) == -1 && 319 (kd->nlfd = open((uf = _PATH_UNIX), O_RDONLY)) == -1)) { 320 _kvm_syserr(kd, kd->program, "%s", uf); 321 goto failed; 322 } 323 324 /* 325 * If there is no valid core header, fail silently here. 326 * The address translations however will fail without 327 * header. Things can be made to run by calling 328 * kvm_dump_mkheader() before doing any translation. 329 */ 330 if (_kvm_get_header(kd) == 0) { 331 if (_kvm_initvtop(kd) < 0) 332 goto failed; 333 } 334 } 335 return (kd); 336 failed: 337 /* 338 * Copy out the error if doing sane error semantics. 339 */ 340 if (errout != 0) 341 (void)strncpy(errout, kd->errbuf, _POSIX2_LINE_MAX - 1); 342 (void)kvm_close(kd); 343 return (0); 344 } 345 346 /* 347 * The kernel dump file (from savecore) contains: 348 * kcore_hdr_t kcore_hdr; 349 * kcore_seg_t cpu_hdr; 350 * (opaque) cpu_data; (size is cpu_hdr.c_size) 351 * kcore_seg_t mem_hdr; 352 * (memory) mem_data; (size is mem_hdr.c_size) 353 * 354 * Note: khdr is padded to khdr.c_hdrsize; 355 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize 356 */ 357 static int 358 _kvm_get_header(kd) 359 kvm_t *kd; 360 { 361 kcore_hdr_t kcore_hdr; 362 kcore_seg_t cpu_hdr; 363 kcore_seg_t mem_hdr; 364 size_t offset; 365 ssize_t sz; 366 367 /* 368 * Read the kcore_hdr_t 369 */ 370 sz = _kvm_pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0); 371 if (sz != sizeof(kcore_hdr)) { 372 return (-1); 373 } 374 375 /* 376 * Currently, we only support dump-files made by the current 377 * architecture... 378 */ 379 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) || 380 (CORE_GETMID(kcore_hdr) != MID_MACHINE)) 381 return (-1); 382 383 /* 384 * Currently, we only support exactly 2 segments: cpu-segment 385 * and data-segment in exactly that order. 386 */ 387 if (kcore_hdr.c_nseg != 2) 388 return (-1); 389 390 /* 391 * Save away the kcore_hdr. All errors after this 392 * should do a to "goto fail" to deallocate things. 393 */ 394 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr)); 395 if (kd->kcore_hdr == NULL) 396 goto fail; 397 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr)); 398 offset = kcore_hdr.c_hdrsize; 399 400 /* 401 * Read the CPU segment header 402 */ 403 sz = _kvm_pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset); 404 if (sz != sizeof(cpu_hdr)) { 405 goto fail; 406 } 407 408 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) || 409 (CORE_GETFLAG(cpu_hdr) != CORE_CPU)) 410 goto fail; 411 offset += kcore_hdr.c_seghdrsize; 412 413 /* 414 * Read the CPU segment DATA. 415 */ 416 kd->cpu_dsize = cpu_hdr.c_size; 417 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size); 418 if (kd->cpu_data == NULL) 419 goto fail; 420 421 sz = _kvm_pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset); 422 if (sz != cpu_hdr.c_size) { 423 goto fail; 424 } 425 426 offset += cpu_hdr.c_size; 427 428 /* 429 * Read the next segment header: data segment 430 */ 431 sz = _kvm_pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset); 432 if (sz != sizeof(mem_hdr)) { 433 goto fail; 434 } 435 436 offset += kcore_hdr.c_seghdrsize; 437 438 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) || 439 (CORE_GETFLAG(mem_hdr) != CORE_DATA)) 440 goto fail; 441 442 kd->dump_off = offset; 443 return (0); 444 445 fail: 446 if (kd->kcore_hdr != NULL) { 447 free(kd->kcore_hdr); 448 kd->kcore_hdr = NULL; 449 } 450 if (kd->cpu_data != NULL) { 451 free(kd->cpu_data); 452 kd->cpu_data = NULL; 453 kd->cpu_dsize = 0; 454 } 455 456 return (-1); 457 } 458 459 /* 460 * The format while on the dump device is: (new format) 461 * kcore_seg_t cpu_hdr; 462 * (opaque) cpu_data; (size is cpu_hdr.c_size) 463 * kcore_seg_t mem_hdr; 464 * (memory) mem_data; (size is mem_hdr.c_size) 465 */ 466 int 467 kvm_dump_mkheader(kd, dump_off) 468 kvm_t *kd; 469 off_t dump_off; 470 { 471 kcore_seg_t cpu_hdr; 472 int hdr_size, sz; 473 474 if (kd->kcore_hdr != NULL) { 475 _kvm_err(kd, kd->program, "already has a dump header"); 476 return (-1); 477 } 478 if (ISALIVE(kd)) { 479 _kvm_err(kd, kd->program, "don't use on live kernel"); 480 return (-1); 481 } 482 483 /* 484 * Validate new format crash dump 485 */ 486 sz = _kvm_pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)dump_off); 487 if (sz != sizeof(cpu_hdr)) { 488 return (-1); 489 } 490 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC) 491 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) { 492 _kvm_err(kd, 0, "invalid magic in cpu_hdr"); 493 return (-1); 494 } 495 hdr_size = ALIGN(sizeof(cpu_hdr)); 496 497 /* 498 * Read the CPU segment. 499 */ 500 kd->cpu_dsize = cpu_hdr.c_size; 501 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize); 502 if (kd->cpu_data == NULL) 503 goto fail; 504 505 sz = _kvm_pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)dump_off+hdr_size); 506 if (sz != cpu_hdr.c_size) { 507 _kvm_err(kd, 0, "invalid size in cpu_hdr"); 508 goto fail; 509 } 510 hdr_size += kd->cpu_dsize; 511 512 /* 513 * Leave phys mem pointer at beginning of memory data 514 */ 515 kd->dump_off = dump_off + hdr_size; 516 errno = 0; 517 if (lseek(kd->pmfd, kd->dump_off, SEEK_SET) != kd->dump_off && errno != 0) { 518 _kvm_err(kd, 0, "invalid dump offset - lseek"); 519 goto fail; 520 } 521 522 /* 523 * Create a kcore_hdr. 524 */ 525 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t)); 526 if (kd->kcore_hdr == NULL) 527 goto fail; 528 529 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t)); 530 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t)); 531 kd->kcore_hdr->c_nseg = 2; 532 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0); 533 534 /* 535 * Now that we have a valid header, enable translations. 536 */ 537 if (_kvm_initvtop(kd) == 0) 538 /* Success */ 539 return (hdr_size); 540 541 fail: 542 if (kd->kcore_hdr != NULL) { 543 free(kd->kcore_hdr); 544 kd->kcore_hdr = NULL; 545 } 546 if (kd->cpu_data != NULL) { 547 free(kd->cpu_data); 548 kd->cpu_data = NULL; 549 kd->cpu_dsize = 0; 550 } 551 return (-1); 552 } 553 554 static int 555 clear_gap(kd, fp, size) 556 kvm_t *kd; 557 FILE *fp; 558 int size; 559 { 560 if (size <= 0) /* XXX - < 0 should never happen */ 561 return (0); 562 while (size-- > 0) { 563 if (fputc(0, fp) == EOF) { 564 _kvm_syserr(kd, kd->program, "clear_gap"); 565 return (-1); 566 } 567 } 568 return (0); 569 } 570 571 /* 572 * Write the dump header info to 'fp'. Note that we can't use fseek(3) here 573 * because 'fp' might be a file pointer obtained by zopen(). 574 */ 575 int 576 kvm_dump_wrtheader(kd, fp, dumpsize) 577 kvm_t *kd; 578 FILE *fp; 579 int dumpsize; 580 { 581 kcore_seg_t seghdr; 582 long offset; 583 int gap; 584 585 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) { 586 _kvm_err(kd, kd->program, "no valid dump header(s)"); 587 return (-1); 588 } 589 590 /* 591 * Write the generic header 592 */ 593 offset = 0; 594 if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) <= 0) { 595 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 596 return (-1); 597 } 598 offset += kd->kcore_hdr->c_hdrsize; 599 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t); 600 if (clear_gap(kd, fp, gap) == -1) 601 return (-1); 602 603 /* 604 * Write the cpu header 605 */ 606 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU); 607 seghdr.c_size = ALIGN(kd->cpu_dsize); 608 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) { 609 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 610 return (-1); 611 } 612 offset += kd->kcore_hdr->c_seghdrsize; 613 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 614 if (clear_gap(kd, fp, gap) == -1) 615 return (-1); 616 617 if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) <= 0) { 618 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 619 return (-1); 620 } 621 offset += seghdr.c_size; 622 gap = seghdr.c_size - kd->cpu_dsize; 623 if (clear_gap(kd, fp, gap) == -1) 624 return (-1); 625 626 /* 627 * Write the actual dump data segment header 628 */ 629 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA); 630 seghdr.c_size = dumpsize; 631 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) { 632 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 633 return (-1); 634 } 635 offset += kd->kcore_hdr->c_seghdrsize; 636 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 637 if (clear_gap(kd, fp, gap) == -1) 638 return (-1); 639 640 return (offset); 641 } 642 643 kvm_t * 644 kvm_openfiles(uf, mf, sf, flag, errout) 645 const char *uf; 646 const char *mf; 647 const char *sf; 648 int flag; 649 char *errout; 650 { 651 register kvm_t *kd; 652 653 if ((kd = malloc(sizeof(*kd))) == NULL) { 654 (void)strncpy(errout, strerror(errno), _POSIX2_LINE_MAX - 1); 655 return (0); 656 } 657 kd->program = 0; 658 return (_kvm_open(kd, uf, mf, sf, flag, errout)); 659 } 660 661 kvm_t * 662 kvm_open(uf, mf, sf, flag, program) 663 const char *uf; 664 const char *mf; 665 const char *sf; 666 int flag; 667 const char *program; 668 { 669 register kvm_t *kd; 670 671 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) { 672 (void)fprintf(stderr, "%s: %s\n", program, strerror(errno)); 673 return (0); 674 } 675 kd->program = program; 676 return (_kvm_open(kd, uf, mf, sf, flag, NULL)); 677 } 678 679 int 680 kvm_close(kd) 681 kvm_t *kd; 682 { 683 register int error = 0; 684 685 if (kd->pmfd >= 0) 686 error |= close(kd->pmfd); 687 if (kd->vmfd >= 0) 688 error |= close(kd->vmfd); 689 if (kd->nlfd >= 0) 690 error |= close(kd->nlfd); 691 if (kd->swfd >= 0) 692 error |= close(kd->swfd); 693 if (kd->db != 0) 694 error |= (kd->db->close)(kd->db); 695 if (kd->vmst) 696 _kvm_freevtop(kd); 697 kd->cpu_dsize = 0; 698 if (kd->cpu_data != NULL) 699 free((void *)kd->cpu_data); 700 if (kd->kcore_hdr != NULL) 701 free((void *)kd->kcore_hdr); 702 if (kd->procbase != 0) 703 free((void *)kd->procbase); 704 if (kd->swapspc != 0) 705 free((void *)kd->swapspc); 706 if (kd->argspc != 0) 707 free((void *)kd->argspc); 708 if (kd->argbuf != 0) 709 free((void *)kd->argbuf); 710 if (kd->argv != 0) 711 free((void *)kd->argv); 712 free((void *)kd); 713 714 return (error); 715 } 716 717 /* 718 * Set up state necessary to do queries on the kernel namelist 719 * data base. If the data base is out-of-data/incompatible with 720 * given executable, set up things so we revert to standard nlist call. 721 * Only called for live kernels. Return 0 on success, -1 on failure. 722 */ 723 static int 724 kvm_dbopen(kd, uf) 725 kvm_t *kd; 726 const char *uf; 727 { 728 DBT rec; 729 int dbversionlen; 730 struct nlist nitem; 731 char dbversion[_POSIX2_LINE_MAX]; 732 char kversion[_POSIX2_LINE_MAX]; 733 char dbname[MAXPATHLEN]; 734 735 uf = basename((char *)uf); 736 737 (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf); 738 kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL); 739 if (kd->db == NULL) { 740 switch (errno) { 741 case ENOENT: 742 /* No kvm_bsd.db, fall back to /bsd silently */ 743 break; 744 case EFTYPE: 745 _kvm_err(kd, kd->program, 746 "file %s is incorrectly formatted", dbname); 747 break; 748 case EINVAL: 749 _kvm_err(kd, kd->program, 750 "invalid argument to dbopen()"); 751 break; 752 default: 753 _kvm_err(kd, kd->program, "unknown dbopen() error"); 754 break; 755 } 756 return (-1); 757 } 758 759 /* 760 * read version out of database 761 */ 762 rec.data = VRS_KEY; 763 rec.size = sizeof(VRS_KEY) - 1; 764 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 765 goto close; 766 if (rec.data == 0 || rec.size > sizeof(dbversion)) 767 goto close; 768 769 bcopy(rec.data, dbversion, rec.size); 770 dbversionlen = rec.size; 771 /* 772 * Read version string from kernel memory. 773 * Since we are dealing with a live kernel, we can call kvm_read() 774 * at this point. 775 */ 776 rec.data = VRS_SYM; 777 rec.size = sizeof(VRS_SYM) - 1; 778 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 779 goto close; 780 if (rec.data == 0 || rec.size != sizeof(struct nlist)) 781 goto close; 782 bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem)); 783 if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) != 784 dbversionlen) 785 goto close; 786 /* 787 * If they match, we win - otherwise clear out kd->db so 788 * we revert to slow nlist(). 789 */ 790 if (bcmp(dbversion, kversion, dbversionlen) == 0) 791 return (0); 792 close: 793 (void)(kd->db->close)(kd->db); 794 kd->db = 0; 795 796 return (-1); 797 } 798 799 int 800 kvm_nlist(kd, nl) 801 kvm_t *kd; 802 struct nlist *nl; 803 { 804 register struct nlist *p; 805 register int nvalid, rv; 806 807 /* 808 * If we can't use the data base, revert to the 809 * slow library call. 810 */ 811 if (kd->db == 0) { 812 rv = __fdnlist(kd->nlfd, nl); 813 if (rv == -1) 814 _kvm_err(kd, 0, "bad namelist"); 815 return (rv); 816 } 817 818 /* 819 * We can use the kvm data base. Go through each nlist entry 820 * and look it up with a db query. 821 */ 822 nvalid = 0; 823 for (p = nl; p->n_name && p->n_name[0]; ++p) { 824 register int len; 825 DBT rec; 826 827 if ((len = strlen(p->n_name)) > 4096) { 828 /* sanity */ 829 _kvm_err(kd, kd->program, "symbol too large"); 830 return (-1); 831 } 832 rec.data = p->n_name; 833 rec.size = len; 834 835 /* 836 * Make sure that n_value = 0 when the symbol isn't found 837 */ 838 p->n_value = 0; 839 840 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) 841 continue; 842 if (rec.data == 0 || rec.size != sizeof(struct nlist)) 843 continue; 844 ++nvalid; 845 /* 846 * Avoid alignment issues. 847 */ 848 bcopy((char *)&((struct nlist *)rec.data)->n_type, 849 (char *)&p->n_type, 850 sizeof(p->n_type)); 851 bcopy((char *)&((struct nlist *)rec.data)->n_value, 852 (char *)&p->n_value, 853 sizeof(p->n_value)); 854 } 855 /* 856 * Return the number of entries that weren't found. 857 */ 858 return ((p - nl) - nvalid); 859 } 860 861 int kvm_dump_inval(kd) 862 kvm_t *kd; 863 { 864 struct nlist nlist[2]; 865 u_long pa, x; 866 867 if (ISALIVE(kd)) { 868 _kvm_err(kd, kd->program, "clearing dump on live kernel"); 869 return (-1); 870 } 871 nlist[0].n_name = "_dumpmag"; 872 nlist[1].n_name = NULL; 873 874 if (kvm_nlist(kd, nlist) == -1) { 875 _kvm_err(kd, 0, "bad namelist"); 876 return (-1); 877 } 878 if (_kvm_kvatop(kd, (u_long)nlist[0].n_value, &pa) == 0) 879 return (-1); 880 881 x = 0; 882 if (_kvm_pwrite(kd, kd->pmfd, &x, sizeof(x), (off_t)_kvm_pa2off(kd, pa)) != sizeof(x)) { 883 _kvm_err(kd, 0, "cannot invalidate dump"); 884 return (-1); 885 } 886 return (0); 887 } 888 889 ssize_t 890 kvm_read(kd, kva, buf, len) 891 kvm_t *kd; 892 register u_long kva; 893 register void *buf; 894 register size_t len; 895 { 896 register int cc; 897 register void *cp; 898 899 if (ISALIVE(kd)) { 900 /* 901 * We're using /dev/kmem. Just read straight from the 902 * device and let the active kernel do the address translation. 903 */ 904 cc = _kvm_pread(kd, kd->vmfd, buf, len, (off_t)kva); 905 if (cc < 0) { 906 _kvm_err(kd, 0, "invalid address (%lx)", kva); 907 return (-1); 908 } else if (cc < len) 909 _kvm_err(kd, kd->program, "short read"); 910 return (cc); 911 } else { 912 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) { 913 _kvm_err(kd, kd->program, "no valid dump header"); 914 return (-1); 915 } 916 cp = buf; 917 while (len > 0) { 918 u_long pa; 919 920 /* In case of error, _kvm_kvatop sets the err string */ 921 cc = _kvm_kvatop(kd, kva, &pa); 922 if (cc == 0) 923 return (-1); 924 if (cc > len) 925 cc = len; 926 cc = _kvm_pread(kd, kd->pmfd, cp, cc, (off_t)_kvm_pa2off(kd, pa)); 927 if (cc < 0) { 928 _kvm_syserr(kd, 0, _PATH_MEM); 929 break; 930 } 931 /* 932 * If kvm_kvatop returns a bogus value or our core 933 * file is truncated, we might wind up seeking beyond 934 * the end of the core file in which case the read will 935 * return 0 (EOF). 936 */ 937 if (cc == 0) 938 break; 939 cp = (char *)cp + cc; 940 kva += cc; 941 len -= cc; 942 } 943 return ((char *)cp - (char *)buf); 944 } 945 /* NOTREACHED */ 946 } 947 948 ssize_t 949 kvm_write(kd, kva, buf, len) 950 kvm_t *kd; 951 register u_long kva; 952 register const void *buf; 953 register size_t len; 954 { 955 register int cc; 956 957 if (ISALIVE(kd)) { 958 /* 959 * Just like kvm_read, only we write. 960 */ 961 cc = _kvm_pwrite(kd, kd->vmfd, (void*)buf, (size_t)len, (off_t)kva); 962 if (cc < 0) { 963 _kvm_err(kd, 0, "invalid address (%lx)", kva); 964 return (-1); 965 } else if (cc < len) 966 _kvm_err(kd, kd->program, "short write"); 967 return (cc); 968 } else { 969 _kvm_err(kd, kd->program, 970 "kvm_write not implemented for dead kernels"); 971 return (-1); 972 } 973 /* NOTREACHED */ 974 } 975