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