1 /* $NetBSD: kvm.c,v 1.83 2004/02/13 11:36:08 wiz 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.83 2004/02/13 11:36:08 wiz 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 } else { 341 /* 342 * We're here because /dev/ksyms was opened 343 * successfully. However, we don't want to keep it 344 * open, so we close it now. Later, we will open 345 * it again, since it will be the only case where 346 * kd->nlfd is negative. 347 */ 348 close(kd->nlfd); 349 kd->nlfd = -1; 350 } 351 } else { 352 /* 353 * This is a crash dump. 354 * Initialize the virtual address translation machinery, 355 * but first setup the namelist fd. 356 */ 357 if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) { 358 _kvm_syserr(kd, kd->program, "%s", uf); 359 goto failed; 360 } 361 362 /* 363 * If there is no valid core header, fail silently here. 364 * The address translations however will fail without 365 * header. Things can be made to run by calling 366 * kvm_dump_mkheader() before doing any translation. 367 */ 368 if (_kvm_get_header(kd) == 0) { 369 if (_kvm_initvtop(kd) < 0) 370 goto failed; 371 } 372 } 373 return (kd); 374 failed: 375 /* 376 * Copy out the error if doing sane error semantics. 377 */ 378 if (errout != 0) 379 (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 380 (void)kvm_close(kd); 381 return (0); 382 } 383 384 /* 385 * The kernel dump file (from savecore) contains: 386 * kcore_hdr_t kcore_hdr; 387 * kcore_seg_t cpu_hdr; 388 * (opaque) cpu_data; (size is cpu_hdr.c_size) 389 * kcore_seg_t mem_hdr; 390 * (memory) mem_data; (size is mem_hdr.c_size) 391 * 392 * Note: khdr is padded to khdr.c_hdrsize; 393 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize 394 */ 395 static int 396 _kvm_get_header(kd) 397 kvm_t *kd; 398 { 399 kcore_hdr_t kcore_hdr; 400 kcore_seg_t cpu_hdr; 401 kcore_seg_t mem_hdr; 402 size_t offset; 403 ssize_t sz; 404 405 /* 406 * Read the kcore_hdr_t 407 */ 408 sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0); 409 if (sz != sizeof(kcore_hdr)) 410 return (-1); 411 412 /* 413 * Currently, we only support dump-files made by the current 414 * architecture... 415 */ 416 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) || 417 (CORE_GETMID(kcore_hdr) != MID_MACHINE)) 418 return (-1); 419 420 /* 421 * Currently, we only support exactly 2 segments: cpu-segment 422 * and data-segment in exactly that order. 423 */ 424 if (kcore_hdr.c_nseg != 2) 425 return (-1); 426 427 /* 428 * Save away the kcore_hdr. All errors after this 429 * should do a to "goto fail" to deallocate things. 430 */ 431 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr)); 432 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr)); 433 offset = kcore_hdr.c_hdrsize; 434 435 /* 436 * Read the CPU segment header 437 */ 438 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset); 439 if (sz != sizeof(cpu_hdr)) 440 goto fail; 441 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) || 442 (CORE_GETFLAG(cpu_hdr) != CORE_CPU)) 443 goto fail; 444 offset += kcore_hdr.c_seghdrsize; 445 446 /* 447 * Read the CPU segment DATA. 448 */ 449 kd->cpu_dsize = cpu_hdr.c_size; 450 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size); 451 if (kd->cpu_data == NULL) 452 goto fail; 453 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset); 454 if (sz != cpu_hdr.c_size) 455 goto fail; 456 offset += cpu_hdr.c_size; 457 458 /* 459 * Read the next segment header: data segment 460 */ 461 sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset); 462 if (sz != sizeof(mem_hdr)) 463 goto fail; 464 offset += kcore_hdr.c_seghdrsize; 465 466 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) || 467 (CORE_GETFLAG(mem_hdr) != CORE_DATA)) 468 goto fail; 469 470 kd->dump_off = offset; 471 return (0); 472 473 fail: 474 if (kd->kcore_hdr != NULL) { 475 free(kd->kcore_hdr); 476 kd->kcore_hdr = NULL; 477 } 478 if (kd->cpu_data != NULL) { 479 free(kd->cpu_data); 480 kd->cpu_data = NULL; 481 kd->cpu_dsize = 0; 482 } 483 return (-1); 484 } 485 486 /* 487 * The format while on the dump device is: (new format) 488 * kcore_seg_t cpu_hdr; 489 * (opaque) cpu_data; (size is cpu_hdr.c_size) 490 * kcore_seg_t mem_hdr; 491 * (memory) mem_data; (size is mem_hdr.c_size) 492 */ 493 int 494 kvm_dump_mkheader(kd, dump_off) 495 kvm_t *kd; 496 off_t dump_off; 497 { 498 kcore_seg_t cpu_hdr; 499 size_t hdr_size; 500 ssize_t sz; 501 502 if (kd->kcore_hdr != NULL) { 503 _kvm_err(kd, kd->program, "already has a dump header"); 504 return (-1); 505 } 506 if (ISALIVE(kd)) { 507 _kvm_err(kd, kd->program, "don't use on live kernel"); 508 return (-1); 509 } 510 511 /* 512 * Validate new format crash dump 513 */ 514 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off); 515 if (sz != sizeof(cpu_hdr)) 516 return (-1); 517 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC) 518 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) { 519 _kvm_err(kd, 0, "invalid magic in cpu_hdr"); 520 return (0); 521 } 522 hdr_size = ALIGN(sizeof(cpu_hdr)); 523 524 /* 525 * Read the CPU segment. 526 */ 527 kd->cpu_dsize = cpu_hdr.c_size; 528 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize); 529 if (kd->cpu_data == NULL) 530 goto fail; 531 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, 532 dump_off + hdr_size); 533 if (sz != cpu_hdr.c_size) 534 goto fail; 535 hdr_size += kd->cpu_dsize; 536 537 /* 538 * Leave phys mem pointer at beginning of memory data 539 */ 540 kd->dump_off = dump_off + hdr_size; 541 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1) 542 goto fail; 543 544 /* 545 * Create a kcore_hdr. 546 */ 547 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t)); 548 if (kd->kcore_hdr == NULL) 549 goto fail; 550 551 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t)); 552 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t)); 553 kd->kcore_hdr->c_nseg = 2; 554 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0); 555 556 /* 557 * Now that we have a valid header, enable translations. 558 */ 559 if (_kvm_initvtop(kd) == 0) 560 /* Success */ 561 return (hdr_size); 562 563 fail: 564 if (kd->kcore_hdr != NULL) { 565 free(kd->kcore_hdr); 566 kd->kcore_hdr = NULL; 567 } 568 if (kd->cpu_data != NULL) { 569 free(kd->cpu_data); 570 kd->cpu_data = NULL; 571 kd->cpu_dsize = 0; 572 } 573 return (-1); 574 } 575 576 static int 577 clear_gap(kd, fp, size) 578 kvm_t *kd; 579 FILE *fp; 580 int size; 581 { 582 if (size <= 0) /* XXX - < 0 should never happen */ 583 return (0); 584 while (size-- > 0) { 585 if (fputc(0, fp) == EOF) { 586 _kvm_syserr(kd, kd->program, "clear_gap"); 587 return (-1); 588 } 589 } 590 return (0); 591 } 592 593 /* 594 * Write the dump header info to 'fp'. Note that we can't use fseek(3) here 595 * because 'fp' might be a file pointer obtained by zopen(). 596 */ 597 int 598 kvm_dump_wrtheader(kd, fp, dumpsize) 599 kvm_t *kd; 600 FILE *fp; 601 int dumpsize; 602 { 603 kcore_seg_t seghdr; 604 long offset; 605 int gap; 606 607 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) { 608 _kvm_err(kd, kd->program, "no valid dump header(s)"); 609 return (-1); 610 } 611 612 /* 613 * Write the generic header 614 */ 615 offset = 0; 616 if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) == 0) { 617 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 618 return (-1); 619 } 620 offset += kd->kcore_hdr->c_hdrsize; 621 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t); 622 if (clear_gap(kd, fp, gap) == -1) 623 return (-1); 624 625 /* 626 * Write the CPU header 627 */ 628 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU); 629 seghdr.c_size = ALIGN(kd->cpu_dsize); 630 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) { 631 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 632 return (-1); 633 } 634 offset += kd->kcore_hdr->c_seghdrsize; 635 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 636 if (clear_gap(kd, fp, gap) == -1) 637 return (-1); 638 639 if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) == 0) { 640 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 641 return (-1); 642 } 643 offset += seghdr.c_size; 644 gap = seghdr.c_size - kd->cpu_dsize; 645 if (clear_gap(kd, fp, gap) == -1) 646 return (-1); 647 648 /* 649 * Write the actual dump data segment header 650 */ 651 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA); 652 seghdr.c_size = dumpsize; 653 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) { 654 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); 655 return (-1); 656 } 657 offset += kd->kcore_hdr->c_seghdrsize; 658 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 659 if (clear_gap(kd, fp, gap) == -1) 660 return (-1); 661 662 return (int)offset; 663 } 664 665 kvm_t * 666 kvm_openfiles(uf, mf, sf, flag, errout) 667 const char *uf; 668 const char *mf; 669 const char *sf; 670 int flag; 671 char *errout; 672 { 673 kvm_t *kd; 674 675 if ((kd = malloc(sizeof(*kd))) == NULL) { 676 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 677 return (0); 678 } 679 kd->program = 0; 680 return (_kvm_open(kd, uf, mf, sf, flag, errout)); 681 } 682 683 kvm_t * 684 kvm_open(uf, mf, sf, flag, program) 685 const char *uf; 686 const char *mf; 687 const char *sf; 688 int flag; 689 const char *program; 690 { 691 kvm_t *kd; 692 693 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) { 694 (void)fprintf(stderr, "%s: %s\n", program, strerror(errno)); 695 return (0); 696 } 697 kd->program = program; 698 return (_kvm_open(kd, uf, mf, sf, flag, NULL)); 699 } 700 701 int 702 kvm_close(kd) 703 kvm_t *kd; 704 { 705 int error = 0; 706 707 if (kd->pmfd >= 0) 708 error |= close(kd->pmfd); 709 if (kd->vmfd >= 0) 710 error |= close(kd->vmfd); 711 if (kd->nlfd >= 0) 712 error |= close(kd->nlfd); 713 if (kd->swfd >= 0) 714 error |= close(kd->swfd); 715 if (kd->vmst) 716 _kvm_freevtop(kd); 717 kd->cpu_dsize = 0; 718 if (kd->cpu_data != NULL) 719 free((void *)kd->cpu_data); 720 if (kd->kcore_hdr != NULL) 721 free((void *)kd->kcore_hdr); 722 if (kd->procbase != 0) 723 free((void *)kd->procbase); 724 if (kd->procbase2 != 0) 725 free((void *)kd->procbase2); 726 if (kd->lwpbase != 0) 727 free((void *)kd->lwpbase); 728 if (kd->swapspc != 0) 729 free((void *)kd->swapspc); 730 if (kd->argspc != 0) 731 free((void *)kd->argspc); 732 if (kd->argbuf != 0) 733 free((void *)kd->argbuf); 734 if (kd->argv != 0) 735 free((void *)kd->argv); 736 free((void *)kd); 737 738 return (0); 739 } 740 741 int 742 kvm_nlist(kd, nl) 743 kvm_t *kd; 744 struct nlist *nl; 745 { 746 int rv, nlfd; 747 748 /* 749 * kd->nlfd might be negative when we get here, and in that 750 * case that means that we're using /dev/ksyms. 751 * So open it again, just for the time we retrieve the list. 752 */ 753 if (kd->nlfd < 0) { 754 nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0); 755 if (nlfd < 0) { 756 _kvm_err(kd, 0, "failed to open %s", _PATH_KSYMS); 757 return (nlfd); 758 } 759 } else 760 nlfd = kd->nlfd; 761 762 /* 763 * Call the nlist(3) routines to retrieve the given namelist. 764 */ 765 rv = __fdnlist(nlfd, nl); 766 767 if (rv == -1) 768 _kvm_err(kd, 0, "bad namelist"); 769 770 if (kd->nlfd < 0) 771 close(nlfd); 772 773 return (rv); 774 } 775 776 int kvm_dump_inval(kd) 777 kvm_t *kd; 778 { 779 struct nlist nl[2]; 780 u_long pa, val; 781 782 if (ISALIVE(kd)) { 783 _kvm_err(kd, kd->program, "clearing dump on live kernel"); 784 return (-1); 785 } 786 nl[0].n_name = "_dumpmag"; 787 nl[1].n_name = NULL; 788 789 if (kvm_nlist(kd, nl) == -1) { 790 _kvm_err(kd, 0, "bad namelist"); 791 return (-1); 792 } 793 if (_kvm_kvatop(kd, (u_long)nl[0].n_value, &pa) == 0) 794 return (-1); 795 796 errno = 0; 797 val = 0; 798 if (pwrite(kd->pmfd, (void *)&val, sizeof(val), 799 _kvm_pa2off(kd, pa)) == -1) { 800 _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite"); 801 return (-1); 802 } 803 return (0); 804 } 805 806 ssize_t 807 kvm_read(kd, kva, buf, len) 808 kvm_t *kd; 809 u_long kva; 810 void *buf; 811 size_t len; 812 { 813 int cc; 814 void *cp; 815 816 if (ISKMEM(kd)) { 817 /* 818 * We're using /dev/kmem. Just read straight from the 819 * device and let the active kernel do the address translation. 820 */ 821 errno = 0; 822 cc = pread(kd->vmfd, buf, len, (off_t)kva); 823 if (cc < 0) { 824 _kvm_syserr(kd, 0, "kvm_read"); 825 return (-1); 826 } else if (cc < len) 827 _kvm_err(kd, kd->program, "short read"); 828 return (cc); 829 } else if (ISSYSCTL(kd)) { 830 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 831 "can't use kvm_read"); 832 return (-1); 833 } else { 834 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) { 835 _kvm_err(kd, kd->program, "no valid dump header"); 836 return (-1); 837 } 838 cp = buf; 839 while (len > 0) { 840 u_long pa; 841 off_t foff; 842 843 cc = _kvm_kvatop(kd, kva, &pa); 844 if (cc == 0) 845 return (-1); 846 if (cc > len) 847 cc = len; 848 foff = _kvm_pa2off(kd, pa); 849 errno = 0; 850 cc = pread(kd->pmfd, cp, (size_t)cc, foff); 851 if (cc < 0) { 852 _kvm_syserr(kd, kd->program, "kvm_read"); 853 break; 854 } 855 /* 856 * If kvm_kvatop returns a bogus value or our core 857 * file is truncated, we might wind up seeking beyond 858 * the end of the core file in which case the read will 859 * return 0 (EOF). 860 */ 861 if (cc == 0) 862 break; 863 cp = (char *)cp + cc; 864 kva += cc; 865 len -= cc; 866 } 867 return ((char *)cp - (char *)buf); 868 } 869 /* NOTREACHED */ 870 } 871 872 ssize_t 873 kvm_write(kd, kva, buf, len) 874 kvm_t *kd; 875 u_long kva; 876 const void *buf; 877 size_t len; 878 { 879 int cc; 880 881 if (ISKMEM(kd)) { 882 /* 883 * Just like kvm_read, only we write. 884 */ 885 errno = 0; 886 cc = pwrite(kd->vmfd, buf, len, (off_t)kva); 887 if (cc < 0) { 888 _kvm_syserr(kd, 0, "kvm_write"); 889 return (-1); 890 } else if (cc < len) 891 _kvm_err(kd, kd->program, "short write"); 892 return (cc); 893 } else if (ISSYSCTL(kd)) { 894 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 895 "can't use kvm_write"); 896 return (-1); 897 } else { 898 _kvm_err(kd, kd->program, 899 "kvm_write not implemented for dead kernels"); 900 return (-1); 901 } 902 /* NOTREACHED */ 903 } 904