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 /* from: static char sccsid[] = "@(#)kvm.c 5.18 (Berkeley) 5/7/91"; */ 37 static char rcsid[] = "$Id: kvm.c,v 1.9 1993/06/01 01:48:36 cgd 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 #ifdef SPPWAIT 58 #define NEWVM 59 #endif 60 61 #ifdef NEWVM 62 #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */ 63 #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */ 64 #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/ 65 #include <vm/vm_page.h> 66 #include <vm/swap_pager.h> 67 #include <sys/kinfo_proc.h> 68 #ifdef hp300 69 #include <hp300/hp300/pte.h> 70 #endif 71 #else /* NEWVM */ 72 #include <machine/pte.h> 73 #include <sys/vmmac.h> 74 #include <sys/text.h> 75 #endif /* NEWVM */ 76 77 /* 78 * files 79 */ 80 static const char *unixf, *memf, *kmemf, *swapf; 81 static int unixx, mem, kmem, swap; 82 static DBM *db; 83 /* 84 * flags 85 */ 86 static int deadkernel; 87 static int kvminit = 0; 88 static int kvmfilesopen = 0; 89 /* 90 * state 91 */ 92 static struct kinfo_proc *kvmprocbase, *kvmprocptr; 93 static int kvmnprocs; 94 /* 95 * u. buffer 96 */ 97 static union { 98 struct user user; 99 char upages[UPAGES][NBPG]; 100 } user; 101 102 #ifdef NEWVM 103 struct swapblk { 104 long offset; /* offset in swap device */ 105 long size; /* remaining size of block in swap device */ 106 }; 107 #endif 108 /* 109 * random other stuff 110 */ 111 #ifndef NEWVM 112 static struct pte *Usrptmap, *usrpt; 113 static struct pte *Sysmap; 114 static int Syssize; 115 #endif 116 static int dmmin, dmmax; 117 static int pcbpf; 118 static int nswap; 119 static char *tmp; 120 #if defined(hp300) 121 static int lowram; 122 static struct ste *Sysseg; 123 #endif 124 #if defined(i386) 125 static struct pde *PTD; 126 #endif 127 128 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 129 #define MAXSYMSIZE 256 130 131 #if defined(hp300) 132 #define pftoc(f) ((f) - lowram) 133 #define iskva(v) (1) 134 #endif 135 136 #ifndef pftoc 137 #define pftoc(f) (f) 138 #endif 139 #ifndef iskva 140 #define iskva(v) ((u_long)(v) & KERNBASE) 141 #endif 142 143 static struct nlist nl[] = { 144 { "_Usrptmap" }, 145 #define X_USRPTMAP 0 146 { "_usrpt" }, 147 #define X_USRPT 1 148 { "_nswap" }, 149 #define X_NSWAP 2 150 { "_dmmin" }, 151 #define X_DMMIN 3 152 { "_dmmax" }, 153 #define X_DMMAX 4 154 { "_vm_page_buckets" }, 155 #define X_VM_PAGE_BUCKETS 5 156 { "_vm_page_hash_mask" }, 157 #define X_VM_PAGE_HASH_MASK 6 158 { "_page_shift" }, 159 #define X_PAGE_SHIFT 7 160 /* 161 * everything here and down, only if a dead kernel 162 */ 163 { "_Sysmap" }, 164 #define X_SYSMAP 8 165 #define X_DEADKERNEL X_SYSMAP 166 { "_Syssize" }, 167 #define X_SYSSIZE 9 168 { "_allproc" }, 169 #define X_ALLPROC 10 170 { "_zombproc" }, 171 #define X_ZOMBPROC 11 172 { "_nproc" }, 173 #define X_NPROC 12 174 #define X_LAST 12 175 #if defined(hp300) 176 { "_Sysseg" }, 177 #define X_SYSSEG (X_LAST+1) 178 { "_lowram" }, 179 #define X_LOWRAM (X_LAST+2) 180 #endif 181 #if defined(i386) 182 { "_IdlePTD" }, 183 #define X_IdlePTD (X_LAST+1) 184 #endif 185 { "" }, 186 }; 187 188 static off_t Vtophys(); 189 static void klseek(), seterr(), setsyserr(), vstodb(); 190 static int getkvars(), kvm_doprocs(), kvm_init(); 191 #ifdef NEWVM 192 static int vatosw(); 193 static int findpage(); 194 #endif 195 196 /* 197 * returns 0 if files were opened now, 198 * 1 if files were already opened, 199 * -1 if files could not be opened. 200 */ 201 kvm_openfiles(uf, mf, sf) 202 const char *uf, *mf, *sf; 203 { 204 if (kvmfilesopen) 205 return (1); 206 unixx = mem = kmem = swap = -1; 207 unixf = (uf == NULL) ? _PATH_UNIX : uf; 208 memf = (mf == NULL) ? _PATH_MEM : mf; 209 210 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) { 211 setsyserr("can't open %s", unixf); 212 goto failed; 213 } 214 if ((mem = open(memf, O_RDONLY, 0)) == -1) { 215 setsyserr("can't open %s", memf); 216 goto failed; 217 } 218 if (sf != NULL) 219 swapf = sf; 220 if (mf != NULL) { 221 deadkernel++; 222 kmemf = mf; 223 kmem = mem; 224 swap = -1; 225 } else { 226 kmemf = _PATH_KMEM; 227 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) { 228 setsyserr("can't open %s", kmemf); 229 goto failed; 230 } 231 swapf = (sf == NULL) ? _PATH_DRUM : sf; 232 /* 233 * live kernel - avoid looking up nlist entries 234 * past X_DEADKERNEL. 235 */ 236 nl[X_DEADKERNEL].n_name = ""; 237 } 238 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) { 239 seterr("can't open %s", swapf); 240 goto failed; 241 } 242 kvmfilesopen++; 243 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/ 244 return (-1); 245 return (0); 246 failed: 247 kvm_close(); 248 return (-1); 249 } 250 251 static 252 kvm_init(uf, mf, sf) 253 char *uf, *mf, *sf; 254 { 255 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 256 return (-1); 257 if (getkvars() == -1) 258 return (-1); 259 kvminit = 1; 260 261 return (0); 262 } 263 264 kvm_close() 265 { 266 if (unixx != -1) { 267 close(unixx); 268 unixx = -1; 269 } 270 if (kmem != -1) { 271 if (kmem != mem) 272 close(kmem); 273 /* otherwise kmem is a copy of mem, and will be closed below */ 274 kmem = -1; 275 } 276 if (mem != -1) { 277 close(mem); 278 mem = -1; 279 } 280 if (swap != -1) { 281 close(swap); 282 swap = -1; 283 } 284 if (db != NULL) { 285 dbm_close(db); 286 db = NULL; 287 } 288 kvminit = 0; 289 kvmfilesopen = 0; 290 deadkernel = 0; 291 #ifndef NEWVM 292 if (Sysmap) { 293 free(Sysmap); 294 Sysmap = NULL; 295 } 296 #endif 297 } 298 299 kvm_nlist(nl) 300 struct nlist *nl; 301 { 302 datum key, data; 303 char dbname[MAXPATHLEN]; 304 char dbversion[_POSIX2_LINE_MAX]; 305 char kversion[_POSIX2_LINE_MAX]; 306 int dbversionlen; 307 char symbuf[MAXSYMSIZE]; 308 struct nlist nbuf, *n; 309 int num, did; 310 311 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 312 return (-1); 313 if (deadkernel) 314 goto hard2; 315 /* 316 * initialize key datum 317 */ 318 key.dptr = symbuf; 319 320 if (db != NULL) 321 goto win; /* off to the races */ 322 /* 323 * open database 324 */ 325 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf)); 326 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL) 327 goto hard2; 328 /* 329 * read version out of database 330 */ 331 bcopy("VERSION", symbuf, sizeof ("VERSION")-1); 332 key.dsize = (sizeof ("VERSION") - 1); 333 data = dbm_fetch(db, key); 334 if (data.dptr == NULL) 335 goto hard1; 336 bcopy(data.dptr, dbversion, data.dsize); 337 dbversionlen = data.dsize; 338 /* 339 * read version string from kernel memory 340 */ 341 bcopy("_version", symbuf, sizeof ("_version")-1); 342 key.dsize = (sizeof ("_version")-1); 343 data = dbm_fetch(db, key); 344 if (data.dptr == NULL) 345 goto hard1; 346 if (data.dsize != sizeof (struct nlist)) 347 goto hard1; 348 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 349 lseek(kmem, nbuf.n_value, 0); 350 if (read(kmem, kversion, dbversionlen) != dbversionlen) 351 goto hard1; 352 /* 353 * if they match, we win - otherwise do it the hard way 354 */ 355 if (bcmp(dbversion, kversion, dbversionlen) != 0) 356 goto hard1; 357 /* 358 * getem from the database. 359 */ 360 win: 361 num = did = 0; 362 for (n = nl; n->n_name && n->n_name[0]; n++, num++) { 363 int len; 364 /* 365 * clear out fields from users buffer 366 */ 367 n->n_type = 0; 368 n->n_other = 0; 369 n->n_desc = 0; 370 n->n_value = 0; 371 /* 372 * query db 373 */ 374 if ((len = strlen(n->n_name)) > MAXSYMSIZE) { 375 seterr("symbol too large"); 376 return (-1); 377 } 378 (void)strcpy(symbuf, n->n_name); 379 key.dsize = len; 380 data = dbm_fetch(db, key); 381 if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) 382 continue; 383 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 384 n->n_value = nbuf.n_value; 385 n->n_type = nbuf.n_type; 386 n->n_desc = nbuf.n_desc; 387 n->n_other = nbuf.n_other; 388 did++; 389 } 390 return (num - did); 391 hard1: 392 dbm_close(db); 393 db = NULL; 394 hard2: 395 num = nlist(unixf, nl); 396 if (num == -1) 397 seterr("nlist (hard way) failed"); 398 return (num); 399 } 400 401 kvm_getprocs(what, arg) 402 int what, arg; 403 { 404 static int ocopysize = -1; 405 406 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 407 return (NULL); 408 if (!deadkernel) { 409 int ret, copysize; 410 411 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) { 412 setsyserr("can't get estimate for kerninfo"); 413 return (-1); 414 } 415 copysize = ret; 416 if (copysize > ocopysize || !kvmprocbase) { 417 if (ocopysize == -1 || !kvmprocbase) 418 kvmprocbase = 419 (struct kinfo_proc *)malloc(copysize); 420 else 421 kvmprocbase = 422 (struct kinfo_proc *)realloc(kvmprocbase, 423 copysize); 424 if (!kvmprocbase) { 425 seterr("out of memory"); 426 return (-1); 427 } 428 } 429 ocopysize = copysize; 430 if ((ret = getkerninfo(what, kvmprocbase, ©size, 431 arg)) == -1) { 432 setsyserr("can't get proc list"); 433 return (-1); 434 } 435 if (copysize % sizeof (struct kinfo_proc)) { 436 seterr("proc size mismatch (got %d total, kinfo_proc: %d)", 437 copysize, sizeof (struct kinfo_proc)); 438 return (-1); 439 } 440 kvmnprocs = copysize / sizeof (struct kinfo_proc); 441 } else { 442 int nproc; 443 444 if (kvm_read((void *) nl[X_NPROC].n_value, &nproc, 445 sizeof (int)) != sizeof (int)) { 446 seterr("can't read nproc"); 447 return (-1); 448 } 449 if ((kvmprocbase = (struct kinfo_proc *) 450 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) { 451 seterr("out of memory (addr: %x nproc = %d)", 452 nl[X_NPROC].n_value, nproc); 453 return (-1); 454 } 455 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase); 456 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc)); 457 } 458 kvmprocptr = kvmprocbase; 459 460 return (kvmnprocs); 461 } 462 463 /* 464 * XXX - should NOT give up so easily - especially since the kernel 465 * may be corrupt (it died). Should gather as much information as possible. 466 * Follows proc ptrs instead of reading table since table may go 467 * away soon. 468 */ 469 static 470 kvm_doprocs(what, arg, buff) 471 int what, arg; 472 char *buff; 473 { 474 struct proc *p, proc; 475 register char *bp = buff; 476 int i = 0; 477 int doingzomb = 0; 478 struct eproc eproc; 479 struct pgrp pgrp; 480 struct session sess; 481 struct tty tty; 482 #ifndef NEWVM 483 struct text text; 484 #endif 485 486 /* allproc */ 487 if (kvm_read((void *) nl[X_ALLPROC].n_value, &p, 488 sizeof (struct proc *)) != sizeof (struct proc *)) { 489 seterr("can't read allproc"); 490 return (-1); 491 } 492 493 again: 494 for (; p; p = proc.p_nxt) { 495 if (kvm_read(p, &proc, sizeof (struct proc)) != 496 sizeof (struct proc)) { 497 seterr("can't read proc at %x", p); 498 return (-1); 499 } 500 #ifdef NEWVM 501 if (kvm_read(proc.p_cred, &eproc.e_pcred, 502 sizeof (struct pcred)) == sizeof (struct pcred)) 503 (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred, 504 sizeof (struct ucred)); 505 switch(ki_op(what)) { 506 507 case KINFO_PROC_PID: 508 if (proc.p_pid != (pid_t)arg) 509 continue; 510 break; 511 512 513 case KINFO_PROC_UID: 514 if (eproc.e_ucred.cr_uid != (uid_t)arg) 515 continue; 516 break; 517 518 case KINFO_PROC_RUID: 519 if (eproc.e_pcred.p_ruid != (uid_t)arg) 520 continue; 521 break; 522 } 523 #else 524 switch(ki_op(what)) { 525 526 case KINFO_PROC_PID: 527 if (proc.p_pid != (pid_t)arg) 528 continue; 529 break; 530 531 532 case KINFO_PROC_UID: 533 if (proc.p_uid != (uid_t)arg) 534 continue; 535 break; 536 537 case KINFO_PROC_RUID: 538 if (proc.p_ruid != (uid_t)arg) 539 continue; 540 break; 541 } 542 #endif 543 /* 544 * gather eproc 545 */ 546 eproc.e_paddr = p; 547 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) != 548 sizeof (struct pgrp)) { 549 seterr("can't read pgrp at %x", proc.p_pgrp); 550 return (-1); 551 } 552 eproc.e_sess = pgrp.pg_session; 553 eproc.e_pgid = pgrp.pg_id; 554 eproc.e_jobc = pgrp.pg_jobc; 555 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session)) 556 != sizeof (struct session)) { 557 seterr("can't read session at %x", pgrp.pg_session); 558 return (-1); 559 } 560 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) { 561 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty)) 562 != sizeof (struct tty)) { 563 seterr("can't read tty at %x", sess.s_ttyp); 564 return (-1); 565 } 566 eproc.e_tdev = tty.t_dev; 567 eproc.e_tsess = tty.t_session; 568 if (tty.t_pgrp != NULL) { 569 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct 570 pgrp)) != sizeof (struct pgrp)) { 571 seterr("can't read tpgrp at &x", 572 tty.t_pgrp); 573 return (-1); 574 } 575 eproc.e_tpgid = pgrp.pg_id; 576 } else 577 eproc.e_tpgid = -1; 578 } else 579 eproc.e_tdev = NODEV; 580 if (proc.p_wmesg) 581 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN); 582 #ifdef NEWVM 583 (void) kvm_read(proc.p_vmspace, &eproc.e_vm, 584 sizeof (struct vmspace)); 585 eproc.e_xsize = eproc.e_xrssize = 586 eproc.e_xccount = eproc.e_xswrss = 0; 587 #else 588 if (proc.p_textp) { 589 kvm_read(proc.p_textp, &text, sizeof (text)); 590 eproc.e_xsize = text.x_size; 591 eproc.e_xrssize = text.x_rssize; 592 eproc.e_xccount = text.x_ccount; 593 eproc.e_xswrss = text.x_swrss; 594 } else { 595 eproc.e_xsize = eproc.e_xrssize = 596 eproc.e_xccount = eproc.e_xswrss = 0; 597 } 598 #endif 599 600 switch(ki_op(what)) { 601 602 case KINFO_PROC_PGRP: 603 if (eproc.e_pgid != (pid_t)arg) 604 continue; 605 break; 606 607 case KINFO_PROC_TTY: 608 if ((proc.p_flag&SCTTY) == 0 || 609 eproc.e_tdev != (dev_t)arg) 610 continue; 611 break; 612 } 613 614 i++; 615 bcopy(&proc, bp, sizeof (struct proc)); 616 bp += sizeof (struct proc); 617 bcopy(&eproc, bp, sizeof (struct eproc)); 618 bp+= sizeof (struct eproc); 619 } 620 if (!doingzomb) { 621 /* zombproc */ 622 if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p, 623 sizeof (struct proc *)) != sizeof (struct proc *)) { 624 seterr("can't read zombproc"); 625 return (-1); 626 } 627 doingzomb = 1; 628 goto again; 629 } 630 631 return (i); 632 } 633 634 struct proc * 635 kvm_nextproc() 636 { 637 638 if (!kvmprocbase && kvm_getprocs(0, 0) == -1) 639 return (NULL); 640 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) { 641 seterr("end of proc list"); 642 return (NULL); 643 } 644 return((struct proc *)(kvmprocptr++)); 645 } 646 647 struct eproc * 648 kvm_geteproc(p) 649 const struct proc *p; 650 { 651 return ((struct eproc *)(((char *)p) + sizeof (struct proc))); 652 } 653 654 kvm_setproc() 655 { 656 kvmprocptr = kvmprocbase; 657 } 658 659 kvm_freeprocs() 660 { 661 662 if (kvmprocbase) { 663 free(kvmprocbase); 664 kvmprocbase = NULL; 665 } 666 } 667 668 #ifdef NEWVM 669 struct user * 670 kvm_getu(p) 671 const struct proc *p; 672 { 673 register struct kinfo_proc *kp = (struct kinfo_proc *)p; 674 register int i; 675 register char *up; 676 u_int vaddr; 677 struct swapblk swb; 678 679 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 680 return (NULL); 681 if (p->p_stat == SZOMB) { 682 seterr("zombie process"); 683 return (NULL); 684 } 685 686 if ((p->p_flag & SLOAD) == 0) { 687 vm_offset_t maddr; 688 689 if (swap < 0) { 690 seterr("no swap"); 691 return (NULL); 692 } 693 /* 694 * Costly operation, better set enable_swap to zero 695 * in vm/vm_glue.c, since paging of user pages isn't 696 * done yet anyway. 697 */ 698 if (vatosw(p, USRSTACK + i * NBPG, &maddr, &swb) == 0) 699 return NULL; 700 701 if (maddr == 0 && swb.size < UPAGES * NBPG) 702 return NULL; 703 704 for (i = 0; i < UPAGES; i++) { 705 if (maddr) { 706 (void) lseek(mem, maddr + i * NBPG, 0); 707 if (read(mem, 708 (char *)user.upages[i], NBPG) != NBPG) { 709 seterr( 710 "can't read u for pid %d from %s", 711 p->p_pid, swapf); 712 return NULL; 713 } 714 } else { 715 (void) lseek(swap, swb.offset + i * NBPG, 0); 716 if (read(swap, 717 (char *)user.upages[i], NBPG) != NBPG) { 718 seterr( 719 "can't read u for pid %d from %s", 720 p->p_pid, swapf); 721 return NULL; 722 } 723 } 724 } 725 return(&user.user); 726 } 727 /* 728 * Read u-area one page at a time for the benefit of post-mortems 729 */ 730 up = (char *) p->p_addr; 731 for (i = 0; i < UPAGES; i++) { 732 klseek(kmem, (long)up, 0); 733 if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) { 734 seterr("cant read page %x of u of pid %d from %s", 735 up, p->p_pid, kmemf); 736 return(NULL); 737 } 738 up += CLBYTES; 739 } 740 pcbpf = (int) btop(p->p_addr); /* what should this be really? */ 741 742 kp->kp_eproc.e_vm.vm_rssize = 743 kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */ 744 return(&user.user); 745 } 746 #else 747 struct user * 748 kvm_getu(p) 749 const struct proc *p; 750 { 751 struct pte *pteaddr, apte; 752 struct pte arguutl[HIGHPAGES+(CLSIZE*2)]; 753 register int i; 754 int ncl; 755 756 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 757 return (NULL); 758 if (p->p_stat == SZOMB) { 759 seterr("zombie process"); 760 return (NULL); 761 } 762 if ((p->p_flag & SLOAD) == 0) { 763 if (swap < 0) { 764 seterr("no swap"); 765 return (NULL); 766 } 767 (void) lseek(swap, (long)dtob(p->p_swaddr), 0); 768 if (read(swap, (char *)&user.user, sizeof (struct user)) != 769 sizeof (struct user)) { 770 seterr("can't read u for pid %d from %s", 771 p->p_pid, swapf); 772 return (NULL); 773 } 774 pcbpf = 0; 775 argaddr0 = 0; 776 argaddr1 = 0; 777 return (&user.user); 778 } 779 pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1]; 780 klseek(kmem, (long)pteaddr, 0); 781 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { 782 seterr("can't read indir pte to get u for pid %d from %s", 783 p->p_pid, kmemf); 784 return (NULL); 785 } 786 lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0); 787 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { 788 seterr("can't read page table for u of pid %d from %s", 789 p->p_pid, memf); 790 return (NULL); 791 } 792 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) 793 argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum)); 794 else 795 argaddr0 = 0; 796 if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum) 797 argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum)); 798 else 799 argaddr1 = 0; 800 pcbpf = arguutl[CLSIZE*2].pg_pfnum; 801 ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES; 802 while (--ncl >= 0) { 803 i = ncl * CLSIZE; 804 lseek(mem, 805 (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0); 806 if (read(mem, user.upages[i], CLBYTES) != CLBYTES) { 807 seterr("can't read page %d of u of pid %d from %s", 808 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf); 809 return(NULL); 810 } 811 } 812 return (&user.user); 813 } 814 #endif 815 816 int 817 kvm_procread(p, addr, buf, len) 818 const struct proc *p; 819 const unsigned addr, buf, len; 820 { 821 register struct kinfo_proc *kp = (struct kinfo_proc *) p; 822 struct swapblk swb; 823 vm_offset_t swaddr = 0, memaddr = 0; 824 unsigned real_len; 825 826 real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET)); 827 828 #if defined(hp300) 829 /* 830 * XXX DANGER WILL ROBINSON -- i have *no* idea to what extent this 831 * works... -- cgd 832 */ 833 BREAK HERE!!! 834 #endif 835 #if defined(i386) 836 if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) { 837 struct pde pde; 838 839 klseek(kmem, 840 (long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(addr)]), 0); 841 842 if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde 843 && pde.pd_v) { 844 845 struct pte pte; 846 847 if (lseek(mem, (long)ctob(pde.pd_pfnum) + 848 (ptei(addr) * sizeof pte), 0) == -1) 849 seterr("kvm_procread: lseek"); 850 if (read(mem, (char *)&pte, sizeof pte) == sizeof pte) { 851 if (pte.pg_v) { 852 memaddr = (long)ctob(pte.pg_pfnum) + 853 (addr % (1 << PGSHIFT)); 854 } 855 } else { 856 seterr("kvm_procread: read"); 857 } 858 } 859 } 860 #endif /* i386 */ 861 862 if (memaddr == 0 && vatosw(p, addr & ~CLOFSET, &memaddr, &swb)) { 863 if (memaddr != 0) { 864 memaddr += addr & CLOFSET; 865 } else { 866 swaddr += addr & CLOFSET; 867 swb.size -= addr & CLOFSET; 868 if (swb.size >= real_len) 869 swaddr = swb.offset; 870 } 871 } 872 873 if (memaddr) { 874 if (lseek(mem, memaddr, 0) == -1) 875 seterr("kvm_getu: lseek"); 876 real_len = read(mem, (char *)buf, real_len); 877 if (real_len == -1) { 878 real_len = 0; 879 seterr("kvm_procread: read"); 880 } 881 } else if (swaddr) { 882 if (lseek(swap, swaddr, 0) == -1) 883 seterr("kvm_getu: lseek"); 884 real_len = read(swap, (char *)buf, real_len); 885 if (real_len == -1) { 886 real_len = 0; 887 seterr("kvm_procread: read"); 888 } 889 } else 890 real_len = 0; 891 892 return real_len; 893 } 894 895 int 896 kvm_procreadstr(p, addr, buf, len) 897 const struct proc *p; 898 const unsigned addr, buf; 899 unsigned len; 900 { 901 int done; 902 char a, *bp = (char *) buf; 903 904 /* XXX -- should be optimized */ 905 906 done = 0; 907 while (len && kvm_procread(p, addr+done, &a, 1) == 1) { 908 *bp++ = a; 909 if (a == '\0') 910 return done; 911 done++; 912 len--; 913 } 914 return done; 915 } 916 917 char * 918 kvm_getargs(p, up) 919 const struct proc *p; 920 const struct user *up; 921 { 922 static char cmdbuf[ARG_MAX + sizeof(p->p_comm) + 5]; 923 register char *cp, *acp; 924 int left, rv; 925 struct ps_strings arginfo; 926 927 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 928 goto retucomm; 929 930 if (kvm_procread(p, PS_STRINGS, &arginfo, sizeof(arginfo)) != 931 sizeof(arginfo)) 932 goto bad; 933 934 cp = cmdbuf; 935 acp = arginfo.ps_argvstr; 936 left = ARG_MAX + 1; 937 while (arginfo.ps_nargvstr--) { 938 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) { 939 acp += rv + 1; 940 left -= rv + 1; 941 cp += rv; 942 *cp++ = ' '; 943 *cp = '\0'; 944 } else 945 goto bad; 946 } 947 cp-- ; *cp = '\0'; 948 949 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') { 950 (void) strcat(cmdbuf, " ("); 951 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); 952 (void) strcat(cmdbuf, ")"); 953 } 954 return (cmdbuf); 955 956 bad: 957 seterr("error locating command name for pid %d", p->p_pid); 958 retucomm: 959 (void) strcpy(cmdbuf, "("); 960 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm)); 961 (void) strcat(cmdbuf, ")"); 962 return (cmdbuf); 963 } 964 965 char * 966 kvm_getenv(p, up) 967 const struct proc *p; 968 const struct user *up; 969 { 970 static char envbuf[ARG_MAX + 1]; 971 register char *cp, *acp; 972 int left, rv; 973 struct ps_strings arginfo; 974 975 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 976 goto retemptyenv; 977 978 if (kvm_procread(p, PS_STRINGS, &arginfo, sizeof(arginfo)) != 979 sizeof(arginfo)) 980 goto bad; 981 982 cp = envbuf; 983 acp = arginfo.ps_envstr; 984 left = ARG_MAX + 1; 985 while (arginfo.ps_nenvstr--) { 986 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) { 987 acp += rv + 1; 988 left -= rv + 1; 989 cp += rv; 990 *cp++ = ' '; 991 *cp = '\0'; 992 } else 993 goto bad; 994 } 995 cp-- ; *cp = '\0'; 996 return (envbuf); 997 998 bad: 999 seterr("error locating environment for pid %d", p->p_pid); 1000 retemptyenv: 1001 envbuf[0] = '\0'; 1002 return (envbuf); 1003 } 1004 1005 static 1006 getkvars() 1007 { 1008 if (kvm_nlist(nl) == -1) 1009 return (-1); 1010 if (deadkernel) { 1011 /* We must do the sys map first because klseek uses it */ 1012 long addr; 1013 1014 #ifndef NEWVM 1015 Syssize = nl[X_SYSSIZE].n_value; 1016 Sysmap = (struct pte *) 1017 calloc((unsigned) Syssize, sizeof (struct pte)); 1018 if (Sysmap == NULL) { 1019 seterr("out of space for Sysmap"); 1020 return (-1); 1021 } 1022 addr = (long) nl[X_SYSMAP].n_value; 1023 addr &= ~KERNBASE; 1024 (void) lseek(kmem, addr, 0); 1025 if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte)) 1026 != Syssize * sizeof (struct pte)) { 1027 seterr("can't read Sysmap"); 1028 return (-1); 1029 } 1030 #endif 1031 #if defined(hp300) 1032 addr = (long) nl[X_LOWRAM].n_value; 1033 (void) lseek(kmem, addr, 0); 1034 if (read(kmem, (char *) &lowram, sizeof (lowram)) 1035 != sizeof (lowram)) { 1036 seterr("can't read lowram"); 1037 return (-1); 1038 } 1039 lowram = btop(lowram); 1040 Sysseg = (struct ste *) malloc(NBPG); 1041 if (Sysseg == NULL) { 1042 seterr("out of space for Sysseg"); 1043 return (-1); 1044 } 1045 addr = (long) nl[X_SYSSEG].n_value; 1046 (void) lseek(kmem, addr, 0); 1047 read(kmem, (char *)&addr, sizeof(addr)); 1048 (void) lseek(kmem, (long)addr, 0); 1049 if (read(kmem, (char *) Sysseg, NBPG) != NBPG) { 1050 seterr("can't read Sysseg"); 1051 return (-1); 1052 } 1053 #endif 1054 #if defined(i386) 1055 PTD = (struct pde *) malloc(NBPG); 1056 if (PTD == NULL) { 1057 seterr("out of space for PTD"); 1058 return (-1); 1059 } 1060 addr = (long) nl[X_IdlePTD].n_value; 1061 (void) lseek(kmem, addr, 0); 1062 read(kmem, (char *)&addr, sizeof(addr)); 1063 (void) lseek(kmem, (long)addr, 0); 1064 if (read(kmem, (char *) PTD, NBPG) != NBPG) { 1065 seterr("can't read PTD"); 1066 return (-1); 1067 } 1068 #endif 1069 } 1070 #ifndef NEWVM 1071 usrpt = (struct pte *)nl[X_USRPT].n_value; 1072 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value; 1073 #endif 1074 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) != 1075 sizeof (long)) { 1076 seterr("can't read nswap"); 1077 return (-1); 1078 } 1079 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) != 1080 sizeof (long)) { 1081 seterr("can't read dmmin"); 1082 return (-1); 1083 } 1084 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) != 1085 sizeof (long)) { 1086 seterr("can't read dmmax"); 1087 return (-1); 1088 } 1089 return (0); 1090 } 1091 1092 kvm_read(loc, buf, len) 1093 void *loc; 1094 void *buf; 1095 { 1096 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 1097 return (-1); 1098 if (iskva(loc)) { 1099 klseek(kmem, (off_t) loc, 0); 1100 if (read(kmem, buf, len) != len) { 1101 seterr("error reading kmem at %x", loc); 1102 return (-1); 1103 } 1104 } else { 1105 lseek(mem, (off_t) loc, 0); 1106 if (read(mem, buf, len) != len) { 1107 seterr("error reading mem at %x", loc); 1108 return (-1); 1109 } 1110 } 1111 return (len); 1112 } 1113 1114 static void 1115 klseek(fd, loc, off) 1116 int fd; 1117 off_t loc; 1118 int off; 1119 { 1120 1121 if (deadkernel) { 1122 if ((loc = Vtophys(loc)) == -1) 1123 return; 1124 } 1125 (void) lseek(fd, (off_t)loc, off); 1126 } 1127 1128 #ifndef NEWVM 1129 /* 1130 * Given a base/size pair in virtual swap area, 1131 * return a physical base/size pair which is the 1132 * (largest) initial, physically contiguous block. 1133 */ 1134 static void 1135 vstodb(vsbase, vssize, dmp, dbp, rev) 1136 register int vsbase; 1137 int vssize; 1138 struct dmap *dmp; 1139 register struct dblock *dbp; 1140 { 1141 register int blk = dmmin; 1142 register swblk_t *ip = dmp->dm_map; 1143 1144 vsbase = ctod(vsbase); 1145 vssize = ctod(vssize); 1146 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 1147 /*panic("vstodb")*/; 1148 while (vsbase >= blk) { 1149 vsbase -= blk; 1150 if (blk < dmmax) 1151 blk *= 2; 1152 ip++; 1153 } 1154 if (*ip <= 0 || *ip + blk > nswap) 1155 /*panic("vstodb")*/; 1156 dbp->db_size = MIN(vssize, blk - vsbase); 1157 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 1158 } 1159 #endif 1160 1161 #ifdef NEWVM 1162 static off_t 1163 Vtophys(loc) 1164 u_long loc; 1165 { 1166 off_t newloc = (off_t) -1; 1167 #ifdef hp300 1168 int p, ste, pte; 1169 1170 ste = *(int *)&Sysseg[loc >> SG_ISHIFT]; 1171 if ((ste & SG_V) == 0) { 1172 seterr("vtophys: segment not valid"); 1173 return((off_t) -1); 1174 } 1175 p = btop(loc & SG_PMASK); 1176 newloc = (ste & SG_FRAME) + (p * sizeof(struct pte)); 1177 (void) lseek(kmem, (long)(newloc-(off_t)ptob(lowram)), 0); 1178 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) { 1179 seterr("vtophys: cannot locate pte"); 1180 return((off_t) -1); 1181 } 1182 newloc = pte & PG_FRAME; 1183 if (pte == PG_NV || newloc < (off_t)ptob(lowram)) { 1184 seterr("vtophys: page not valid"); 1185 return((off_t) -1); 1186 } 1187 newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET); 1188 #endif 1189 #ifdef i386 1190 struct pde pde; 1191 struct pte pte; 1192 int p; 1193 1194 pde = PTD[loc >> PD_SHIFT]; 1195 if (pde.pd_v == 0) { 1196 seterr("vtophys: page directory entry not valid"); 1197 return((off_t) -1); 1198 } 1199 p = btop(loc & PT_MASK); 1200 newloc = pde.pd_pfnum + (p * sizeof(struct pte)); 1201 (void) lseek(kmem, (long)newloc, 0); 1202 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) { 1203 seterr("vtophys: cannot obtain desired pte"); 1204 return((off_t) -1); 1205 } 1206 newloc = pte.pg_pfnum; 1207 if (pte.pg_v == 0) { 1208 seterr("vtophys: page table entry not valid"); 1209 return((off_t) -1); 1210 } 1211 newloc += (loc & PGOFSET); 1212 #endif 1213 return((off_t) newloc); 1214 } 1215 #else 1216 static off_t 1217 vtophys(loc) 1218 long loc; 1219 { 1220 int p; 1221 off_t newloc; 1222 register struct pte *pte; 1223 1224 newloc = loc & ~KERNBASE; 1225 p = btop(newloc); 1226 #if defined(vax) || defined(tahoe) 1227 if ((loc & KERNBASE) == 0) { 1228 seterr("vtophys: translating non-kernel address"); 1229 return((off_t) -1); 1230 } 1231 #endif 1232 if (p >= Syssize) { 1233 seterr("vtophys: page out of bound (%d>=%d)", p, Syssize); 1234 return((off_t) -1); 1235 } 1236 pte = &Sysmap[p]; 1237 if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) { 1238 seterr("vtophys: page not valid"); 1239 return((off_t) -1); 1240 } 1241 #if defined(hp300) 1242 if (pte->pg_pfnum < lowram) { 1243 seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram); 1244 return((off_t) -1); 1245 } 1246 #endif 1247 loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET)); 1248 return(loc); 1249 } 1250 #endif 1251 1252 1253 #ifdef NEWVM 1254 /* 1255 * locate address of unwired or swapped page 1256 */ 1257 1258 #define DEBUG 0 1259 1260 #define KREAD(off, addr, len) \ 1261 (kvm_read((void *)(off), (char *)(addr), (len)) == (len)) 1262 1263 1264 static int 1265 vatosw(p, vaddr, maddr, swb) 1266 struct proc *p ; 1267 vm_offset_t vaddr; 1268 vm_offset_t *maddr; 1269 struct swapblk *swb; 1270 { 1271 register struct kinfo_proc *kp = (struct kinfo_proc *)p; 1272 vm_map_t mp = &kp->kp_eproc.e_vm.vm_map; 1273 struct vm_object vm_object; 1274 struct vm_map_entry vm_entry; 1275 struct pager_struct pager; 1276 struct swpager swpager; 1277 struct swblock swblock; 1278 long addr, off; 1279 int i; 1280 1281 if (p->p_pid == 0 || p->p_pid == 2) 1282 return 0; 1283 1284 addr = (long)mp->header.next; 1285 for (i = 0; i < mp->nentries; i++) { 1286 /* Weed through map entries until vaddr in range */ 1287 if (!KREAD(addr, &vm_entry, sizeof(vm_entry))) { 1288 setsyserr("vatosw: read vm_map_entry"); 1289 return 0; 1290 } 1291 if ((vaddr >= vm_entry.start) && (vaddr <= vm_entry.end) && 1292 (vm_entry.object.vm_object != 0)) 1293 break; 1294 1295 addr = (long)vm_entry.next; 1296 } 1297 if (i == mp->nentries) { 1298 seterr("%u: map not found\n", p->p_pid); 1299 return 0; 1300 } 1301 1302 if (vm_entry.is_a_map || vm_entry.is_sub_map) { 1303 seterr("%u: Is a map\n", p->p_pid); 1304 return 0; 1305 } 1306 1307 /* Locate memory object */ 1308 off = (vaddr - vm_entry.start) + vm_entry.offset; 1309 addr = (long)vm_entry.object.vm_object; 1310 while (1) { 1311 if (!KREAD(addr, &vm_object, sizeof vm_object)) { 1312 setsyserr("vatosw: read vm_object"); 1313 return 0; 1314 } 1315 1316 #if DEBUG 1317 fprintf(stderr, "%u: find page: object %#x offset %x\n", 1318 p->p_pid, addr, off); 1319 #endif 1320 1321 /* Lookup in page queue */ 1322 if (findpage(addr, off, maddr)) 1323 return 1; 1324 1325 if (vm_object.shadow == 0) 1326 break; 1327 1328 #if DEBUG 1329 fprintf(stderr, "%u: shadow obj at %x: offset %x+%x\n", 1330 p->p_pid, addr, off, vm_object.shadow_offset); 1331 #endif 1332 1333 addr = (long)vm_object.shadow; 1334 off += vm_object.shadow_offset; 1335 } 1336 1337 if (!vm_object.pager) { 1338 seterr("%u: no pager\n", p->p_pid); 1339 return 0; 1340 } 1341 1342 /* Find address in swap space */ 1343 if (!KREAD(vm_object.pager, &pager, sizeof pager)) { 1344 setsyserr("vatosw: read pager"); 1345 return 0; 1346 } 1347 if (pager.pg_type != PG_SWAP) { 1348 seterr("%u: weird pager\n", p->p_pid); 1349 return 0; 1350 } 1351 1352 /* Get swap pager data */ 1353 if (!KREAD(pager.pg_data, &swpager, sizeof swpager)) { 1354 setsyserr("vatosw: read swpager"); 1355 return 0; 1356 } 1357 1358 off += vm_object.paging_offset; 1359 1360 /* Read swap block array */ 1361 if (!KREAD((long)swpager.sw_blocks + 1362 (off/dbtob(swpager.sw_bsize)) * sizeof swblock, 1363 &swblock, sizeof swblock)) { 1364 setsyserr("vatosw: read swblock"); 1365 return 0; 1366 } 1367 swb->offset = dbtob(swblock.swb_block)+ (off % dbtob(swpager.sw_bsize)); 1368 swb->size = dbtob(swpager.sw_bsize) - (off % dbtob(swpager.sw_bsize)); 1369 return 1; 1370 } 1371 1372 1373 #define atop(x) (((unsigned)(x)) >> page_shift) 1374 #define vm_page_hash(object, offset) \ 1375 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask) 1376 1377 static int 1378 findpage(object, offset, maddr) 1379 long object; 1380 long offset; 1381 vm_offset_t *maddr; 1382 { 1383 static long vm_page_hash_mask; 1384 static long vm_page_buckets; 1385 static long page_shift; 1386 queue_head_t bucket; 1387 struct vm_page mem; 1388 long addr, baddr; 1389 1390 if (vm_page_hash_mask == 0 && !KREAD(nl[X_VM_PAGE_HASH_MASK].n_value, 1391 &vm_page_hash_mask, sizeof (long))) { 1392 seterr("can't read vm_page_hash_mask"); 1393 return 0; 1394 } 1395 if (page_shift == 0 && !KREAD(nl[X_PAGE_SHIFT].n_value, 1396 &page_shift, sizeof (long))) { 1397 seterr("can't read page_shift"); 1398 return 0; 1399 } 1400 if (vm_page_buckets == 0 && !KREAD(nl[X_VM_PAGE_BUCKETS].n_value, 1401 &vm_page_buckets, sizeof (long))) { 1402 seterr("can't read vm_page_buckets"); 1403 return 0; 1404 } 1405 1406 baddr = vm_page_buckets + vm_page_hash(object,offset) * sizeof(queue_head_t); 1407 if (!KREAD(baddr, &bucket, sizeof (bucket))) { 1408 seterr("can't read vm_page_bucket"); 1409 return 0; 1410 } 1411 1412 addr = (long)bucket.next; 1413 while (addr != baddr) { 1414 if (!KREAD(addr, &mem, sizeof (mem))) { 1415 seterr("can't read vm_page"); 1416 return 0; 1417 } 1418 if ((long)mem.object == object && mem.offset == offset) { 1419 *maddr = (long)mem.phys_addr; 1420 return 1; 1421 } 1422 addr = (long)mem.hashq.next; 1423 } 1424 return 0; 1425 } 1426 #endif /* NEWVM */ 1427 1428 #include <varargs.h> 1429 static char errbuf[_POSIX2_LINE_MAX]; 1430 1431 static void 1432 seterr(va_alist) 1433 va_dcl 1434 { 1435 char *fmt; 1436 va_list ap; 1437 1438 va_start(ap); 1439 fmt = va_arg(ap, char *); 1440 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap); 1441 #if DEBUG 1442 (void) vfprintf(stderr, fmt, ap); 1443 #endif 1444 va_end(ap); 1445 } 1446 1447 static void 1448 setsyserr(va_alist) 1449 va_dcl 1450 { 1451 char *fmt, *cp; 1452 va_list ap; 1453 extern int errno; 1454 1455 va_start(ap); 1456 fmt = va_arg(ap, char *); 1457 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap); 1458 for (cp=errbuf; *cp; cp++) 1459 ; 1460 snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno)); 1461 va_end(ap); 1462 } 1463 1464 char * 1465 kvm_geterr() 1466 { 1467 return (errbuf); 1468 } 1469