1 /* $NetBSD: kvm.c,v 1.81 2003/08/07 16:44:36 agc 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. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #if defined(LIBC_SCCS) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 40 #else 41 __RCSID("$NetBSD: kvm.c,v 1.81 2003/08/07 16:44:36 agc Exp $"); 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include <sys/param.h> 46 #include <sys/user.h> 47 #include <sys/lwp.h> 48 #include <sys/proc.h> 49 #include <sys/ioctl.h> 50 #include <sys/stat.h> 51 #include <sys/sysctl.h> 52 53 #include <sys/core.h> 54 #include <sys/exec_aout.h> 55 #include <sys/kcore.h> 56 #include <sys/ksyms.h> 57 58 #include <uvm/uvm_extern.h> 59 60 #include <machine/cpu.h> 61 62 #include <ctype.h> 63 #include <fcntl.h> 64 #include <limits.h> 65 #include <nlist.h> 66 #include <paths.h> 67 #include <stdarg.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_get_header __P((kvm_t *)); 77 static kvm_t *_kvm_open __P((kvm_t *, const char *, const char *, 78 const char *, int, char *)); 79 static int clear_gap __P((kvm_t *, FILE *, int)); 80 static int open_cloexec __P((const char *, int, 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 /* 92 * Report an error using printf style arguments. "program" is kd->program 93 * on hard errors, and 0 on soft errors, so that under sun error emulation, 94 * only hard errors are printed out (otherwise, programs like gdb will 95 * generate tons of error messages when trying to access bogus pointers). 96 */ 97 void 98 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 99 { 100 va_list ap; 101 102 va_start(ap, fmt); 103 if (program != NULL) { 104 (void)fprintf(stderr, "%s: ", program); 105 (void)vfprintf(stderr, fmt, ap); 106 (void)fputc('\n', stderr); 107 } else 108 (void)vsnprintf(kd->errbuf, 109 sizeof(kd->errbuf), fmt, ap); 110 111 va_end(ap); 112 } 113 114 void 115 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 116 { 117 va_list ap; 118 size_t n; 119 120 va_start(ap, fmt); 121 if (program != NULL) { 122 (void)fprintf(stderr, "%s: ", program); 123 (void)vfprintf(stderr, fmt, ap); 124 (void)fprintf(stderr, ": %s\n", strerror(errno)); 125 } else { 126 char *cp = kd->errbuf; 127 128 (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap); 129 n = strlen(cp); 130 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 131 strerror(errno)); 132 } 133 va_end(ap); 134 } 135 136 void * 137 _kvm_malloc(kd, n) 138 kvm_t *kd; 139 size_t n; 140 { 141 void *p; 142 143 if ((p = malloc(n)) == NULL) 144 _kvm_err(kd, kd->program, "%s", strerror(errno)); 145 return (p); 146 } 147 148 /* 149 * Open a file setting the close on exec bit. 150 */ 151 static int 152 open_cloexec(fname, flags, mode) 153 const char *fname; 154 int flags, mode; 155 { 156 int fd; 157 158 if ((fd = open(fname, flags, mode)) == -1) 159 return fd; 160 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) 161 goto error; 162 163 return fd; 164 error: 165 flags = errno; 166 (void)close(fd); 167 errno = flags; 168 return -1; 169 } 170 171 /* 172 * Wrapper around the lseek(2) system call; calls _kvm_syserr() for us 173 * in the event of emergency. 174 */ 175 static off_t 176 Lseek(kd, fd, offset, whence) 177 kvm_t *kd; 178 int fd; 179 off_t offset; 180 int whence; 181 { 182 off_t off; 183 184 errno = 0; 185 186 if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) { 187 _kvm_syserr(kd, kd->program, "Lseek"); 188 return ((off_t)-1); 189 } 190 return (off); 191 } 192 193 /* 194 * Wrapper around the pread(2) system call; calls _kvm_syserr() for us 195 * in the event of emergency. 196 */ 197 static ssize_t 198 Pread(kd, fd, buf, nbytes, offset) 199 kvm_t *kd; 200 int fd; 201 void *buf; 202 size_t nbytes; 203 off_t offset; 204 { 205 ssize_t rv; 206 207 errno = 0; 208 209 if ((rv = pread(fd, buf, nbytes, offset)) != nbytes && 210 errno != 0) 211 _kvm_syserr(kd, kd->program, "Pread"); 212 return (rv); 213 } 214 215 static kvm_t * 216 _kvm_open(kd, uf, mf, sf, flag, errout) 217 kvm_t *kd; 218 const char *uf; 219 const char *mf; 220 const char *sf; 221 int flag; 222 char *errout; 223 { 224 struct stat st; 225 int ufgiven; 226 227 kd->pmfd = -1; 228 kd->vmfd = -1; 229 kd->swfd = -1; 230 kd->nlfd = -1; 231 kd->alive = KVM_ALIVE_DEAD; 232 kd->procbase = 0; 233 kd->procbase2 = 0; 234 kd->lwpbase = 0; 235 kd->nbpg = getpagesize(); 236 kd->swapspc = 0; 237 kd->argspc = 0; 238 kd->arglen = 0; 239 kd->argbuf = 0; 240 kd->argv = 0; 241 kd->vmst = 0; 242 kd->vm_page_buckets = 0; 243 kd->kcore_hdr = 0; 244 kd->cpu_dsize = 0; 245 kd->cpu_data = 0; 246 kd->dump_off = 0; 247 248 if (flag & KVM_NO_FILES) { 249 kd->alive = KVM_ALIVE_SYSCTL; 250 return(kd); 251 } 252 253 /* 254 * Call the MD open hook. This sets: 255 * usrstack, min_uva, max_uva 256 */ 257 if (_kvm_mdopen(kd)) { 258 _kvm_err(kd, kd->program, "md init failed"); 259 goto failed; 260 } 261 262 ufgiven = (uf != NULL); 263 if (!ufgiven) { 264 #ifdef CPU_BOOTED_KERNEL 265 /* 130 is 128 + '/' + '\0' */ 266 static char booted_kernel[130]; 267 int mib[2], rc; 268 size_t len; 269 270 mib[0] = CTL_MACHDEP; 271 mib[1] = CPU_BOOTED_KERNEL; 272 booted_kernel[0] = '/'; 273 booted_kernel[1] = '\0'; 274 len = sizeof(booted_kernel) - 2; 275 rc = sysctl(&mib[0], 2, &booted_kernel[1], &len, NULL, 0); 276 booted_kernel[sizeof(booted_kernel) - 1] = '\0'; 277 uf = (booted_kernel[1] == '/') ? 278 &booted_kernel[1] : &booted_kernel[0]; 279 if (rc != -1) 280 rc = stat(uf, &st); 281 if (rc != -1 && !S_ISREG(st.st_mode)) 282 rc = -1; 283 if (rc == -1) 284 #endif /* CPU_BOOTED_KERNEL */ 285 uf = _PATH_UNIX; 286 } 287 else if (strlen(uf) >= MAXPATHLEN) { 288 _kvm_err(kd, kd->program, "exec file name too long"); 289 goto failed; 290 } 291 if (flag & ~O_RDWR) { 292 _kvm_err(kd, kd->program, "bad flags arg"); 293 goto failed; 294 } 295 if (mf == 0) 296 mf = _PATH_MEM; 297 if (sf == 0) 298 sf = _PATH_DRUM; 299 300 if ((kd->pmfd = open_cloexec(mf, flag, 0)) < 0) { 301 _kvm_syserr(kd, kd->program, "%s", mf); 302 goto failed; 303 } 304 if (fstat(kd->pmfd, &st) < 0) { 305 _kvm_syserr(kd, kd->program, "%s", mf); 306 goto failed; 307 } 308 if (S_ISCHR(st.st_mode)) { 309 /* 310 * If this is a character special device, then check that 311 * it's /dev/mem. If so, open kmem too. (Maybe we should 312 * make it work for either /dev/mem or /dev/kmem -- in either 313 * case you're working with a live kernel.) 314 */ 315 if (strcmp(mf, _PATH_MEM) != 0) { /* XXX */ 316 _kvm_err(kd, kd->program, 317 "%s: not physical memory device", mf); 318 goto failed; 319 } 320 if ((kd->vmfd = open_cloexec(_PATH_KMEM, flag, 0)) < 0) { 321 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 322 goto failed; 323 } 324 kd->alive = KVM_ALIVE_FILES; 325 if ((kd->swfd = open_cloexec(sf, flag, 0)) < 0) { 326 _kvm_syserr(kd, kd->program, "%s", sf); 327 goto failed; 328 } 329 /* 330 * Open the kernel namelist. If /dev/ksyms doesn't 331 * exist, open the current kernel. 332 */ 333 if (ufgiven == 0) 334 kd->nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0); 335 if (kd->nlfd < 0) { 336 if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) { 337 _kvm_syserr(kd, kd->program, "%s", uf); 338 goto failed; 339 } 340 } 341 } else { 342 /* 343 * This is a crash dump. 344 * Initialize the virtual address translation machinery, 345 * but first setup the namelist fd. 346 */ 347 if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) { 348 _kvm_syserr(kd, kd->program, "%s", uf); 349 goto failed; 350 } 351 352 /* 353 * If there is no valid core header, fail silently here. 354 * The address translations however will fail without 355 * header. Things can be made to run by calling 356 * kvm_dump_mkheader() before doing any translation. 357 */ 358 if (_kvm_get_header(kd) == 0) { 359 if (_kvm_initvtop(kd) < 0) 360 goto failed; 361 } 362 } 363 return (kd); 364 failed: 365 /* 366 * Copy out the error if doing sane error semantics. 367 */ 368 if (errout != 0) 369 (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 370 (void)kvm_close(kd); 371 return (0); 372 } 373 374 /* 375 * The kernel dump file (from savecore) contains: 376 * kcore_hdr_t kcore_hdr; 377 * kcore_seg_t cpu_hdr; 378 * (opaque) cpu_data; (size is cpu_hdr.c_size) 379 * kcore_seg_t mem_hdr; 380 * (memory) mem_data; (size is mem_hdr.c_size) 381 * 382 * Note: khdr is padded to khdr.c_hdrsize; 383 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize 384 */ 385 static int 386 _kvm_get_header(kd) 387 kvm_t *kd; 388 { 389 kcore_hdr_t kcore_hdr; 390 kcore_seg_t cpu_hdr; 391 kcore_seg_t mem_hdr; 392 size_t offset; 393 ssize_t sz; 394 395 /* 396 * Read the kcore_hdr_t 397 */ 398 sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0); 399 if (sz != sizeof(kcore_hdr)) 400 return (-1); 401 402 /* 403 * Currently, we only support dump-files made by the current 404 * architecture... 405 */ 406 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) || 407 (CORE_GETMID(kcore_hdr) != MID_MACHINE)) 408 return (-1); 409 410 /* 411 * Currently, we only support exactly 2 segments: cpu-segment 412 * and data-segment in exactly that order. 413 */ 414 if (kcore_hdr.c_nseg != 2) 415 return (-1); 416 417 /* 418 * Save away the kcore_hdr. All errors after this 419 * should do a to "goto fail" to deallocate things. 420 */ 421 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr)); 422 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr)); 423 offset = kcore_hdr.c_hdrsize; 424 425 /* 426 * Read the CPU segment header 427 */ 428 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset); 429 if (sz != sizeof(cpu_hdr)) 430 goto fail; 431 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) || 432 (CORE_GETFLAG(cpu_hdr) != CORE_CPU)) 433 goto fail; 434 offset += kcore_hdr.c_seghdrsize; 435 436 /* 437 * Read the CPU segment DATA. 438 */ 439 kd->cpu_dsize = cpu_hdr.c_size; 440 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size); 441 if (kd->cpu_data == NULL) 442 goto fail; 443 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset); 444 if (sz != cpu_hdr.c_size) 445 goto fail; 446 offset += cpu_hdr.c_size; 447 448 /* 449 * Read the next segment header: data segment 450 */ 451 sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset); 452 if (sz != sizeof(mem_hdr)) 453 goto fail; 454 offset += kcore_hdr.c_seghdrsize; 455 456 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) || 457 (CORE_GETFLAG(mem_hdr) != CORE_DATA)) 458 goto fail; 459 460 kd->dump_off = offset; 461 return (0); 462 463 fail: 464 if (kd->kcore_hdr != NULL) { 465 free(kd->kcore_hdr); 466 kd->kcore_hdr = NULL; 467 } 468 if (kd->cpu_data != NULL) { 469 free(kd->cpu_data); 470 kd->cpu_data = NULL; 471 kd->cpu_dsize = 0; 472 } 473 return (-1); 474 } 475 476 /* 477 * The format while on the dump device is: (new format) 478 * kcore_seg_t cpu_hdr; 479 * (opaque) cpu_data; (size is cpu_hdr.c_size) 480 * kcore_seg_t mem_hdr; 481 * (memory) mem_data; (size is mem_hdr.c_size) 482 */ 483 int 484 kvm_dump_mkheader(kd, dump_off) 485 kvm_t *kd; 486 off_t dump_off; 487 { 488 kcore_seg_t cpu_hdr; 489 size_t hdr_size; 490 ssize_t sz; 491 492 if (kd->kcore_hdr != NULL) { 493 _kvm_err(kd, kd->program, "already has a dump header"); 494 return (-1); 495 } 496 if (ISALIVE(kd)) { 497 _kvm_err(kd, kd->program, "don't use on live kernel"); 498 return (-1); 499 } 500 501 /* 502 * Validate new format crash dump 503 */ 504 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off); 505 if (sz != sizeof(cpu_hdr)) 506 return (-1); 507 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC) 508 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) { 509 _kvm_err(kd, 0, "invalid magic in cpu_hdr"); 510 return (0); 511 } 512 hdr_size = ALIGN(sizeof(cpu_hdr)); 513 514 /* 515 * Read the CPU segment. 516 */ 517 kd->cpu_dsize = cpu_hdr.c_size; 518 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize); 519 if (kd->cpu_data == NULL) 520 goto fail; 521 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, 522 dump_off + hdr_size); 523 if (sz != cpu_hdr.c_size) 524 goto fail; 525 hdr_size += kd->cpu_dsize; 526 527 /* 528 * Leave phys mem pointer at beginning of memory data 529 */ 530 kd->dump_off = dump_off + hdr_size; 531 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1) 532 goto fail; 533 534 /* 535 * Create a kcore_hdr. 536 */ 537 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t)); 538 if (kd->kcore_hdr == NULL) 539 goto fail; 540 541 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t)); 542 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t)); 543 kd->kcore_hdr->c_nseg = 2; 544 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0); 545 546 /* 547 * Now that we have a valid header, enable translations. 548 */ 549 if (_kvm_initvtop(kd) == 0) 550 /* Success */ 551 return (hdr_size); 552 553 fail: 554 if (kd->kcore_hdr != NULL) { 555 free(kd->kcore_hdr); 556 kd->kcore_hdr = NULL; 557 } 558 if (kd->cpu_data != NULL) { 559 free(kd->cpu_data); 560 kd->cpu_data = NULL; 561 kd->cpu_dsize = 0; 562 } 563 return (-1); 564 } 565 566 static int 567 clear_gap(kd, fp, size) 568 kvm_t *kd; 569 FILE *fp; 570 int size; 571 { 572 if (size <= 0) /* XXX - < 0 should never happen */ 573 return (0); 574 while (size-- > 0) { 575 if (fputc(0, fp) == EOF) { 576 _kvm_syserr(kd, kd->program, "clear_gap"); 577 return (-1); 578 } 579 } 580 return (0); 581 } 582 583 /* 584 * Write the dump header info to 'fp'. Note that we can't use fseek(3) here 585 * because 'fp' might be a file pointer obtained by zopen(). 586 */ 587 int 588 kvm_dump_wrtheader(kd, fp, dumpsize) 589 kvm_t *kd; 590 FILE *fp; 591 int dumpsize; 592 { 593 kcore_seg_t seghdr; 594 long offset; 595 int gap; 596 597 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) { 598 _kvm_err(kd, kd->program, "no valid dump header(s)"); 599 return (-1); 600 } 601 602 /* 603 * Write the generic header 604 */ 605 offset = 0; 606 if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) == 0) { 607 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 608 return (-1); 609 } 610 offset += kd->kcore_hdr->c_hdrsize; 611 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t); 612 if (clear_gap(kd, fp, gap) == -1) 613 return (-1); 614 615 /* 616 * Write the cpu header 617 */ 618 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU); 619 seghdr.c_size = ALIGN(kd->cpu_dsize); 620 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) { 621 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 622 return (-1); 623 } 624 offset += kd->kcore_hdr->c_seghdrsize; 625 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 626 if (clear_gap(kd, fp, gap) == -1) 627 return (-1); 628 629 if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) == 0) { 630 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 631 return (-1); 632 } 633 offset += seghdr.c_size; 634 gap = seghdr.c_size - kd->cpu_dsize; 635 if (clear_gap(kd, fp, gap) == -1) 636 return (-1); 637 638 /* 639 * Write the actual dump data segment header 640 */ 641 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA); 642 seghdr.c_size = dumpsize; 643 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) { 644 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 645 return (-1); 646 } 647 offset += kd->kcore_hdr->c_seghdrsize; 648 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 649 if (clear_gap(kd, fp, gap) == -1) 650 return (-1); 651 652 return (int)offset; 653 } 654 655 kvm_t * 656 kvm_openfiles(uf, mf, sf, flag, errout) 657 const char *uf; 658 const char *mf; 659 const char *sf; 660 int flag; 661 char *errout; 662 { 663 kvm_t *kd; 664 665 if ((kd = malloc(sizeof(*kd))) == NULL) { 666 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 667 return (0); 668 } 669 kd->program = 0; 670 return (_kvm_open(kd, uf, mf, sf, flag, errout)); 671 } 672 673 kvm_t * 674 kvm_open(uf, mf, sf, flag, program) 675 const char *uf; 676 const char *mf; 677 const char *sf; 678 int flag; 679 const char *program; 680 { 681 kvm_t *kd; 682 683 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) { 684 (void)fprintf(stderr, "%s: %s\n", program, strerror(errno)); 685 return (0); 686 } 687 kd->program = program; 688 return (_kvm_open(kd, uf, mf, sf, flag, NULL)); 689 } 690 691 int 692 kvm_close(kd) 693 kvm_t *kd; 694 { 695 int error = 0; 696 697 if (kd->pmfd >= 0) 698 error |= close(kd->pmfd); 699 if (kd->vmfd >= 0) 700 error |= close(kd->vmfd); 701 if (kd->nlfd >= 0) 702 error |= close(kd->nlfd); 703 if (kd->swfd >= 0) 704 error |= close(kd->swfd); 705 if (kd->vmst) 706 _kvm_freevtop(kd); 707 kd->cpu_dsize = 0; 708 if (kd->cpu_data != NULL) 709 free((void *)kd->cpu_data); 710 if (kd->kcore_hdr != NULL) 711 free((void *)kd->kcore_hdr); 712 if (kd->procbase != 0) 713 free((void *)kd->procbase); 714 if (kd->procbase2 != 0) 715 free((void *)kd->procbase2); 716 if (kd->lwpbase != 0) 717 free((void *)kd->lwpbase); 718 if (kd->swapspc != 0) 719 free((void *)kd->swapspc); 720 if (kd->argspc != 0) 721 free((void *)kd->argspc); 722 if (kd->argbuf != 0) 723 free((void *)kd->argbuf); 724 if (kd->argv != 0) 725 free((void *)kd->argv); 726 free((void *)kd); 727 728 return (0); 729 } 730 731 int 732 kvm_nlist(kd, nl) 733 kvm_t *kd; 734 struct nlist *nl; 735 { 736 int rv; 737 738 /* 739 * Call the nlist(3) routines to retrieve the given namelist. 740 */ 741 rv = __fdnlist(kd->nlfd, nl); 742 if (rv == -1) 743 _kvm_err(kd, 0, "bad namelist"); 744 return (rv); 745 } 746 747 int kvm_dump_inval(kd) 748 kvm_t *kd; 749 { 750 struct nlist nl[2]; 751 u_long pa, val; 752 753 if (ISALIVE(kd)) { 754 _kvm_err(kd, kd->program, "clearing dump on live kernel"); 755 return (-1); 756 } 757 nl[0].n_name = "_dumpmag"; 758 nl[1].n_name = NULL; 759 760 if (kvm_nlist(kd, nl) == -1) { 761 _kvm_err(kd, 0, "bad namelist"); 762 return (-1); 763 } 764 if (_kvm_kvatop(kd, (u_long)nl[0].n_value, &pa) == 0) 765 return (-1); 766 767 errno = 0; 768 val = 0; 769 if (pwrite(kd->pmfd, (void *)&val, sizeof(val), 770 _kvm_pa2off(kd, pa)) == -1) { 771 _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite"); 772 return (-1); 773 } 774 return (0); 775 } 776 777 ssize_t 778 kvm_read(kd, kva, buf, len) 779 kvm_t *kd; 780 u_long kva; 781 void *buf; 782 size_t len; 783 { 784 int cc; 785 void *cp; 786 787 if (ISKMEM(kd)) { 788 /* 789 * We're using /dev/kmem. Just read straight from the 790 * device and let the active kernel do the address translation. 791 */ 792 errno = 0; 793 cc = pread(kd->vmfd, buf, len, (off_t)kva); 794 if (cc < 0) { 795 _kvm_syserr(kd, 0, "kvm_read"); 796 return (-1); 797 } else if (cc < len) 798 _kvm_err(kd, kd->program, "short read"); 799 return (cc); 800 } else if (ISSYSCTL(kd)) { 801 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 802 "can't use kvm_read"); 803 return (-1); 804 } else { 805 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) { 806 _kvm_err(kd, kd->program, "no valid dump header"); 807 return (-1); 808 } 809 cp = buf; 810 while (len > 0) { 811 u_long pa; 812 off_t foff; 813 814 cc = _kvm_kvatop(kd, kva, &pa); 815 if (cc == 0) 816 return (-1); 817 if (cc > len) 818 cc = len; 819 foff = _kvm_pa2off(kd, pa); 820 errno = 0; 821 cc = pread(kd->pmfd, cp, (size_t)cc, foff); 822 if (cc < 0) { 823 _kvm_syserr(kd, kd->program, "kvm_read"); 824 break; 825 } 826 /* 827 * If kvm_kvatop returns a bogus value or our core 828 * file is truncated, we might wind up seeking beyond 829 * the end of the core file in which case the read will 830 * return 0 (EOF). 831 */ 832 if (cc == 0) 833 break; 834 cp = (char *)cp + cc; 835 kva += cc; 836 len -= cc; 837 } 838 return ((char *)cp - (char *)buf); 839 } 840 /* NOTREACHED */ 841 } 842 843 ssize_t 844 kvm_write(kd, kva, buf, len) 845 kvm_t *kd; 846 u_long kva; 847 const void *buf; 848 size_t len; 849 { 850 int cc; 851 852 if (ISKMEM(kd)) { 853 /* 854 * Just like kvm_read, only we write. 855 */ 856 errno = 0; 857 cc = pwrite(kd->vmfd, buf, len, (off_t)kva); 858 if (cc < 0) { 859 _kvm_syserr(kd, 0, "kvm_write"); 860 return (-1); 861 } else if (cc < len) 862 _kvm_err(kd, kd->program, "short write"); 863 return (cc); 864 } else if (ISSYSCTL(kd)) { 865 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 866 "can't use kvm_write"); 867 return (-1); 868 } else { 869 _kvm_err(kd, kd->program, 870 "kvm_write not implemented for dead kernels"); 871 return (-1); 872 } 873 /* NOTREACHED */ 874 } 875