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