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