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.2 (Berkeley) 5/14/86"; 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(btoc(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: }