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