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