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