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