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