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