1 static char *sccsid = "@(#)analyze.c 4.4 (Berkeley) 05/18/81"; 2 #include <stdio.h> 3 #include <sys/param.h> 4 #include <sys/dir.h> 5 #include <sys/pte.h> 6 #include <nlist.h> 7 #include <sys/map.h> 8 #include <sys/user.h> 9 #include <sys/proc.h> 10 #include <sys/text.h> 11 #include <sys/cmap.h> 12 #include <sys/vm.h> 13 14 /* 15 * Analyze - analyze a core (and optional paging area) saved from 16 * a virtual Unix system crash. 17 */ 18 19 int Dflg; 20 int dflg; 21 int vflg; 22 int mflg; 23 int fflg; 24 int sflg; 25 int uflg; 26 27 /* use vprintf with care; it plays havoc with ``else's'' */ 28 #define vprintf if (vflg) printf 29 30 #define clear(x) ((int)x & 0x7fffffff) 31 32 struct proc *proc, *aproc; 33 int nproc; 34 struct text *text, *atext; 35 int ntext; 36 struct mapent *swapmap; 37 int nswapmap; 38 struct cmap *cmap; 39 int ecmx; 40 struct pte *usrpt; 41 struct pte *Usrptma; 42 int firstfree; 43 int maxfree; 44 int freemem; 45 struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 46 int pid; 47 48 struct paginfo { 49 char z_type; 50 char z_count; 51 short z_pid; 52 struct pte z_pte; 53 } *paginfo; 54 #define ZLOST 0 55 #define ZDATA 1 56 #define ZSTACK 2 57 #define ZUDOT 3 58 #define ZPAGET 4 59 #define ZTEXT 5 60 #define ZFREE 6 61 #define ZINTRAN 7 62 63 struct dblks { 64 short d_first; 65 short d_size; 66 char d_type; 67 char d_index; 68 } *dblks; 69 int ndblks; 70 71 #define DFREE 0 72 #define DDATA 1 73 #define DSTACK 2 74 #define DTEXT 3 75 #define DUDOT 4 76 #define DPAGET 5 77 78 union { 79 char buf[UPAGES][512]; 80 struct user U; 81 } u_area; 82 #define u u_area.U 83 84 int fcore = -1; 85 int fswap = -1; 86 87 struct nlist nl[] = { 88 #define X_PROC 0 89 { "_proc" }, 90 #define X_USRPT 1 91 { "_usrpt" }, 92 #define X_PTMA 2 93 { "_Usrptmap" }, 94 #define X_FIRSTFREE 3 95 { "_firstfree" }, 96 #define X_MAXFREE 4 97 { "_maxfree" }, 98 #define X_TEXT 5 99 { "_text" }, 100 #define X_FREEMEM 6 101 { "_freemem" }, 102 #define X_CMAP 7 103 { "_cmap" }, 104 #define X_ECMAP 8 105 { "_ecmap" }, 106 #define X_SWAPMAP 9 107 { "_swapmap" }, 108 #define X_NPROC 10 109 { "_nproc" }, 110 #define X_NTEXT 11 111 { "_ntext" }, 112 #define X_NSWAPMAP 12 113 { "_nswapmap" }, 114 { 0 } 115 }; 116 117 main(argc, argv) 118 int argc; 119 char **argv; 120 { 121 register struct nlist *np; 122 register struct proc *p; 123 register struct text *xp; 124 register struct pte *pte; 125 register int i; 126 int w, a; 127 128 argc--, argv++; 129 while (argc > 0 && argv[0][0] == '-') { 130 register char *cp = *argv++; 131 argc--; 132 while (*++cp) switch (*cp) { 133 134 case 'm': 135 mflg++; 136 break; 137 138 case 'v': 139 vflg++; 140 break; 141 142 case 's': 143 if (argc < 2) 144 goto usage; 145 if ((fswap = open(argv[0], 0)) < 0) { 146 perror(argv[0]); 147 exit(1); 148 } 149 argc--,argv++; 150 sflg++; 151 break; 152 153 case 'f': 154 fflg++; 155 break; 156 157 case 'D': 158 Dflg++; 159 break; 160 161 case 'd': 162 dflg++; 163 break; 164 165 case 'u': 166 uflg++; 167 break; 168 169 default: 170 goto usage; 171 } 172 } 173 if (argc < 1) { 174 usage: 175 fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 176 exit(1); 177 } 178 close(0); 179 if ((fcore = open(argv[0], 0)) < 0) { 180 perror(argv[0]); 181 exit(1); 182 } 183 nlist(argc > 1 ? argv[1] : "/vmunix", nl); 184 if (nl[0].n_value == 0) { 185 fprintf(stderr, "%s: bad namelist\n", 186 argc > 1 ? argv[1] : "/vmunix"); 187 exit(1); 188 } 189 for (np = nl; np->n_name[0]; np++) 190 vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 191 usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 192 Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 193 firstfree = get(nl[X_FIRSTFREE].n_value); 194 maxfree = get(nl[X_MAXFREE].n_value); 195 freemem = get(nl[X_FREEMEM].n_value); 196 paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 197 if (paginfo == NULL) { 198 fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 199 exit(1); 200 } 201 vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 202 usrpt, Usrptma, firstfree, maxfree, freemem); 203 { 204 lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 205 read(fcore, (char *)&aproc, sizeof aproc); 206 lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0); 207 read(fcore, (char *)&nproc, sizeof nproc); 208 printf("%d procs\n", nproc); 209 proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 210 lseek(fcore, (long)clear(aproc), 0); 211 if (read(fcore, (char *)proc, nproc * sizeof (struct proc)) 212 != nproc * sizeof (struct proc)) { 213 perror("proc read"); 214 exit(1); 215 } 216 } 217 { 218 lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 219 read(fcore, (char *)&atext, sizeof atext); 220 lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0); 221 read(fcore, (char *)&ntext, sizeof ntext); 222 printf("%d texts\n", ntext); 223 text = (struct text *)calloc(ntext, sizeof (struct text)); 224 lseek(fcore, (long)clear(atext), 0); 225 if (read(fcore, (char *)text, ntext * sizeof (struct text)) 226 != ntext * sizeof (struct text)) { 227 perror("text read"); 228 exit(1); 229 } 230 } 231 i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 232 ecmx = i / sizeof (struct cmap); 233 cmap = (struct cmap *)calloc(i, 1); 234 if (cmap == NULL) { 235 fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 236 exit(1); 237 } 238 lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 239 if (read(fcore, (char *)cmap, i) != i) { 240 perror("cmap read"); 241 exit(1); 242 } 243 { struct mapent *aswapmap; 244 lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 245 read(fcore, (char *)&aswapmap, sizeof aswapmap); 246 lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0); 247 read(fcore, (char *)&nswapmap, sizeof nswapmap); 248 nswapmap--; 249 printf("%d swapmap entries\n", nswapmap); 250 swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent)); 251 dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks)); 252 lseek(fcore, (long)clear(aswapmap+1), 0); 253 if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent)) 254 != nswapmap * sizeof (struct mapent)) { 255 perror("swapmap read"); 256 exit(1); 257 } 258 } 259 for (p = &proc[1]; p < proc+nproc; p++) { 260 p->p_p0br = (struct pte *)clear(p->p_p0br); 261 p->p_addr = (struct pte *)clear(p->p_addr); 262 if (p->p_stat == 0) 263 continue; 264 printf("proc %d ", p->p_pid); 265 if (p->p_stat == SZOMB) { 266 printf("zombie\n"); 267 continue; 268 } 269 if (p->p_flag & SLOAD) { 270 printf("loaded, p0br %x, ", p->p_p0br); 271 printf("%d pages of page tables:", p->p_szpt); 272 a = btokmx(p->p_p0br); 273 for (i = 0; i < p->p_szpt; i++) { 274 w = get(&Usrptma[a + i]); 275 printf(" %x", w & PG_PFNUM); 276 } 277 printf("\n"); 278 for(i = 0; i < p->p_szpt; i++) { 279 w = get(&Usrptma[a + i]); 280 if (getpt(w, i)) 281 count(p, (struct pte *)&w, ZPAGET); 282 } 283 } else { 284 /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 285 i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 286 printf("swapped, swaddr %x\n", p->p_swaddr); 287 duse(p->p_swaddr, clrnd(ctod(UPAGES)), DUDOT, p - proc); 288 duse(p->p_swaddr + ctod(UPAGES), 289 clrnd(i - p->p_tsize / NPTEPG), DPAGET, p - proc); 290 /* i, DPAGET, p - proc); */ 291 } 292 p->p_p0br = (struct pte *)p0br; 293 p->p_addr = uaddr(p); 294 p->p_textp = &text[p->p_textp - atext]; 295 if (p->p_pid == 2) 296 continue; 297 if (getu(p)) 298 continue; 299 u.u_procp = p; 300 pdmap(); 301 if ((p->p_flag & SLOAD) == 0) 302 continue; 303 pid = p->p_pid; 304 for (i = 0; i < p->p_tsize; i++) { 305 pte = tptopte(p, i); 306 if (pte->pg_fod || pte->pg_pfnum == 0) 307 continue; 308 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 309 count(p, pte, ZINTRAN); 310 else 311 count(p, pte, ZTEXT); 312 } 313 vprintf("\n"); 314 for (i = 0; i < p->p_dsize; i++) { 315 pte = dptopte(p, i); 316 if (pte->pg_fod || pte->pg_pfnum == 0) 317 continue; 318 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 319 count(p, pte, ZINTRAN); 320 else 321 count(p, pte, ZDATA); 322 } 323 vprintf("\n"); 324 for (i = 0; i < p->p_ssize; i++) { 325 pte = sptopte(p, i); 326 if (pte->pg_fod || pte->pg_pfnum == 0) 327 continue; 328 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 329 count(p, pte, ZINTRAN); 330 else 331 count(p, pte, ZSTACK); 332 } 333 vprintf("\n"); 334 for (i = 0; i < UPAGES; i++) 335 count(p, &p->p_addr[i], ZUDOT); 336 vprintf("\n"); 337 vprintf("\n"); 338 } 339 for (xp = &text[0]; xp < text+ntext; xp++) 340 if (xp->x_iptr) { 341 for (i = 0; i < xp->x_size; i += DMTEXT) 342 duse(xp->x_daddr[i], 343 (xp->x_size - i) > DMTEXT 344 ? DMTEXT : xp->x_size - i, 345 DTEXT, xp - text); 346 if (xp->x_flag & XPAGI) 347 duse(xp->x_ptdaddr, clrnd(ctopt(xp->x_size)), 348 DTEXT, xp - text); 349 } 350 dmcheck(); 351 fixfree(); 352 summary(); 353 exit(0); 354 } 355 356 pdmap() 357 { 358 register struct text *xp; 359 360 if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 361 return; 362 if (Dflg) 363 printf("disk for pid %d", u.u_procp->p_pid); 364 if ((xp = u.u_procp->p_textp) && Dflg) 365 ptdmap(xp->x_daddr, xp->x_size); 366 pdmseg("data", &u.u_dmap, DDATA); 367 pdmseg("stack", &u.u_smap, DSTACK); 368 if (Dflg) 369 printf("\n"); 370 } 371 372 ptdmap(dp, size) 373 register daddr_t *dp; 374 int size; 375 { 376 register int i; 377 int rem; 378 379 if (Dflg) 380 printf(" text:"); 381 for (i = 0, rem = size; rem > 0; i++) { 382 if (Dflg) 383 printf(" %x<%x>", dp[i], rem < DMTEXT ? rem : DMTEXT); 384 rem -= rem < DMTEXT ? rem : DMTEXT; 385 } 386 } 387 388 pdmseg(cp, dmp, type) 389 char *cp; 390 struct dmap *dmp; 391 { 392 register int i; 393 int b, rem; 394 395 if (Dflg) 396 printf(", %s:", cp); 397 b = DMMIN; 398 for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 399 if (Dflg) 400 printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 401 duse(dmp->dm_map[i], b, type, u.u_procp - proc); 402 rem -= b; 403 if (b < DMMAX) 404 b *= 2; 405 } 406 } 407 408 duse(first, size, type, index) 409 { 410 register struct dblks *dp; 411 412 if (fswap == -1) 413 return; 414 dp = &dblks[ndblks]; 415 if (++ndblks > 2*nswapmap) { 416 fprintf(stderr, "too many disk blocks\n"); 417 exit(1); 418 } 419 dp->d_first = first; 420 dp->d_size = size; 421 dp->d_type = type; 422 dp->d_index = index; 423 } 424 425 dsort(d, e) 426 register struct dblks *d, *e; 427 { 428 429 return (e->d_first - d->d_first); 430 } 431 432 dmcheck() 433 { 434 register struct mapent *smp; 435 register struct dblks *d, *e; 436 437 for (smp = swapmap; smp->m_size; smp++) 438 duse(smp->m_addr, smp->m_size, DFREE, 0); 439 duse(CLSIZE, DMTEXT - CLSIZE, DFREE, 0); 440 qsort(dblks, ndblks, sizeof (struct dblks), dsort); 441 d = &dblks[ndblks - 1]; 442 if (d->d_first > 1) 443 printf("lost swap map: start %x size %x\n", 1, d->d_first); 444 for (; d > dblks; d--) { 445 if (dflg) 446 dprint(d); 447 e = d - 1; 448 if (d->d_first + d->d_size > e->d_first) { 449 printf("overlap in swap mappings:\n"); 450 dprint(d); 451 dprint(e); 452 } else if (d->d_first + d->d_size < e->d_first) { 453 printf("lost swap map: start %x size %x\n", 454 d->d_first + d->d_size, 455 e->d_first - (d->d_first + d->d_size)); 456 } 457 } 458 if (dflg) 459 dprint(dblks); 460 if (sflg) 461 printf("swap space ends at %x\n", d->d_first + d->d_size); 462 } 463 464 char *dnames[] = { 465 "DFREE", 466 "DDATA", 467 "DSTACK", 468 "DTEXT", 469 "DUDOT", 470 "DPAGET", 471 }; 472 473 dprint(d) 474 register struct dblks *d; 475 { 476 477 printf("at %4x size %4x type %s", d->d_first, d->d_size, 478 dnames[d->d_type]); 479 switch (d->d_type) { 480 481 case DSTACK: 482 case DDATA: 483 printf(" pid %d", proc[d->d_index].p_pid); 484 break; 485 } 486 printf("\n"); 487 } 488 489 getpt(x, i) 490 int x, i; 491 { 492 493 lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 494 if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 495 perror("read"); 496 fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 497 return (0); 498 } 499 return (1); 500 } 501 502 checkpg(p, pte, type) 503 register struct pte *pte; 504 register struct proc *p; 505 int type; 506 { 507 char corepg[NBPG], swapg[NBPG]; 508 register int i, count, dblock; 509 register int pfnum = pte->pg_pfnum; 510 511 if (type == ZPAGET || type == ZUDOT) 512 return (0); 513 lseek(fcore, (long)(NBPG * pfnum), 0); 514 if (read(fcore, corepg, NBPG) != NBPG){ 515 perror("read"); 516 fprintf(stderr, "Error reading core page %x\n", pfnum); 517 return (0); 518 } 519 switch (type) { 520 521 case ZDATA: 522 if (ptetodp(p, pte) >= u.u_dmap.dm_size) 523 return (0); 524 break; 525 526 case ZTEXT: 527 break; 528 529 case ZSTACK: 530 if (ptetosp(p, pte) >= u.u_smap.dm_size) 531 return (0); 532 break; 533 534 default: 535 return(0); 536 break; 537 } 538 dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 539 vprintf(" %x", dblock); 540 if (pte->pg_fod || pte->pg_pfnum == 0) 541 return (0); 542 if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 543 return (0); 544 lseek(fswap, (long)(NBPG * dblock), 0); 545 if (read(fswap, swapg, NBPG) != NBPG) { 546 fprintf(stderr,"swap page %x: ", dblock); 547 perror("read"); 548 } 549 count = 0; 550 for (i = 0; i < NBPG; i++) 551 if (corepg[i] != swapg[i]) 552 count++; 553 if (count == 0) 554 vprintf("\tsame"); 555 return (count); 556 } 557 558 getu(p) 559 register struct proc *p; 560 { 561 int i, w, cc, errs = 0; 562 563 if (uflg && (p->p_flag & SLOAD)) 564 printf("pid %d u. pages:", p->p_pid); 565 for (i = 0; i < UPAGES; i++) { 566 if (p->p_flag & SLOAD) { 567 if (uflg) 568 printf(" %x", p->p_addr[i].pg_pfnum); 569 lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 570 if (read(fcore, u_area.buf[i], NBPG) != NBPG) 571 perror("core u. read"), errs++; 572 } else if (fswap >= 0) { 573 lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 574 if (read(fswap, u_area.buf[i], NBPG) != NBPG) 575 perror("swap u. read"), errs++; 576 } 577 } 578 if (uflg && (p->p_flag & SLOAD)) 579 printf("\n"); 580 return (errs); 581 } 582 583 char *typepg[] = { 584 "lost", 585 "data", 586 "stack", 587 "udot", 588 "paget", 589 "text", 590 "free", 591 "intransit", 592 }; 593 594 count(p, pte, type) 595 struct proc *p; 596 register struct pte *pte; 597 int type; 598 { 599 register int pfnum = pte->pg_pfnum; 600 register struct paginfo *zp = &paginfo[pfnum]; 601 int ndif; 602 #define zprintf if (type==ZINTRAN || vflg) printf 603 604 if (type == ZINTRAN && pfnum == 0) 605 return; 606 zprintf("page %x %s", pfnum, typepg[type]); 607 if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 608 zprintf("\n"); 609 } else { 610 if (vflg == 0 && type != ZINTRAN) 611 printf("page %x %s,", pfnum, typepg[type]); 612 printf(" %d bytes differ\n",ndif); 613 } 614 if (pfnum < firstfree || pfnum > maxfree) { 615 printf("page number out of range:\n"); 616 printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 617 return; 618 } 619 if (bad(zp, type)) { 620 printf("dup page pte %x", *(int *)pte); 621 dumpcm("", pte->pg_pfnum); 622 dump(zp); 623 printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 624 return; 625 } 626 zp->z_type = type; 627 zp->z_count++; 628 zp->z_pid = pid; 629 zp->z_pte = *pte; 630 } 631 632 bad(zp, type) 633 struct paginfo *zp; 634 { 635 if (type == ZTEXT) { 636 if (zp->z_type != 0 && zp->z_type != ZTEXT) 637 return (1); 638 return (0); 639 } 640 return (zp->z_count); 641 } 642 643 dump(zp) 644 struct paginfo *zp; 645 { 646 647 printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 648 } 649 650 summary() 651 { 652 register int i; 653 register struct paginfo *zp; 654 register int pfnum; 655 656 for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 657 zp = &paginfo[i]; 658 if (zp->z_type == ZLOST) 659 dumpcm("lost", i); 660 pfnum = pgtocm(i); 661 if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 662 dumpcm("locked", i); 663 if (mflg) 664 dumpcm("mem", i); 665 } 666 } 667 668 char *tynames[] = { 669 "sys", 670 "text", 671 "data", 672 "stack" 673 }; 674 dumpcm(cp, pg) 675 char *cp; 676 int pg; 677 { 678 int pslot; 679 int cm; 680 register struct cmap *c; 681 682 cm = pgtocm(pg); 683 printf("cm %x %s page %x ", cm, cp, pg); 684 c = &cmap[cm]; 685 printf("\t[%x, %x", c->c_page, c->c_ndx); 686 if (c->c_type == CSYS) 687 goto skip; 688 if (c->c_type != CTEXT) { 689 if (c->c_ndx >= nproc) { 690 printf(" [text c->c_ndx %d?]", c->c_ndx); 691 goto skip; 692 } 693 printf(" (=pid %d)", proc[c->c_ndx].p_pid); 694 } else { 695 if (c->c_ndx >= ntext) { 696 printf(" [text c->c_ndx %d?]", c->c_ndx); 697 goto skip; 698 } 699 pslot= (text[c->c_ndx].x_caddr - aproc); 700 printf(" (=pid"); 701 for(;;) { 702 printf(" %d", proc[pslot].p_pid); 703 if (proc[pslot].p_xlink == 0) 704 break; 705 pslot= (proc[pslot].p_xlink - aproc); 706 } 707 printf(")"); 708 } 709 skip: 710 printf("] "); 711 printf(tynames[c->c_type]); 712 if (c->c_free) 713 printf(" free"); 714 if (c->c_gone) 715 printf(" gone"); 716 if (c->c_lock) 717 printf(" lock"); 718 if (c->c_want) 719 printf(" want"); 720 if (c->c_intrans) 721 printf(" intrans"); 722 if (c->c_blkno) 723 printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 724 if (c->c_hlink) { 725 printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 726 if (c->c_hlink > ecmx) 727 printf(" <<<"); 728 } 729 printf("\n"); 730 } 731 732 fixfree() 733 { 734 register int i, next, prev; 735 736 next = CMHEAD; 737 for (i=freemem/CLSIZE; --i >=0; ) { 738 prev = next; 739 next = cmap[next].c_next; 740 if (cmap[next].c_free == 0) { 741 printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 742 dumpcm("bad free link in", cmtopg(prev)); 743 dumpcm("to non free block", cmtopg(next)); 744 } 745 if (cmtopg(next) > maxfree) { 746 printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 747 dumpcm("bad link in", cmtopg(prev)); 748 } 749 paginfo[cmtopg(next)].z_type = ZFREE; 750 if (fflg) 751 dumpcm("free", cmtopg(next)); 752 paginfo[cmtopg(next)+1].z_type = ZFREE; 753 if (fflg) 754 dumpcm("free", cmtopg(next)+1); 755 } 756 } 757 758 get(loc) 759 unsigned loc; 760 { 761 int x; 762 763 lseek(fcore, (long)clear(loc), 0); 764 if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 765 perror("read"); 766 fprintf(stderr, "get failed on %x\n", clear(loc)); 767 return (0); 768 } 769 return (x); 770 } 771 /* 772 * Convert a virtual page number 773 * to its corresponding disk block number. 774 * Used in pagein/pageout to initiate single page transfers. 775 */ 776 vtod(p, v, dmap, smap) 777 register struct proc *p; 778 register struct dmap *dmap, *smap; 779 { 780 struct dblock db; 781 782 if (v < p->p_tsize) 783 return(p->p_textp->x_daddr[v / DMTEXT] + v % DMTEXT); 784 if (isassv(p, v)) 785 vstodb(vtosp(p, v), 1, smap, &db, 1); 786 else 787 vstodb(vtodp(p, v), 1, dmap, &db, 0); 788 return (db.db_base); 789 } 790 791 /* 792 * Convert a pte pointer to 793 * a virtual page number. 794 */ 795 ptetov(p, pte) 796 register struct proc *p; 797 register struct pte *pte; 798 { 799 800 if (isatpte(p, pte)) 801 return (tptov(p, ptetotp(p, pte))); 802 else if (isadpte(p, pte)) 803 return (dptov(p, ptetodp(p, pte))); 804 else 805 return (sptov(p, ptetosp(p, pte))); 806 } 807 808 /* 809 * Given a base/size pair in virtual swap area, 810 * return a physical base/size pair which is the 811 * (largest) initial, physically contiguous block. 812 */ 813 vstodb(vsbase, vssize, dmp, dbp, rev) 814 register int vsbase; 815 int vssize; 816 register struct dmap *dmp; 817 register struct dblock *dbp; 818 { 819 register int blk = DMMIN; 820 register swblk_t *ip = dmp->dm_map; 821 822 if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 823 panic("vstodb"); 824 while (vsbase >= blk) { 825 vsbase -= blk; 826 if (blk < DMMAX) 827 blk *= 2; 828 ip++; 829 } 830 dbp->db_size = min(vssize, blk - vsbase); 831 dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 832 } 833 834 panic(cp) 835 char *cp; 836 { 837 printf("panic!: %s\n", cp); 838 } 839 840 min(a, b) 841 { 842 return (a < b ? a : b); 843 } 844