1 /*- 2 * Copyright (c) 1993 Christopher G. Demetriou 3 * Copyright (c) 1989 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #if defined(LIBC_SCCS) && !defined(lint) 36 /*static char sccsid[] = "from: @(#)kvm.c 5.18 (Berkeley) 5/7/91";*/ 37 static char rcsid[] = "$Id: kvm.c,v 1.20 1993/10/13 15:49:55 mycroft Exp $"; 38 #endif /* LIBC_SCCS and not lint */ 39 40 #include <sys/param.h> 41 #include <sys/user.h> 42 #include <sys/proc.h> 43 #include <sys/ioctl.h> 44 #include <sys/kinfo.h> 45 #include <sys/tty.h> 46 #include <sys/exec.h> 47 #include <machine/vmparam.h> 48 #include <fcntl.h> 49 #include <nlist.h> 50 #include <kvm.h> 51 #include <ndbm.h> 52 #include <limits.h> 53 #include <paths.h> 54 #include <stdio.h> 55 #include <string.h> 56 57 #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */ 58 #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */ 59 #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/ 60 #include <vm/vm_page.h> 61 #include <vm/swap_pager.h> 62 #include <sys/kinfo_proc.h> 63 #if defined(hp300) || defined(amiga) 64 #include <machine/pte.h> 65 #define btos(x) (((unsigned)(x)) >> SEGSHIFT) /* XXX */ 66 #endif 67 68 /* 69 * files 70 */ 71 static const char *unixf, *memf, *kmemf, *swapf; 72 static int unixx, mem, kmem, swap; 73 static DBM *db; 74 /* 75 * flags 76 */ 77 static int deadkernel; 78 static int kvminit = 0; 79 static int kvmfilesopen = 0; 80 /* 81 * state 82 */ 83 static struct kinfo_proc *kvmprocbase, *kvmprocptr; 84 static int kvmnprocs; 85 /* 86 * u. buffer 87 */ 88 static union { 89 struct user user; 90 char upages[UPAGES][NBPG]; 91 } user; 92 93 struct swapblk { 94 long offset; /* offset in swap device */ 95 long size; /* remaining size of block in swap device */ 96 }; 97 98 /* 99 * random other stuff 100 */ 101 static int dmmin, dmmax; 102 static int pcbpf; 103 static int nswap; 104 static long vm_page_hash_mask; 105 static long vm_page_buckets; 106 static long page_shift; 107 static char *tmp; 108 #if defined(hp300) || defined(amiga) 109 static int lowram; 110 static struct ste *Sysseg; 111 #endif 112 #if defined(i386) 113 static struct pde *PTD; 114 #endif 115 116 #define atop(x) (((unsigned)(x)) >> page_shift) 117 #define vm_page_hash(object, offset) \ 118 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask) 119 120 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 121 #define MAXSYMSIZE 256 122 123 static struct nlist nl[] = { 124 { "_Usrptmap" }, 125 #define X_USRPTMAP 0 126 { "_usrpt" }, 127 #define X_USRPT 1 128 { "_nswap" }, 129 #define X_NSWAP 2 130 { "_dmmin" }, 131 #define X_DMMIN 3 132 { "_dmmax" }, 133 #define X_DMMAX 4 134 { "_vm_page_buckets" }, 135 #define X_VM_PAGE_BUCKETS 5 136 { "_vm_page_hash_mask" }, 137 #define X_VM_PAGE_HASH_MASK 6 138 { "_page_shift" }, 139 #define X_PAGE_SHIFT 7 140 /* 141 * everything here and down, only if a dead kernel 142 */ 143 { "_Sysmap" }, 144 #define X_SYSMAP 8 145 #define X_DEADKERNEL X_SYSMAP 146 { "_Syssize" }, 147 #define X_SYSSIZE 9 148 { "_allproc" }, 149 #define X_ALLPROC 10 150 { "_zombproc" }, 151 #define X_ZOMBPROC 11 152 { "_nproc" }, 153 #define X_NPROC 12 154 #define X_LAST 12 155 #if defined(hp300) || defined(amiga) 156 { "_Sysseg" }, 157 #define X_SYSSEG (X_LAST+1) 158 { "_lowram" }, 159 #define X_LOWRAM (X_LAST+2) 160 #endif 161 #if defined(i386) 162 { "_IdlePTD" }, 163 #define X_IdlePTD (X_LAST+1) 164 #endif 165 { "" }, 166 }; 167 168 static off_t Vtophys(); 169 static void klseek(), seterr(), setsyserr(), vstodb(); 170 static int getkvars(), kvm_doprocs(), kvm_init(); 171 static int vatosw(); 172 static int pager_get(); 173 static int findpage(); 174 175 /* 176 * returns 0 if files were opened now, 177 * 1 if files were already opened, 178 * -1 if files could not be opened. 179 */ 180 kvm_openfiles(uf, mf, sf) 181 const char *uf, *mf, *sf; 182 { 183 if (kvmfilesopen) 184 return (1); 185 unixx = mem = kmem = swap = -1; 186 unixf = (uf == NULL) ? _PATH_UNIX : uf; 187 memf = (mf == NULL) ? _PATH_MEM : mf; 188 189 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) { 190 setsyserr("can't open %s", unixf); 191 goto failed; 192 } 193 if ((mem = open(memf, O_RDONLY, 0)) == -1) { 194 setsyserr("can't open %s", memf); 195 goto failed; 196 } 197 if (sf != NULL) 198 swapf = sf; 199 if (mf != NULL) { 200 deadkernel++; 201 kmemf = mf; 202 kmem = mem; 203 swap = -1; 204 } else { 205 kmemf = _PATH_KMEM; 206 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) { 207 setsyserr("can't open %s", kmemf); 208 goto failed; 209 } 210 swapf = (sf == NULL) ? _PATH_DRUM : sf; 211 /* 212 * live kernel - avoid looking up nlist entries 213 * past X_DEADKERNEL. 214 */ 215 nl[X_DEADKERNEL].n_name = ""; 216 } 217 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) { 218 seterr("can't open %s", swapf); 219 goto failed; 220 } 221 kvmfilesopen++; 222 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/ 223 return (-1); 224 return (0); 225 failed: 226 kvm_close(); 227 return (-1); 228 } 229 230 static 231 kvm_init(uf, mf, sf) 232 char *uf, *mf, *sf; 233 { 234 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 235 return (-1); 236 if (getkvars() == -1) 237 return (-1); 238 kvminit = 1; 239 240 return (0); 241 } 242 243 kvm_close() 244 { 245 if (unixx != -1) { 246 close(unixx); 247 unixx = -1; 248 } 249 if (kmem != -1) { 250 if (kmem != mem) 251 close(kmem); 252 /* otherwise kmem is a copy of mem, and will be closed below */ 253 kmem = -1; 254 } 255 if (mem != -1) { 256 close(mem); 257 mem = -1; 258 } 259 if (swap != -1) { 260 close(swap); 261 swap = -1; 262 } 263 if (db != NULL) { 264 dbm_close(db); 265 db = NULL; 266 } 267 kvminit = 0; 268 kvmfilesopen = 0; 269 deadkernel = 0; 270 } 271 272 kvm_nlist(nl) 273 struct nlist *nl; 274 { 275 datum key, data; 276 char dbname[MAXPATHLEN]; 277 char dbversion[_POSIX2_LINE_MAX]; 278 char kversion[_POSIX2_LINE_MAX]; 279 int dbversionlen; 280 char symbuf[MAXSYMSIZE]; 281 struct nlist nbuf, *n; 282 int num, did; 283 284 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 285 return (-1); 286 if (deadkernel) 287 goto hard2; 288 /* 289 * initialize key datum 290 */ 291 key.dptr = symbuf; 292 293 if (db != NULL) 294 goto win; /* off to the races */ 295 /* 296 * open database 297 */ 298 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf)); 299 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL) 300 goto hard2; 301 /* 302 * read version out of database 303 */ 304 bcopy("VERSION", symbuf, sizeof ("VERSION")-1); 305 key.dsize = (sizeof ("VERSION") - 1); 306 data = dbm_fetch(db, key); 307 if (data.dptr == NULL) 308 goto hard1; 309 bcopy(data.dptr, dbversion, data.dsize); 310 dbversionlen = data.dsize; 311 /* 312 * read version string from kernel memory 313 */ 314 bcopy("_version", symbuf, sizeof ("_version")-1); 315 key.dsize = (sizeof ("_version")-1); 316 data = dbm_fetch(db, key); 317 if (data.dptr == NULL) 318 goto hard1; 319 if (data.dsize != sizeof (struct nlist)) 320 goto hard1; 321 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 322 lseek(kmem, nbuf.n_value, 0); 323 if (read(kmem, kversion, dbversionlen) != dbversionlen) 324 goto hard1; 325 /* 326 * if they match, we win - otherwise do it the hard way 327 */ 328 if (bcmp(dbversion, kversion, dbversionlen) != 0) 329 goto hard1; 330 /* 331 * getem from the database. 332 */ 333 win: 334 num = did = 0; 335 for (n = nl; n->n_name && n->n_name[0]; n++, num++) { 336 int len; 337 /* 338 * clear out fields from users buffer 339 */ 340 n->n_type = 0; 341 n->n_other = 0; 342 n->n_desc = 0; 343 n->n_value = 0; 344 /* 345 * query db 346 */ 347 if ((len = strlen(n->n_name)) > MAXSYMSIZE) { 348 seterr("symbol too large"); 349 return (-1); 350 } 351 (void)strcpy(symbuf, n->n_name); 352 key.dsize = len; 353 data = dbm_fetch(db, key); 354 if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) 355 continue; 356 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 357 n->n_value = nbuf.n_value; 358 n->n_type = nbuf.n_type; 359 n->n_desc = nbuf.n_desc; 360 n->n_other = nbuf.n_other; 361 did++; 362 } 363 return (num - did); 364 hard1: 365 dbm_close(db); 366 db = NULL; 367 hard2: 368 num = nlist(unixf, nl); 369 if (num == -1) 370 seterr("nlist (hard way) failed"); 371 return (num); 372 } 373 374 kvm_getprocs(what, arg) 375 int what, arg; 376 { 377 static int ocopysize = -1; 378 379 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 380 return (NULL); 381 if (!deadkernel) { 382 int ret, copysize; 383 384 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) { 385 setsyserr("can't get estimate for kerninfo"); 386 return (-1); 387 } 388 copysize = ret; 389 if (copysize > ocopysize || !kvmprocbase) { 390 if (ocopysize == -1 || !kvmprocbase) 391 kvmprocbase = 392 (struct kinfo_proc *)malloc(copysize); 393 else 394 kvmprocbase = 395 (struct kinfo_proc *)realloc(kvmprocbase, 396 copysize); 397 if (!kvmprocbase) { 398 seterr("out of memory"); 399 return (-1); 400 } 401 } 402 ocopysize = copysize; 403 if ((ret = getkerninfo(what, kvmprocbase, ©size, 404 arg)) == -1) { 405 setsyserr("can't get proc list"); 406 return (-1); 407 } 408 if (copysize % sizeof (struct kinfo_proc)) { 409 seterr("proc size mismatch (got %d total, kinfo_proc: %d)", 410 copysize, sizeof (struct kinfo_proc)); 411 return (-1); 412 } 413 kvmnprocs = copysize / sizeof (struct kinfo_proc); 414 } else { 415 int nproc; 416 417 if (kvm_read((void *) nl[X_NPROC].n_value, &nproc, 418 sizeof (int)) == -1) { 419 seterr("can't read nproc"); 420 return (-1); 421 } 422 if ((kvmprocbase = (struct kinfo_proc *) 423 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) { 424 seterr("out of memory (addr: %x nproc = %d)", 425 nl[X_NPROC].n_value, nproc); 426 return (-1); 427 } 428 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase); 429 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc)); 430 } 431 kvmprocptr = kvmprocbase; 432 433 return (kvmnprocs); 434 } 435 436 /* 437 * XXX - should NOT give up so easily - especially since the kernel 438 * may be corrupt (it died). Should gather as much information as possible. 439 * Follows proc ptrs instead of reading table since table may go 440 * away soon. 441 */ 442 static 443 kvm_doprocs(what, arg, buff) 444 int what, arg; 445 char *buff; 446 { 447 struct proc *p, proc; 448 register char *bp = buff; 449 int i = 0; 450 int doingzomb = 0; 451 struct eproc eproc; 452 struct pgrp pgrp; 453 struct session sess; 454 struct tty tty; 455 456 /* allproc */ 457 if (kvm_read((void *) nl[X_ALLPROC].n_value, &p, 458 sizeof (struct proc *)) == -1) { 459 seterr("can't read allproc"); 460 return (-1); 461 } 462 463 again: 464 for (; p; p = proc.p_nxt) { 465 if (kvm_read(p, &proc, sizeof (struct proc)) == -1) { 466 seterr("can't read proc at %x", p); 467 return (-1); 468 } 469 if (kvm_read(proc.p_cred, &eproc.e_pcred, 470 sizeof (struct pcred)) != -1) 471 (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred, 472 sizeof (struct ucred)); 473 474 switch(ki_op(what)) { 475 476 case KINFO_PROC_PID: 477 if (proc.p_pid != (pid_t)arg) 478 continue; 479 break; 480 481 482 case KINFO_PROC_UID: 483 if (eproc.e_ucred.cr_uid != (uid_t)arg) 484 continue; 485 break; 486 487 case KINFO_PROC_RUID: 488 if (eproc.e_pcred.p_ruid != (uid_t)arg) 489 continue; 490 break; 491 } 492 /* 493 * gather eproc 494 */ 495 eproc.e_paddr = p; 496 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) == -1) { 497 seterr("can't read pgrp at %x", proc.p_pgrp); 498 return (-1); 499 } 500 eproc.e_sess = pgrp.pg_session; 501 eproc.e_pgid = pgrp.pg_id; 502 eproc.e_jobc = pgrp.pg_jobc; 503 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session)) 504 == -1) { 505 seterr("can't read session at %x", pgrp.pg_session); 506 return (-1); 507 } 508 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) { 509 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty)) 510 == -1) { 511 seterr("can't read tty at %x", sess.s_ttyp); 512 return (-1); 513 } 514 eproc.e_tdev = tty.t_dev; 515 eproc.e_tsess = tty.t_session; 516 if (tty.t_pgrp != NULL) { 517 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct 518 pgrp)) == -1) { 519 seterr("can't read tpgrp at &x", 520 tty.t_pgrp); 521 return (-1); 522 } 523 eproc.e_tpgid = pgrp.pg_id; 524 } else 525 eproc.e_tpgid = -1; 526 } else 527 eproc.e_tdev = NODEV; 528 if (proc.p_wmesg) 529 (void) kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN); 530 (void) kvm_read(proc.p_vmspace, &eproc.e_vm, 531 sizeof (struct vmspace)); 532 eproc.e_xsize = eproc.e_xrssize = 533 eproc.e_xccount = eproc.e_xswrss = 0; 534 535 switch(ki_op(what)) { 536 537 case KINFO_PROC_PGRP: 538 if (eproc.e_pgid != (pid_t)arg) 539 continue; 540 break; 541 542 case KINFO_PROC_TTY: 543 if ((proc.p_flag&SCTTY) == 0 || 544 eproc.e_tdev != (dev_t)arg) 545 continue; 546 break; 547 } 548 549 i++; 550 bcopy(&proc, bp, sizeof (struct proc)); 551 bp += sizeof (struct proc); 552 bcopy(&eproc, bp, sizeof (struct eproc)); 553 bp+= sizeof (struct eproc); 554 } 555 if (!doingzomb) { 556 /* zombproc */ 557 if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p, 558 sizeof (struct proc *)) == -1) { 559 seterr("can't read zombproc"); 560 return (-1); 561 } 562 doingzomb = 1; 563 goto again; 564 } 565 566 return (i); 567 } 568 569 struct proc * 570 kvm_nextproc() 571 { 572 573 if (!kvmprocbase && kvm_getprocs(0, 0) == -1) 574 return (NULL); 575 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) { 576 seterr("end of proc list"); 577 return (NULL); 578 } 579 return((struct proc *)(kvmprocptr++)); 580 } 581 582 struct eproc * 583 kvm_geteproc(p) 584 const struct proc *p; 585 { 586 return ((struct eproc *)(((char *)p) + sizeof (struct proc))); 587 } 588 589 kvm_setproc() 590 { 591 kvmprocptr = kvmprocbase; 592 } 593 594 kvm_freeprocs() 595 { 596 597 if (kvmprocbase) { 598 free(kvmprocbase); 599 kvmprocbase = NULL; 600 } 601 } 602 603 struct user * 604 kvm_getu(p) 605 const struct proc *p; 606 { 607 register struct kinfo_proc *kp = (struct kinfo_proc *)p; 608 register int i; 609 register char *up; 610 u_int vaddr; 611 struct swapblk swb; 612 613 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 614 return (NULL); 615 if (p->p_stat == SZOMB) { 616 seterr("zombie process"); 617 return (NULL); 618 } 619 620 if ((p->p_flag & SLOAD) == 0) { 621 vm_offset_t maddr; 622 623 if (swap < 0) { 624 seterr("no swap"); 625 return (NULL); 626 } 627 /* 628 * Costly operation, better set enable_swap to zero 629 * in vm/vm_glue.c, since paging of user pages isn't 630 * done yet anyway. 631 */ 632 if (vatosw(&kp->kp_eproc.e_vm.vm_map, USRSTACK + i * NBPG, 633 &maddr, &swb) == 0) 634 return NULL; 635 636 if (maddr == 0 && swb.size < UPAGES * NBPG) 637 return NULL; 638 639 for (i = 0; i < UPAGES; i++) { 640 if (maddr) { 641 (void) lseek(mem, maddr + i * NBPG, 0); 642 if (read(mem, 643 (char *)user.upages[i], NBPG) != NBPG) { 644 seterr( 645 "can't read u for pid %d from %s", 646 p->p_pid, swapf); 647 return NULL; 648 } 649 } else { 650 (void) lseek(swap, swb.offset + i * NBPG, 0); 651 if (read(swap, 652 (char *)user.upages[i], NBPG) != NBPG) { 653 seterr( 654 "can't read u for pid %d from %s", 655 p->p_pid, swapf); 656 return NULL; 657 } 658 } 659 } 660 return(&user.user); 661 } 662 /* 663 * Read u-area one page at a time for the benefit of post-mortems 664 */ 665 up = (char *) p->p_addr; 666 for (i = 0; i < UPAGES; i++) { 667 klseek(kmem, (long)up, 0); 668 if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) { 669 seterr("cant read page %x of u of pid %d from %s", 670 up, p->p_pid, kmemf); 671 return(NULL); 672 } 673 up += CLBYTES; 674 } 675 pcbpf = (int) btop(p->p_addr); /* what should this be really? */ 676 677 kp->kp_eproc.e_vm.vm_rssize = 678 kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */ 679 return(&user.user); 680 } 681 682 int 683 kvm_procread(p, addr, buf, len) 684 const struct proc *p; 685 const unsigned addr; 686 unsigned len; 687 char *buf; 688 { 689 register struct kinfo_proc *kp = (struct kinfo_proc *) p; 690 struct swapblk swb; 691 vm_offset_t swaddr = 0, memaddr = 0; 692 unsigned real_len; 693 694 real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET)); 695 696 if (vatosw(&kp->kp_eproc.e_vm.vm_map, addr & ~CLOFSET, &memaddr, 697 &swb) == 0) 698 return 0; 699 700 if (memaddr) { 701 memaddr += addr & CLOFSET; 702 if (lseek(mem, memaddr, 0) == -1) 703 seterr("kvm_procread: lseek mem"); 704 len = read(mem, buf, real_len); 705 if (len == -1) { 706 seterr("kvm_procread: read mem"); 707 return 0; 708 } 709 } else { 710 char bouncebuf[CLBYTES]; 711 swaddr = swb.offset + (addr & CLOFSET); 712 swb.size -= addr & CLOFSET; 713 if (lseek(swap, swaddr & ~CLOFSET, 0) == -1) { 714 seterr("kvm_procread: lseek swap"); 715 return 0; 716 } 717 len = read(swap, bouncebuf, CLBYTES); 718 if (len == -1 || len <= (swaddr & CLOFSET)) { 719 seterr("kvm_procread: read swap"); 720 return 0; 721 } 722 len = MIN(len - (swaddr & CLOFSET), real_len); 723 memcpy(buf, &bouncebuf[swaddr & CLOFSET], len); 724 } 725 726 return len; 727 } 728 729 int 730 kvm_procreadstr(p, addr, buf, len) 731 const struct proc *p; 732 const unsigned addr; 733 char *buf; 734 unsigned len; 735 { 736 int done, little; 737 char copy[200], *pb; 738 char a; 739 740 done = 0; 741 copy[0] = '\0'; 742 while (len) { 743 little = kvm_procread(p, addr+done, copy, MIN(len, sizeof copy)); 744 if (little<1) 745 break; 746 pb = copy; 747 while (little--) { 748 len--; 749 if( (*buf++ = *pb++) == '\0' ) 750 return done; 751 done++; 752 } 753 } 754 return done; 755 } 756 757 char * 758 kvm_getargs(p, up) 759 const struct proc *p; 760 const struct user *up; 761 { 762 static char cmdbuf[ARG_MAX + sizeof(p->p_comm) + 5]; 763 register char *cp, *acp; 764 int left, rv; 765 struct ps_strings arginfo; 766 767 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 768 goto retucomm; 769 770 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) != 771 sizeof(arginfo)) 772 goto bad; 773 774 cmdbuf[0] = '\0'; 775 cp = cmdbuf; 776 acp = arginfo.ps_argvstr; 777 left = ARG_MAX + 1; 778 while (arginfo.ps_nargvstr--) { 779 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) { 780 acp += rv + 1; 781 left -= rv + 1; 782 cp += rv; 783 *cp++ = ' '; 784 *cp = '\0'; 785 } else 786 goto bad; 787 } 788 cp-- ; *cp = '\0'; 789 790 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') { 791 (void) strcat(cmdbuf, " ("); 792 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); 793 (void) strcat(cmdbuf, ")"); 794 } 795 return (cmdbuf); 796 797 bad: 798 seterr("error locating command name for pid %d", p->p_pid); 799 retucomm: 800 (void) strcpy(cmdbuf, "("); 801 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm)); 802 (void) strcat(cmdbuf, ")"); 803 return (cmdbuf); 804 } 805 806 char * 807 kvm_getenv(p, up) 808 const struct proc *p; 809 const struct user *up; 810 { 811 static char envbuf[ARG_MAX + 1]; 812 register char *cp, *acp; 813 int left, rv; 814 struct ps_strings arginfo; 815 816 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 817 goto retemptyenv; 818 819 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) != 820 sizeof(arginfo)) 821 goto bad; 822 823 cp = envbuf; 824 acp = arginfo.ps_envstr; 825 left = ARG_MAX + 1; 826 while (arginfo.ps_nenvstr--) { 827 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) { 828 acp += rv + 1; 829 left -= rv + 1; 830 cp += rv; 831 *cp++ = ' '; 832 *cp = '\0'; 833 } else 834 goto bad; 835 } 836 cp-- ; *cp = '\0'; 837 return (envbuf); 838 839 bad: 840 seterr("error locating environment for pid %d", p->p_pid); 841 retemptyenv: 842 envbuf[0] = '\0'; 843 return (envbuf); 844 } 845 846 static 847 getkvars() 848 { 849 if (kvm_nlist(nl) == -1) 850 return (-1); 851 if (deadkernel) { 852 /* We must do the sys map first because klseek uses it */ 853 long addr; 854 855 #if defined(hp300) || defined(amiga) 856 addr = (long) nl[X_LOWRAM].n_value; 857 (void) lseek(kmem, addr, 0); 858 if (read(kmem, (char *) &lowram, sizeof (lowram)) 859 != sizeof (lowram)) { 860 seterr("can't read lowram"); 861 return (-1); 862 } 863 lowram = btop(lowram); 864 Sysseg = (struct ste *) malloc(NBPG); 865 if (Sysseg == NULL) { 866 seterr("out of space for Sysseg"); 867 return (-1); 868 } 869 addr = (long) nl[X_SYSSEG].n_value; 870 (void) lseek(kmem, addr, 0); 871 read(kmem, (char *)&addr, sizeof(addr)); 872 (void) lseek(kmem, (long)addr, 0); 873 if (read(kmem, (char *) Sysseg, NBPG) != NBPG) { 874 seterr("can't read Sysseg"); 875 return (-1); 876 } 877 #endif 878 #if defined(i386) 879 PTD = (struct pde *) malloc(NBPG); 880 if (PTD == NULL) { 881 seterr("out of space for PTD"); 882 return (-1); 883 } 884 addr = (long) nl[X_IdlePTD].n_value; 885 (void) lseek(kmem, addr, 0); 886 read(kmem, (char *)&addr, sizeof(addr)); 887 (void) lseek(kmem, (long)addr, 0); 888 if (read(kmem, (char *) PTD, NBPG) != NBPG) { 889 seterr("can't read PTD"); 890 return (-1); 891 } 892 #endif 893 } 894 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) == -1) { 895 seterr("can't read nswap"); 896 return (-1); 897 } 898 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) == -1) { 899 seterr("can't read dmmin"); 900 return (-1); 901 } 902 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) == -1) { 903 seterr("can't read dmmax"); 904 return (-1); 905 } 906 if (kvm_read((void *) nl[X_VM_PAGE_HASH_MASK].n_value, 907 &vm_page_hash_mask, sizeof (long)) == -1) { 908 seterr("can't read vm_page_hash_mask"); 909 return (-1); 910 } 911 if (kvm_read((void *) nl[X_VM_PAGE_BUCKETS].n_value, 912 &vm_page_buckets, sizeof (long)) == -1) { 913 seterr("can't read vm_page_buckets"); 914 return (-1); 915 } 916 if (kvm_read((void *) nl[X_PAGE_SHIFT].n_value, 917 &page_shift, sizeof (long)) == -1) { 918 seterr("can't read page_shift"); 919 return (-1); 920 } 921 922 return (0); 923 } 924 925 kvm_read(loc, buf, len) 926 void *loc; 927 void *buf; 928 { 929 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 930 return (-1); 931 klseek(kmem, (off_t) loc, 0); 932 if (read(kmem, buf, len) != len) { 933 seterr("error reading kmem at %x", loc); 934 return (-1); 935 } 936 return (len); 937 } 938 939 static void 940 klseek(fd, loc, off) 941 int fd; 942 off_t loc; 943 int off; 944 { 945 946 if (deadkernel) { 947 if ((loc = Vtophys(loc)) == -1) 948 return; 949 } 950 (void) lseek(fd, (off_t)loc, off); 951 } 952 953 static off_t 954 Vtophys(loc) 955 u_long loc; 956 { 957 off_t newloc = (off_t) -1; 958 #if defined(hp300) || defined(amiga) 959 int p, ste, pte; 960 961 ste = *(int *)&Sysseg[btos(loc)]; 962 if ((ste & SG_V) == 0) { 963 seterr("vtophys: segment not valid"); 964 return((off_t) -1); 965 } 966 p = btop(loc & SG_PMASK); 967 newloc = (ste & SG_FRAME) + (p * sizeof(struct pte)); 968 (void) lseek(mem, newloc, 0); 969 if (read(mem, (char *)&pte, sizeof pte) != sizeof pte) { 970 seterr("vtophys: cannot locate pte"); 971 return((off_t) -1); 972 } 973 newloc = pte & PG_FRAME; 974 if (pte == PG_NV || newloc < (off_t)ptob(lowram)) { 975 seterr("vtophys: page not valid"); 976 return((off_t) -1); 977 } 978 newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET); 979 #endif 980 #ifdef i386 981 struct pde pde; 982 struct pte pte; 983 int p; 984 985 pde = PTD[loc >> PD_SHIFT]; 986 if (pde.pd_v == 0) { 987 seterr("vtophys: page directory entry not valid"); 988 return((off_t) -1); 989 } 990 p = btop(loc & PT_MASK); 991 newloc = pde.pd_pfnum + (p * sizeof(struct pte)); 992 (void) lseek(kmem, (long)newloc, 0); 993 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) { 994 seterr("vtophys: cannot obtain desired pte"); 995 return((off_t) -1); 996 } 997 newloc = pte.pg_pfnum; 998 if (pte.pg_v == 0) { 999 seterr("vtophys: page table entry not valid"); 1000 return((off_t) -1); 1001 } 1002 newloc += (loc & PGOFSET); 1003 #endif 1004 return((off_t) newloc); 1005 } 1006 1007 /* 1008 * locate address of unwired or swapped page 1009 */ 1010 1011 static int 1012 vatosw(mp, vaddr, maddr, swb) 1013 vm_map_t mp; 1014 vm_offset_t vaddr; 1015 vm_offset_t *maddr; 1016 struct swapblk *swb; 1017 { 1018 struct vm_object vm_object; 1019 struct vm_map_entry vm_entry; 1020 long saddr, addr, off; 1021 int i; 1022 1023 saddr = addr = (long)mp->header.next; 1024 #ifdef DEBUG 1025 fprintf(stderr, "vatosw: head=%x\n", &mp->header); 1026 #endif 1027 for (i = 0; ; i++) { 1028 /* Weed through map entries until vaddr in range */ 1029 if (kvm_read((void *) addr, &vm_entry, sizeof(vm_entry)) == -1) { 1030 setsyserr("vatosw: read vm_map_entry"); 1031 return 0; 1032 } 1033 #ifdef DEBUG 1034 fprintf(stderr, "vatosw: %d/%d, vaddr=%x, start=%x, end=%x ", 1035 i, mp->nentries, vaddr, vm_entry.start, vm_entry.end); 1036 fprintf(stderr, "addr=%x, next=%x\n", addr, vm_entry.next); 1037 #endif 1038 if ((vaddr >= vm_entry.start) && (vaddr < vm_entry.end)) 1039 if (vm_entry.object.vm_object != 0) 1040 break; 1041 else { 1042 #ifdef DEBUG 1043 fprintf(stderr, "vatosw: no object\n"); 1044 #endif 1045 seterr("vatosw: no object\n"); 1046 return 0; 1047 } 1048 1049 addr = (long)vm_entry.next; 1050 1051 if (addr == saddr) { 1052 seterr("vatosw: map not found\n"); 1053 return 0; 1054 } 1055 } 1056 1057 if (vm_entry.is_a_map || vm_entry.is_sub_map) { 1058 #ifdef DEBUG 1059 fprintf(stderr, "vatosw: is a %smap\n", 1060 vm_entry.is_sub_map ? "sub " : ""); 1061 #endif 1062 seterr("vatosw: is a %smap\n", 1063 vm_entry.is_sub_map ? "sub " : ""); 1064 return 0; 1065 } 1066 1067 /* Locate memory object */ 1068 off = (vaddr - vm_entry.start) + vm_entry.offset; 1069 addr = (long)vm_entry.object.vm_object; 1070 while (1) { 1071 if (kvm_read((void *) addr, &vm_object, sizeof (vm_object)) == -1) { 1072 setsyserr("vatosw: read vm_object"); 1073 return 0; 1074 } 1075 1076 #ifdef DEBUG 1077 fprintf(stderr, "vatosw: find page: object %#x offset %x\n", 1078 addr, off); 1079 #endif 1080 1081 /* Lookup in page queue */ 1082 if ((i = findpage(addr, off, maddr)) != -1) 1083 return i; 1084 1085 if (vm_object.pager != 0 && 1086 (i = pager_get(&vm_object, off, swb)) != -1) 1087 return i; 1088 1089 if (vm_object.shadow == 0) 1090 break; 1091 1092 #ifdef DEBUG 1093 fprintf(stderr, "vatosw: shadow obj at %x: offset %x+%x\n", 1094 addr, off, vm_object.shadow_offset); 1095 #endif 1096 1097 addr = (long)vm_object.shadow; 1098 off += vm_object.shadow_offset; 1099 } 1100 1101 seterr("vatosw: page not found\n"); 1102 return 0; 1103 } 1104 1105 1106 int 1107 pager_get(object, off, swb) 1108 struct vm_object *object; 1109 long off; 1110 struct swapblk *swb; 1111 { 1112 struct pager_struct pager; 1113 struct swpager swpager; 1114 struct swblock swblock; 1115 1116 /* Find address in swap space */ 1117 if (kvm_read(object->pager, &pager, sizeof (pager)) == -1) { 1118 setsyserr("pager_get: read pager"); 1119 return 0; 1120 } 1121 if (pager.pg_type != PG_SWAP) { 1122 seterr("pager_get: weird pager\n"); 1123 return 0; 1124 } 1125 1126 /* Get swap pager data */ 1127 if (kvm_read(pager.pg_data, &swpager, sizeof (swpager)) == -1) { 1128 setsyserr("pager_get: read swpager"); 1129 return 0; 1130 } 1131 1132 off += object->paging_offset; 1133 1134 /* Read swap block array */ 1135 if (kvm_read((void *) swpager.sw_blocks + 1136 (off/dbtob(swpager.sw_bsize)) * sizeof swblock, 1137 &swblock, sizeof (swblock)) == -1) { 1138 setsyserr("pager_get: read swblock"); 1139 return 0; 1140 } 1141 1142 off %= dbtob(swpager.sw_bsize); 1143 1144 if (swblock.swb_mask & (1 << atop(off))) { 1145 swb->offset = dbtob(swblock.swb_block) + off; 1146 swb->size = dbtob(swpager.sw_bsize) - off; 1147 return 1; 1148 } 1149 1150 return -1; 1151 } 1152 1153 static int 1154 findpage(object, offset, maddr) 1155 long object; 1156 long offset; 1157 vm_offset_t *maddr; 1158 { 1159 queue_head_t bucket; 1160 struct vm_page mem; 1161 long addr, baddr; 1162 1163 baddr = vm_page_buckets + 1164 vm_page_hash(object,offset) * sizeof(queue_head_t); 1165 1166 if (kvm_read((void *) baddr, &bucket, sizeof (bucket)) == -1) { 1167 seterr("can't read vm_page_bucket"); 1168 return 0; 1169 } 1170 1171 addr = (long)bucket.next; 1172 1173 while (addr != baddr) { 1174 if (kvm_read((void *) addr, &mem, sizeof (mem)) == -1) { 1175 seterr("can't read vm_page"); 1176 return 0; 1177 } 1178 1179 if ((long)mem.object == object && mem.offset == offset) { 1180 *maddr = (long)mem.phys_addr; 1181 return 1; 1182 } 1183 1184 addr = (long)mem.hashq.next; 1185 } 1186 1187 return -1; 1188 } 1189 1190 #include <varargs.h> 1191 static char errbuf[_POSIX2_LINE_MAX]; 1192 1193 static void 1194 seterr(va_alist) 1195 va_dcl 1196 { 1197 char *fmt; 1198 va_list ap; 1199 1200 va_start(ap); 1201 fmt = va_arg(ap, char *); 1202 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap); 1203 #ifdef DEBUG 1204 (void) printf("%s", errbuf); 1205 #endif 1206 va_end(ap); 1207 } 1208 1209 static void 1210 setsyserr(va_alist) 1211 va_dcl 1212 { 1213 char *fmt, *cp; 1214 va_list ap; 1215 extern int errno; 1216 1217 va_start(ap); 1218 fmt = va_arg(ap, char *); 1219 (void) vsnprintf(cp = errbuf, _POSIX2_LINE_MAX, fmt, ap); 1220 cp += strlen(cp); 1221 (void) snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", 1222 strerror(errno)); 1223 #ifdef DEBUG 1224 (void) printf("%s", errbuf); 1225 #endif 1226 va_end(ap); 1227 } 1228 1229 char * 1230 kvm_geterr() 1231 { 1232 return (errbuf); 1233 } 1234