1 /*- 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)kvm_proc.c 5.13 (Berkeley) 02/24/91"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <machine/pte.h> 13 #include <machine/vmparam.h> 14 #include <sys/param.h> 15 #include <sys/vmmac.h> 16 #include <sys/user.h> 17 #include <sys/proc.h> 18 #include <sys/text.h> 19 #include <sys/ioctl.h> 20 #include <sys/kinfo.h> 21 #include <sys/tty.h> 22 #include <fcntl.h> 23 #include <kvm.h> 24 #include <nlist.h> 25 #include <ndbm.h> 26 #include <limits.h> 27 #include <paths.h> 28 #include <stdio.h> 29 #include <string.h> 30 31 /* 32 * files 33 */ 34 static char *unixf, *memf, *kmemf, *swapf; 35 static int unixx, mem, kmem, swap; 36 static DBM *db; 37 /* 38 * flags 39 */ 40 static int deadkernel; 41 static int kvminit = 0; 42 static int kvmfilesopen = 0; 43 /* 44 * state 45 */ 46 static struct kinfo_proc *kvmprocbase, *kvmprocptr; 47 static int kvmnprocs; 48 /* 49 * u. buffer 50 */ 51 static union { 52 struct user user; 53 char upages[UPAGES][NBPG]; 54 } user; 55 /* 56 * random other stuff 57 */ 58 static struct pte *Usrptmap, *usrpt; 59 static int dmmin, dmmax; 60 static struct pte *Sysmap; 61 static int Syssize; 62 static int pcbpf; 63 static int argaddr0; /* XXX */ 64 static int argaddr1; 65 static int nswap; 66 static char *tmp; 67 #if defined(hp300) 68 static int lowram; 69 #endif 70 71 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 72 #define MAXSYMSIZE 256 73 74 #if defined(hp300) 75 #define pftoc(f) ((f) - lowram) 76 #define iskva(v) (1) 77 #endif 78 79 #ifndef pftoc 80 #define pftoc(f) (f) 81 #endif 82 #ifndef iskva 83 #define iskva(v) ((v) & KERNBASE) 84 #endif 85 86 static struct nlist nl[] = { 87 { "_Usrptmap" }, 88 #define X_USRPTMAP 0 89 { "_usrpt" }, 90 #define X_USRPT 1 91 { "_nswap" }, 92 #define X_NSWAP 2 93 { "_dmmin" }, 94 #define X_DMMIN 3 95 { "_dmmax" }, 96 #define X_DMMAX 4 97 /* 98 * everything here and down, only if a dead kernel 99 */ 100 { "_Sysmap" }, 101 #define X_SYSMAP 5 102 #define X_DEADKERNEL X_SYSMAP 103 { "_Syssize" }, 104 #define X_SYSSIZE 6 105 { "_allproc" }, 106 #define X_ALLPROC 7 107 { "_zombproc" }, 108 #define X_ZOMBPROC 8 109 { "_nproc" }, 110 #define X_NPROC 9 111 #define X_LAST 9 112 #if defined(hp300) 113 { "_lowram" }, 114 #define X_LOWRAM (X_LAST+1) 115 #endif 116 { "" }, 117 }; 118 119 static off_t vtophys(); 120 static void klseek(), seterr(), setsyserr(), vstodb(); 121 static int getkvars(), kvm_doprocs(), kvm_init(); 122 123 /* 124 * returns 0 if files were opened now, 125 * 1 if files were already opened, 126 * -1 if files could not be opened. 127 */ 128 kvm_openfiles(uf, mf, sf) 129 char *uf, *mf, *sf; 130 { 131 if (kvmfilesopen) 132 return (1); 133 unixx = mem = kmem = swap = -1; 134 unixf = (uf == NULL) ? _PATH_UNIX : uf; 135 memf = (mf == NULL) ? _PATH_MEM : mf; 136 137 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) { 138 setsyserr("can't open %s", unixf); 139 goto failed; 140 } 141 if ((mem = open(memf, O_RDONLY, 0)) == -1) { 142 setsyserr("can't open %s", memf); 143 goto failed; 144 } 145 if (sf != NULL) 146 swapf = sf; 147 if (mf != NULL) { 148 deadkernel++; 149 kmemf = mf; 150 kmem = mem; 151 swap = -1; 152 } else { 153 kmemf = _PATH_KMEM; 154 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) { 155 setsyserr("can't open %s", kmemf); 156 goto failed; 157 } 158 swapf = (sf == NULL) ? _PATH_DRUM : sf; 159 /* 160 * live kernel - avoid looking up nlist entries 161 * past X_DEADKERNEL. 162 */ 163 nl[X_DEADKERNEL].n_name = ""; 164 } 165 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) { 166 seterr("can't open %s", swapf); 167 goto failed; 168 } 169 kvmfilesopen++; 170 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/ 171 return (-1); 172 return (0); 173 failed: 174 kvm_close(); 175 return (-1); 176 } 177 178 static 179 kvm_init(uf, mf, sf) 180 char *uf, *mf, *sf; 181 { 182 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 183 return (-1); 184 if (getkvars() == -1) 185 return (-1); 186 kvminit = 1; 187 188 return (0); 189 } 190 191 kvm_close() 192 { 193 if (unixx != -1) { 194 close(unixx); 195 unixx = -1; 196 } 197 if (kmem != -1) { 198 if (kmem != mem) 199 close(kmem); 200 /* otherwise kmem is a copy of mem, and will be closed below */ 201 kmem = -1; 202 } 203 if (mem != -1) { 204 close(mem); 205 mem = -1; 206 } 207 if (swap != -1) { 208 close(swap); 209 swap = -1; 210 } 211 if (db != NULL) { 212 dbm_close(db); 213 db = NULL; 214 } 215 kvminit = 0; 216 kvmfilesopen = 0; 217 deadkernel = 0; 218 if (Sysmap) { 219 free(Sysmap); 220 Sysmap = NULL; 221 } 222 } 223 224 kvm_nlist(nl) 225 struct nlist *nl; 226 { 227 datum key, data; 228 char dbname[MAXPATHLEN]; 229 char dbversion[_POSIX2_LINE_MAX]; 230 char kversion[_POSIX2_LINE_MAX]; 231 int dbversionlen; 232 char symbuf[MAXSYMSIZE]; 233 struct nlist nbuf, *n; 234 int num, did; 235 236 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 237 return (-1); 238 if (deadkernel) 239 goto hard2; 240 /* 241 * initialize key datum 242 */ 243 key.dptr = symbuf; 244 245 if (db != NULL) 246 goto win; /* off to the races */ 247 /* 248 * open database 249 */ 250 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf)); 251 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL) 252 goto hard2; 253 /* 254 * read version out of database 255 */ 256 bcopy("VERSION", symbuf, sizeof ("VERSION")-1); 257 key.dsize = (sizeof ("VERSION") - 1) + 1; 258 data = dbm_fetch(db, key); 259 if (data.dptr == NULL) 260 goto hard1; 261 bcopy(data.dptr, dbversion, data.dsize); 262 dbversionlen = data.dsize; 263 /* 264 * read version string from kernel memory 265 */ 266 bcopy("_version", symbuf, sizeof ("_version")-1); 267 key.dsize = (sizeof ("_version")-1) + 1; 268 data = dbm_fetch(db, key); 269 if (data.dptr == NULL) 270 goto hard1; 271 if (data.dsize != sizeof (struct nlist)) 272 goto hard1; 273 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 274 lseek(kmem, nbuf.n_value, 0); 275 if (read(kmem, kversion, dbversionlen) != dbversionlen) 276 goto hard1; 277 /* 278 * if they match, we win - otherwise do it the hard way 279 */ 280 if (bcmp(dbversion, kversion, dbversionlen) != 0) 281 goto hard1; 282 /* 283 * getem from the database. 284 */ 285 win: 286 num = did = 0; 287 for (n = nl; n->n_name && n->n_name[0]; n++, num++) { 288 int len; 289 /* 290 * clear out fields from users buffer 291 */ 292 n->n_type = 0; 293 n->n_other = 0; 294 n->n_desc = 0; 295 n->n_value = 0; 296 /* 297 * query db 298 */ 299 if ((len = strlen(n->n_name)) > MAXSYMSIZE) { 300 seterr("kvm_nlist: symbol too large"); 301 return (-1); 302 } 303 (void)strcpy(symbuf, n->n_name); 304 key.dsize = len + 1; 305 data = dbm_fetch(db, key); 306 if (data.dptr == NULL || data.dsize != sizeof (struct nlist)) 307 continue; 308 bcopy(data.dptr, &nbuf, sizeof (struct nlist)); 309 n->n_value = nbuf.n_value; 310 n->n_type = nbuf.n_type; 311 n->n_desc = nbuf.n_desc; 312 n->n_other = nbuf.n_other; 313 did++; 314 } 315 return (num - did); 316 hard1: 317 dbm_close(db); 318 db = NULL; 319 hard2: 320 return (nlist(unixf, nl)); /* XXX seterr if -1 */ 321 } 322 323 kvm_getprocs(what, arg) 324 int what, arg; 325 { 326 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 327 return (NULL); 328 if (!deadkernel) { 329 int ret, copysize; 330 331 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) { 332 setsyserr("can't get estimate for kerninfo"); 333 return (-1); 334 } 335 copysize = ret; 336 if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize)) 337 == NULL) { 338 seterr("out of memory"); 339 return (-1); 340 } 341 if ((ret = getkerninfo(what, kvmprocbase, ©size, 342 arg)) == -1) { 343 setsyserr("can't get proc list"); 344 return (-1); 345 } 346 if (copysize % sizeof (struct kinfo_proc)) { 347 seterr("proc size mismatch (kinfo_proc: %d)", 348 sizeof (struct kinfo_proc)); 349 return (-1); 350 } 351 kvmnprocs = copysize / sizeof (struct kinfo_proc); 352 } else { 353 int nproc; 354 355 if (kvm_read(nl[X_NPROC].n_value, &nproc, sizeof (int)) != 356 sizeof (int)) { 357 seterr("can't read nproc"); 358 return (-1); 359 } 360 if ((kvmprocbase = (struct kinfo_proc *) 361 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) { 362 seterr("out of memory (addr: %x nproc = %d)", 363 nl[X_NPROC].n_value, nproc); 364 return (-1); 365 } 366 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase); 367 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc)); 368 } 369 kvmprocptr = kvmprocbase; 370 371 return (kvmnprocs); 372 } 373 374 /* 375 * XXX - should NOT give up so easily - especially since the kernel 376 * may be corrupt (it died). Should gather as much information as possible. 377 * Follows proc ptrs instead of reading table since table may go 378 * away soon. 379 */ 380 static 381 kvm_doprocs(what, arg, buff) 382 int what, arg; 383 char *buff; 384 { 385 struct proc *p, proc; 386 register char *bp = buff; 387 int i = 0; 388 int doingzomb = 0; 389 struct eproc eproc; 390 struct pgrp pgrp; 391 struct session sess; 392 struct tty tty; 393 struct text text; 394 395 /* allproc */ 396 if (kvm_read(nl[X_ALLPROC].n_value, &p, 397 sizeof (struct proc *)) != sizeof (struct proc *)) { 398 seterr("can't read allproc"); 399 return (-1); 400 } 401 402 again: 403 for (; p; p = proc.p_nxt) { 404 if (kvm_read(p, &proc, sizeof (struct proc)) != 405 sizeof (struct proc)) { 406 seterr("can't read proc at %x", p); 407 return (-1); 408 } 409 switch(ki_op(what)) { 410 411 case KINFO_PROC_PID: 412 if (proc.p_pid != (pid_t)arg) 413 continue; 414 break; 415 416 417 case KINFO_PROC_UID: 418 if (proc.p_uid != (uid_t)arg) 419 continue; 420 break; 421 422 case KINFO_PROC_RUID: 423 if (proc.p_ruid != (uid_t)arg) 424 continue; 425 break; 426 } 427 /* 428 * gather eproc 429 */ 430 eproc.e_paddr = p; 431 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) != 432 sizeof (struct pgrp)) { 433 seterr("can't read pgrp at %x", proc.p_pgrp); 434 return (-1); 435 } 436 eproc.e_sess = pgrp.pg_session; 437 eproc.e_pgid = pgrp.pg_id; 438 eproc.e_jobc = pgrp.pg_jobc; 439 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session)) 440 != sizeof (struct session)) { 441 seterr("can't read session at %x", pgrp.pg_session); 442 return (-1); 443 } 444 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) { 445 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty)) 446 != sizeof (struct tty)) { 447 seterr("can't read tty at %x", sess.s_ttyp); 448 return (-1); 449 } 450 eproc.e_tdev = tty.t_dev; 451 eproc.e_tsess = tty.t_session; 452 if (tty.t_pgrp != NULL) { 453 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct 454 pgrp)) != sizeof (struct pgrp)) { 455 seterr("can't read tpgrp at &x", 456 tty.t_pgrp); 457 return (-1); 458 } 459 eproc.e_tpgid = pgrp.pg_id; 460 } else 461 eproc.e_tpgid = -1; 462 } else 463 eproc.e_tdev = NODEV; 464 if (proc.p_wmesg) 465 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN); 466 if (proc.p_textp) { 467 kvm_read(proc.p_textp, &text, sizeof (text)); 468 eproc.e_xsize = text.x_size; 469 eproc.e_xrssize = text.x_rssize; 470 eproc.e_xccount = text.x_ccount; 471 eproc.e_xswrss = text.x_swrss; 472 } else { 473 eproc.e_xsize = eproc.e_xrssize = 474 eproc.e_xccount = eproc.e_xswrss = 0; 475 } 476 477 switch(ki_op(what)) { 478 479 case KINFO_PROC_PGRP: 480 if (eproc.e_pgid != (pid_t)arg) 481 continue; 482 break; 483 484 case KINFO_PROC_TTY: 485 if ((proc.p_flag&SCTTY) == 0 || 486 eproc.e_tdev != (dev_t)arg) 487 continue; 488 break; 489 } 490 491 i++; 492 bcopy(&proc, bp, sizeof (struct proc)); 493 bp += sizeof (struct proc); 494 bcopy(&eproc, bp, sizeof (struct eproc)); 495 bp+= sizeof (struct eproc); 496 } 497 if (!doingzomb) { 498 /* zombproc */ 499 if (kvm_read(nl[X_ZOMBPROC].n_value, &p, 500 sizeof (struct proc *)) != sizeof (struct proc *)) { 501 seterr("can't read zombproc"); 502 return (-1); 503 } 504 doingzomb = 1; 505 goto again; 506 } 507 508 return (i); 509 } 510 511 struct proc * 512 kvm_nextproc() 513 { 514 515 if (!kvmprocbase && kvm_getprocs(0, 0) == -1) 516 return (NULL); 517 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) { 518 seterr("end of proc list"); 519 return (NULL); 520 } 521 return((struct proc *)(kvmprocptr++)); 522 } 523 524 struct eproc * 525 kvm_geteproc(p) 526 const struct proc *p; 527 { 528 return ((struct eproc *)(((char *)p) + sizeof (struct proc))); 529 } 530 531 kvm_setproc() 532 { 533 kvmprocptr = kvmprocbase; 534 } 535 536 kvm_freeprocs() 537 { 538 539 if (kvmprocbase) { 540 free(kvmprocbase); 541 kvmprocbase = NULL; 542 } 543 } 544 545 struct user * 546 kvm_getu(p) 547 const struct proc *p; 548 { 549 struct pte *pteaddr, apte; 550 struct pte arguutl[HIGHPAGES+(CLSIZE*2)]; 551 register int i; 552 int ncl; 553 554 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) 555 return (NULL); 556 if (p->p_stat == SZOMB) { 557 seterr("zombie process"); 558 return (NULL); 559 } 560 if ((p->p_flag & SLOAD) == 0) { 561 if (swap < 0) { 562 seterr("no swap"); 563 return (NULL); 564 } 565 (void) lseek(swap, (long)dtob(p->p_swaddr), 0); 566 if (read(swap, (char *)&user.user, sizeof (struct user)) != 567 sizeof (struct user)) { 568 seterr("can't read u for pid %d from %s\n", 569 p->p_pid, swapf); 570 return (NULL); 571 } 572 pcbpf = 0; 573 argaddr0 = 0; 574 argaddr1 = 0; 575 return (&user.user); 576 } 577 pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1]; 578 klseek(kmem, (long)pteaddr, 0); 579 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { 580 seterr("can't read indir pte to get u for pid %d from %s", 581 p->p_pid, kmemf); 582 return (NULL); 583 } 584 lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0); 585 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { 586 seterr("can't read page table for u of pid %d from %s", 587 p->p_pid, memf); 588 return (NULL); 589 } 590 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum) 591 argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum)); 592 else 593 argaddr0 = 0; 594 if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum) 595 argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum)); 596 else 597 argaddr1 = 0; 598 pcbpf = arguutl[CLSIZE*2].pg_pfnum; 599 ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES; 600 while (--ncl >= 0) { 601 i = ncl * CLSIZE; 602 lseek(mem, 603 (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0); 604 if (read(mem, user.upages[i], CLBYTES) != CLBYTES) { 605 seterr("can't read page %d of u of pid %d from %s", 606 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf); 607 return(NULL); 608 } 609 } 610 return (&user.user); 611 } 612 613 char * 614 kvm_getargs(p, up) 615 const struct proc *p; 616 const struct user *up; 617 { 618 char cmdbuf[CLBYTES*2]; 619 union { 620 char argc[CLBYTES*2]; 621 int argi[CLBYTES*2/sizeof (int)]; 622 } argspac; 623 register char *cp; 624 register int *ip; 625 char c; 626 int nbad; 627 struct dblock db; 628 char *file; 629 630 if (up == NULL || p->p_pid == 0 || p->p_pid == 2) 631 goto retucomm; 632 if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) { 633 if (swap < 0 || p->p_ssize == 0) 634 goto retucomm; 635 vstodb(0, CLSIZE, &up->u_smap, &db, 1); 636 (void) lseek(swap, (long)dtob(db.db_base), 0); 637 if (read(swap, (char *)&argspac.argc[CLBYTES], CLBYTES) 638 != CLBYTES) 639 goto bad; 640 vstodb(1, CLSIZE, &up->u_smap, &db, 1); 641 (void) lseek(swap, (long)dtob(db.db_base), 0); 642 if (read(swap, (char *)&argspac.argc[0], CLBYTES) != CLBYTES) 643 goto bad; 644 file = swapf; 645 } else { 646 if (argaddr0) { 647 lseek(mem, (long)argaddr0, 0); 648 if (read(mem, (char *)&argspac, CLBYTES) != CLBYTES) 649 goto bad; 650 } else 651 bzero(&argspac, CLBYTES); 652 lseek(mem, (long)argaddr1, 0); 653 if (read(mem, &argspac.argc[CLBYTES], CLBYTES) != CLBYTES) 654 goto bad; 655 file = memf; 656 } 657 ip = &argspac.argi[CLBYTES*2/sizeof (int)]; 658 ip -= 2; /* last arg word and .long 0 */ 659 while (*--ip) { 660 if (ip == argspac.argi) 661 goto retucomm; 662 } 663 *(char *)ip = ' '; 664 ip++; 665 nbad = 0; 666 for (cp = (char *)ip; cp < &argspac.argc[CLBYTES*2]; cp++) { 667 c = *cp & 0177; 668 if (c == 0) 669 *cp = ' '; 670 else if (c < ' ' || c > 0176) { 671 if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */ 672 *cp++ = ' '; 673 break; 674 } 675 *cp = '?'; 676 } else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */ 677 while (*--cp != ' ') 678 if (cp <= (char *)ip) 679 break; 680 break; 681 } 682 } 683 *cp = 0; 684 while (*--cp == ' ') 685 *cp = 0; 686 cp = (char *)ip; 687 (void) strncpy(cmdbuf, cp, &argspac.argc[CLBYTES*2] - cp); 688 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') { 689 (void) strcat(cmdbuf, " ("); 690 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm)); 691 (void) strcat(cmdbuf, ")"); 692 } 693 return (cmdbuf); 694 695 bad: 696 seterr("error locating command name for pid %d from %s\n", 697 p->p_pid, file); 698 retucomm: 699 (void) strcpy(cmdbuf, " ("); 700 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm)); 701 (void) strcat(cmdbuf, ")"); 702 return (cmdbuf); 703 } 704 705 706 static 707 getkvars() 708 { 709 if (kvm_nlist(nl) == -1) 710 return (-1); 711 if (deadkernel) { 712 /* We must do the sys map first because klseek uses it */ 713 long addr; 714 715 Syssize = nl[X_SYSSIZE].n_value; 716 Sysmap = (struct pte *) 717 calloc((unsigned) Syssize, sizeof (struct pte)); 718 if (Sysmap == NULL) { 719 seterr("out of space for Sysmap"); 720 return (-1); 721 } 722 addr = (long) nl[X_SYSMAP].n_value; 723 addr &= ~KERNBASE; 724 (void) lseek(kmem, addr, 0); 725 if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte)) 726 != Syssize * sizeof (struct pte)) { 727 seterr("can't read Sysmap"); 728 return (-1); 729 } 730 #if defined(hp300) 731 addr = (long) nl[X_LOWRAM].n_value; 732 (void) lseek(kmem, addr, 0); 733 if (read(kmem, (char *) &lowram, sizeof (lowram)) 734 != sizeof (lowram)) { 735 seterr("can't read lowram"); 736 return (-1); 737 } 738 lowram = btop(lowram); 739 #endif 740 } 741 usrpt = (struct pte *)nl[X_USRPT].n_value; 742 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value; 743 if (kvm_read((long)nl[X_NSWAP].n_value, &nswap, sizeof (long)) != 744 sizeof (long)) { 745 seterr("can't read nswap"); 746 return (-1); 747 } 748 if (kvm_read((long)nl[X_DMMIN].n_value, &dmmin, sizeof (long)) != 749 sizeof (long)) { 750 seterr("can't read dmmin"); 751 return (-1); 752 } 753 if (kvm_read((long)nl[X_DMMAX].n_value, &dmmax, sizeof (long)) != 754 sizeof (long)) { 755 seterr("can't read dmmax"); 756 return (-1); 757 } 758 return (0); 759 } 760 761 kvm_read(loc, buf, len) 762 unsigned long loc; 763 char *buf; 764 { 765 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1) 766 return (-1); 767 if (iskva(loc)) { 768 klseek(kmem, loc, 0); 769 if (read(kmem, buf, len) != len) { 770 seterr("error reading kmem at %x\n", loc); 771 return (-1); 772 } 773 } else { 774 lseek(mem, loc, 0); 775 if (read(mem, buf, len) != len) { 776 seterr("error reading mem at %x\n", loc); 777 return (-1); 778 } 779 } 780 return (len); 781 } 782 783 static void 784 klseek(fd, loc, off) 785 int fd; 786 off_t loc; 787 int off; 788 { 789 790 if (deadkernel) { 791 if ((loc = vtophys(loc)) == -1) 792 return; 793 } 794 (void) lseek(fd, (off_t)loc, off); 795 } 796 797 /* 798 * Given a base/size pair in virtual swap area, 799 * return a physical base/size pair which is the 800 * (largest) initial, physically contiguous block. 801 */ 802 static void 803 vstodb(vsbase, vssize, dmp, dbp, rev) 804 register int vsbase; 805 int vssize; 806 struct dmap *dmp; 807 register struct dblock *dbp; 808 { 809 register int blk = dmmin; 810 register swblk_t *ip = dmp->dm_map; 811 812 vsbase = ctod(vsbase); 813 vssize = ctod(vssize); 814 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 815 /*panic("vstodb")*/; 816 while (vsbase >= blk) { 817 vsbase -= blk; 818 if (blk < dmmax) 819 blk *= 2; 820 ip++; 821 } 822 if (*ip <= 0 || *ip + blk > nswap) 823 /*panic("vstodb")*/; 824 dbp->db_size = MIN(vssize, blk - vsbase); 825 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase); 826 } 827 828 static off_t 829 vtophys(loc) 830 long loc; 831 { 832 int p; 833 off_t newloc; 834 register struct pte *pte; 835 836 newloc = loc & ~KERNBASE; 837 p = btop(newloc); 838 #if defined(vax) || defined(tahoe) 839 if ((loc & KERNBASE) == 0) { 840 seterr("vtophys: translating non-kernel address"); 841 return((off_t) -1); 842 } 843 #endif 844 if (p >= Syssize) { 845 seterr("vtophys: page out of bound (%d>=%d)", p, Syssize); 846 return((off_t) -1); 847 } 848 pte = &Sysmap[p]; 849 if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) { 850 seterr("vtophys: page not valid"); 851 return((off_t) -1); 852 } 853 #if defined(hp300) 854 if (pte->pg_pfnum < lowram) { 855 seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram); 856 return((off_t) -1); 857 } 858 #endif 859 loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET)); 860 return(loc); 861 } 862 863 #include <varargs.h> 864 static char errbuf[_POSIX2_LINE_MAX]; 865 866 static void 867 seterr(va_alist) 868 va_dcl 869 { 870 char *fmt; 871 va_list ap; 872 873 va_start(ap); 874 fmt = va_arg(ap, char *); 875 (void) vsprintf(errbuf, fmt, ap); 876 va_end(ap); 877 } 878 879 static void 880 setsyserr(va_alist) 881 va_dcl 882 { 883 char *fmt, *cp; 884 va_list ap; 885 extern int errno; 886 887 va_start(ap); 888 fmt = va_arg(ap, char *); 889 (void) vsprintf(errbuf, fmt, ap); 890 for (cp=errbuf; *cp; cp++) 891 ; 892 sprintf(cp, ": %s", strerror(errno)); 893 va_end(ap); 894 } 895 896 char * 897 kvm_geterr() 898 { 899 return (errbuf); 900 } 901