1*12702Ssam #ifndef lint 2*12702Ssam static char *sccsid = "@(#)analyze.c 4.7 (Berkeley) 05/24/83"; 3*12702Ssam #endif 4*12702Ssam 5*12702Ssam /* 6*12702Ssam * Analyze - analyze a core (and optional paging area) saved from 7*12702Ssam * a virtual Unix system crash. 8*12702Ssam */ 9950Sbill #include <stdio.h> 10950Sbill #include <sys/param.h> 11950Sbill #include <sys/dir.h> 129891Ssam #include <machine/pte.h> 13950Sbill #include <nlist.h> 14950Sbill #include <sys/map.h> 15950Sbill #include <sys/user.h> 16950Sbill #include <sys/proc.h> 17950Sbill #include <sys/text.h> 18950Sbill #include <sys/cmap.h> 19950Sbill #include <sys/vm.h> 20950Sbill 21950Sbill int Dflg; 22950Sbill int dflg; 23950Sbill int vflg; 24950Sbill int mflg; 25950Sbill int fflg; 26950Sbill int sflg; 272824Swnj int uflg; 28950Sbill 29950Sbill /* use vprintf with care; it plays havoc with ``else's'' */ 30950Sbill #define vprintf if (vflg) printf 31950Sbill 3210809Ssam #ifdef vax 33950Sbill #define clear(x) ((int)x & 0x7fffffff) 3410809Ssam #else 3510809Ssam #define clear(x) ((int)x) 3610809Ssam #endif 37950Sbill 383795Sroot struct proc *proc, *aproc; 393526Sroot int nproc; 403795Sroot struct text *text, *atext; 413526Sroot int ntext; 423526Sroot struct mapent *swapmap; 433526Sroot int nswapmap; 44*12702Ssam int dmmin, dmmax, dmtext; 45950Sbill struct cmap *cmap; 462824Swnj int ecmx; 47950Sbill struct pte *usrpt; 48950Sbill struct pte *Usrptma; 49950Sbill int firstfree; 50950Sbill int maxfree; 51950Sbill int freemem; 52950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 53950Sbill int pid; 54950Sbill 55950Sbill struct paginfo { 56950Sbill char z_type; 57950Sbill char z_count; 58950Sbill short z_pid; 59950Sbill struct pte z_pte; 60950Sbill } *paginfo; 61950Sbill #define ZLOST 0 62950Sbill #define ZDATA 1 63950Sbill #define ZSTACK 2 64950Sbill #define ZUDOT 3 65950Sbill #define ZPAGET 4 66950Sbill #define ZTEXT 5 67950Sbill #define ZFREE 6 68950Sbill #define ZINTRAN 7 69950Sbill 70950Sbill struct dblks { 71950Sbill short d_first; 72950Sbill short d_size; 73950Sbill char d_type; 74950Sbill char d_index; 753526Sroot } *dblks; 76950Sbill int ndblks; 77950Sbill 78950Sbill #define DFREE 0 79950Sbill #define DDATA 1 80950Sbill #define DSTACK 2 81950Sbill #define DTEXT 3 82950Sbill #define DUDOT 4 83950Sbill #define DPAGET 5 84950Sbill 85950Sbill union { 8610809Ssam char buf[UPAGES][NBPG]; 87950Sbill struct user U; 88950Sbill } u_area; 89950Sbill #define u u_area.U 90950Sbill 91950Sbill int fcore = -1; 92950Sbill int fswap = -1; 93950Sbill 94950Sbill struct nlist nl[] = { 95950Sbill #define X_PROC 0 96950Sbill { "_proc" }, 97950Sbill #define X_USRPT 1 98950Sbill { "_usrpt" }, 99950Sbill #define X_PTMA 2 1002824Swnj { "_Usrptmap" }, 101950Sbill #define X_FIRSTFREE 3 1022824Swnj { "_firstfree" }, 103950Sbill #define X_MAXFREE 4 104950Sbill { "_maxfree" }, 105950Sbill #define X_TEXT 5 106950Sbill { "_text" }, 107950Sbill #define X_FREEMEM 6 108950Sbill { "_freemem" }, 109950Sbill #define X_CMAP 7 110950Sbill { "_cmap" }, 111950Sbill #define X_ECMAP 8 112950Sbill { "_ecmap" }, 113950Sbill #define X_SWAPMAP 9 114950Sbill { "_swapmap" }, 1153526Sroot #define X_NPROC 10 1163526Sroot { "_nproc" }, 1173526Sroot #define X_NTEXT 11 1183526Sroot { "_ntext" }, 1193526Sroot #define X_NSWAPMAP 12 1203526Sroot { "_nswapmap" }, 121*12702Ssam #define X_DMMIN 13 122*12702Ssam { "_dmmin" }, 123*12702Ssam #define X_DMMAX 14 124*12702Ssam { "_dmmax" }, 125*12702Ssam #define X_DMTEXT 15 126*12702Ssam { "_dmtext" }, 127*12702Ssam { "" } 128950Sbill }; 129950Sbill 130950Sbill main(argc, argv) 131950Sbill int argc; 132950Sbill char **argv; 133950Sbill { 134950Sbill register struct nlist *np; 135950Sbill register struct proc *p; 136950Sbill register struct text *xp; 137950Sbill register struct pte *pte; 138950Sbill register int i; 139950Sbill int w, a; 140950Sbill 14110809Ssam #ifdef DEBUG 14210809Ssam setbuf(stdout, NULL); 14310809Ssam #endif 144950Sbill argc--, argv++; 145950Sbill while (argc > 0 && argv[0][0] == '-') { 146950Sbill register char *cp = *argv++; 147950Sbill argc--; 148950Sbill while (*++cp) switch (*cp) { 149950Sbill 150950Sbill case 'm': 151950Sbill mflg++; 152950Sbill break; 153950Sbill 154950Sbill case 'v': 155950Sbill vflg++; 156950Sbill break; 157950Sbill 158950Sbill case 's': 159950Sbill if (argc < 2) 160950Sbill goto usage; 161950Sbill if ((fswap = open(argv[0], 0)) < 0) { 162950Sbill perror(argv[0]); 163950Sbill exit(1); 164950Sbill } 165950Sbill argc--,argv++; 166950Sbill sflg++; 167950Sbill break; 168950Sbill 169950Sbill case 'f': 170950Sbill fflg++; 171950Sbill break; 172950Sbill 173950Sbill case 'D': 174950Sbill Dflg++; 175950Sbill break; 176950Sbill 177950Sbill case 'd': 178950Sbill dflg++; 179950Sbill break; 180950Sbill 1812824Swnj case 'u': 1822824Swnj uflg++; 1832824Swnj break; 1842824Swnj 185950Sbill default: 186950Sbill goto usage; 187950Sbill } 188950Sbill } 189950Sbill if (argc < 1) { 190950Sbill usage: 191950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 192950Sbill exit(1); 193950Sbill } 194950Sbill close(0); 195950Sbill if ((fcore = open(argv[0], 0)) < 0) { 196950Sbill perror(argv[0]); 197950Sbill exit(1); 198950Sbill } 199950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 200950Sbill if (nl[0].n_value == 0) { 201950Sbill fprintf(stderr, "%s: bad namelist\n", 202950Sbill argc > 1 ? argv[1] : "/vmunix"); 203950Sbill exit(1); 204950Sbill } 205*12702Ssam for (np = nl; np->n_name && *np->n_name; np++) 206950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 207950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 208950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 209950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 210950Sbill maxfree = get(nl[X_MAXFREE].n_value); 211950Sbill freemem = get(nl[X_FREEMEM].n_value); 212*12702Ssam dmmin = get(nl[X_DMMIN]); 213*12702Ssam dmmax = get(nl[X_DMMAX]); 214*12702Ssam dmtext = get(nl[X_DMTEXT]); 215950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 216950Sbill if (paginfo == NULL) { 217950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 218950Sbill exit(1); 219950Sbill } 220950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 221950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 2223795Sroot { 2233526Sroot lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 2243526Sroot read(fcore, (char *)&aproc, sizeof aproc); 2253526Sroot lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0); 2263526Sroot read(fcore, (char *)&nproc, sizeof nproc); 2273526Sroot printf("%d procs\n", nproc); 2283526Sroot proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 2293526Sroot lseek(fcore, (long)clear(aproc), 0); 2303526Sroot if (read(fcore, (char *)proc, nproc * sizeof (struct proc)) 2313526Sroot != nproc * sizeof (struct proc)) { 232950Sbill perror("proc read"); 233950Sbill exit(1); 2343526Sroot } 235950Sbill } 2363795Sroot { 2373526Sroot lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 2383526Sroot read(fcore, (char *)&atext, sizeof atext); 2393526Sroot lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0); 2403526Sroot read(fcore, (char *)&ntext, sizeof ntext); 2413526Sroot printf("%d texts\n", ntext); 2423526Sroot text = (struct text *)calloc(ntext, sizeof (struct text)); 2433526Sroot lseek(fcore, (long)clear(atext), 0); 2443526Sroot if (read(fcore, (char *)text, ntext * sizeof (struct text)) 2453526Sroot != ntext * sizeof (struct text)) { 246950Sbill perror("text read"); 247950Sbill exit(1); 2483526Sroot } 249950Sbill } 250950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 2512824Swnj ecmx = i / sizeof (struct cmap); 252950Sbill cmap = (struct cmap *)calloc(i, 1); 253950Sbill if (cmap == NULL) { 254950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 255950Sbill exit(1); 256950Sbill } 257950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 258950Sbill if (read(fcore, (char *)cmap, i) != i) { 259950Sbill perror("cmap read"); 260950Sbill exit(1); 261950Sbill } 2623526Sroot { struct mapent *aswapmap; 2633526Sroot lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 2643526Sroot read(fcore, (char *)&aswapmap, sizeof aswapmap); 2653526Sroot lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0); 2663526Sroot read(fcore, (char *)&nswapmap, sizeof nswapmap); 2673526Sroot nswapmap--; 2683526Sroot printf("%d swapmap entries\n", nswapmap); 2693526Sroot swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent)); 2703526Sroot dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks)); 2713526Sroot lseek(fcore, (long)clear(aswapmap+1), 0); 2723526Sroot if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent)) 2733526Sroot != nswapmap * sizeof (struct mapent)) { 274950Sbill perror("swapmap read"); 275950Sbill exit(1); 2763526Sroot } 277950Sbill } 2783526Sroot for (p = &proc[1]; p < proc+nproc; p++) { 279950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 280950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 281950Sbill if (p->p_stat == 0) 282950Sbill continue; 283950Sbill printf("proc %d ", p->p_pid); 284950Sbill if (p->p_stat == SZOMB) { 285950Sbill printf("zombie\n"); 286950Sbill continue; 287950Sbill } 288950Sbill if (p->p_flag & SLOAD) { 289950Sbill printf("loaded, p0br %x, ", p->p_p0br); 290950Sbill printf("%d pages of page tables:", p->p_szpt); 291950Sbill a = btokmx(p->p_p0br); 292950Sbill for (i = 0; i < p->p_szpt; i++) { 293950Sbill w = get(&Usrptma[a + i]); 294950Sbill printf(" %x", w & PG_PFNUM); 295950Sbill } 296950Sbill printf("\n"); 297950Sbill for(i = 0; i < p->p_szpt; i++) { 298950Sbill w = get(&Usrptma[a + i]); 299950Sbill if (getpt(w, i)) 300950Sbill count(p, (struct pte *)&w, ZPAGET); 301950Sbill } 302950Sbill } else { 303950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 304950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 305950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 30610809Ssam duse(p->p_swaddr, ctod(clrnd(UPAGES)), DUDOT, p - proc); 307950Sbill duse(p->p_swaddr + ctod(UPAGES), 30810809Ssam ctod(clrnd(i - p->p_tsize / NPTEPG)), 30910809Ssam DPAGET, p - proc); 310950Sbill /* i, DPAGET, p - proc); */ 311950Sbill } 312950Sbill p->p_p0br = (struct pte *)p0br; 313950Sbill p->p_addr = uaddr(p); 31410809Ssam if (p->p_textp) 31510809Ssam p->p_textp = &text[p->p_textp - atext]; 316950Sbill if (p->p_pid == 2) 317950Sbill continue; 318950Sbill if (getu(p)) 319950Sbill continue; 320950Sbill u.u_procp = p; 321950Sbill pdmap(); 322950Sbill if ((p->p_flag & SLOAD) == 0) 323950Sbill continue; 324950Sbill pid = p->p_pid; 325950Sbill for (i = 0; i < p->p_tsize; i++) { 326950Sbill pte = tptopte(p, i); 327950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 328950Sbill continue; 329950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 330950Sbill count(p, pte, ZINTRAN); 331950Sbill else 332950Sbill count(p, pte, ZTEXT); 333950Sbill } 334950Sbill vprintf("\n"); 335950Sbill for (i = 0; i < p->p_dsize; i++) { 336950Sbill pte = dptopte(p, i); 337950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 338950Sbill continue; 339950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 340950Sbill count(p, pte, ZINTRAN); 341950Sbill else 342950Sbill count(p, pte, ZDATA); 343950Sbill } 344950Sbill vprintf("\n"); 345950Sbill for (i = 0; i < p->p_ssize; i++) { 346950Sbill pte = sptopte(p, i); 347950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 348950Sbill continue; 349950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 350950Sbill count(p, pte, ZINTRAN); 351950Sbill else 352950Sbill count(p, pte, ZSTACK); 353950Sbill } 354950Sbill vprintf("\n"); 355950Sbill for (i = 0; i < UPAGES; i++) 356950Sbill count(p, &p->p_addr[i], ZUDOT); 357950Sbill vprintf("\n"); 358950Sbill vprintf("\n"); 359950Sbill } 3603526Sroot for (xp = &text[0]; xp < text+ntext; xp++) 361950Sbill if (xp->x_iptr) { 36210809Ssam int size = ctod(xp->x_size); 36310809Ssam 364*12702Ssam for (i = 0; i < size; i += dmtext) 365950Sbill duse(xp->x_daddr[i], 366*12702Ssam (size - i) > dmtext 367*12702Ssam ? dmtext : size - i, 368950Sbill DTEXT, xp - text); 369950Sbill if (xp->x_flag & XPAGI) 37010809Ssam duse(xp->x_ptdaddr, 37110809Ssam ctod(clrnd(ctopt(xp->x_size))), 372950Sbill DTEXT, xp - text); 373950Sbill } 374950Sbill dmcheck(); 375950Sbill fixfree(); 376950Sbill summary(); 377950Sbill exit(0); 378950Sbill } 379950Sbill 380950Sbill pdmap() 381950Sbill { 382950Sbill register struct text *xp; 383950Sbill 384950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 385950Sbill return; 386950Sbill if (Dflg) 387950Sbill printf("disk for pid %d", u.u_procp->p_pid); 388950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 389950Sbill ptdmap(xp->x_daddr, xp->x_size); 390950Sbill pdmseg("data", &u.u_dmap, DDATA); 391950Sbill pdmseg("stack", &u.u_smap, DSTACK); 392950Sbill if (Dflg) 393950Sbill printf("\n"); 394950Sbill } 395950Sbill 396950Sbill ptdmap(dp, size) 397950Sbill register daddr_t *dp; 398950Sbill int size; 399950Sbill { 400950Sbill register int i; 401950Sbill int rem; 402950Sbill 403950Sbill if (Dflg) 404950Sbill printf(" text:"); 405950Sbill for (i = 0, rem = size; rem > 0; i++) { 406950Sbill if (Dflg) 407*12702Ssam printf(" %x<%x>", dp[i], rem < dmtext ? rem : dmtext); 408*12702Ssam rem -= rem < dmtext ? rem : dmtext; 409950Sbill } 410950Sbill } 411950Sbill 412950Sbill pdmseg(cp, dmp, type) 413950Sbill char *cp; 414950Sbill struct dmap *dmp; 415950Sbill { 416950Sbill register int i; 417950Sbill int b, rem; 418950Sbill 419950Sbill if (Dflg) 420950Sbill printf(", %s:", cp); 421*12702Ssam b = dmmin; 422950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 423950Sbill if (Dflg) 424950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 425950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 426950Sbill rem -= b; 427*12702Ssam if (b < dmmax) 428950Sbill b *= 2; 429950Sbill } 430950Sbill } 431950Sbill 432950Sbill duse(first, size, type, index) 433950Sbill { 434950Sbill register struct dblks *dp; 435950Sbill 436950Sbill if (fswap == -1) 437950Sbill return; 438950Sbill dp = &dblks[ndblks]; 4393526Sroot if (++ndblks > 2*nswapmap) { 4403526Sroot fprintf(stderr, "too many disk blocks\n"); 441950Sbill exit(1); 442950Sbill } 443950Sbill dp->d_first = first; 444950Sbill dp->d_size = size; 445950Sbill dp->d_type = type; 446950Sbill dp->d_index = index; 447950Sbill } 448950Sbill 449950Sbill dsort(d, e) 450950Sbill register struct dblks *d, *e; 451950Sbill { 452950Sbill 453950Sbill return (e->d_first - d->d_first); 454950Sbill } 455950Sbill 456950Sbill dmcheck() 457950Sbill { 4583526Sroot register struct mapent *smp; 459950Sbill register struct dblks *d, *e; 460950Sbill 461950Sbill for (smp = swapmap; smp->m_size; smp++) 462950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 463*12702Ssam duse(ctod(CLSIZE), dmtext - ctod(CLSIZE), DFREE, 0); 464950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 465950Sbill d = &dblks[ndblks - 1]; 466950Sbill if (d->d_first > 1) 467950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 468950Sbill for (; d > dblks; d--) { 469950Sbill if (dflg) 470950Sbill dprint(d); 471950Sbill e = d - 1; 472950Sbill if (d->d_first + d->d_size > e->d_first) { 473950Sbill printf("overlap in swap mappings:\n"); 474950Sbill dprint(d); 475950Sbill dprint(e); 476950Sbill } else if (d->d_first + d->d_size < e->d_first) { 477950Sbill printf("lost swap map: start %x size %x\n", 478950Sbill d->d_first + d->d_size, 479950Sbill e->d_first - (d->d_first + d->d_size)); 480950Sbill } 481950Sbill } 482950Sbill if (dflg) 483950Sbill dprint(dblks); 484950Sbill if (sflg) 485950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 486950Sbill } 487950Sbill 488950Sbill char *dnames[] = { 489950Sbill "DFREE", 490950Sbill "DDATA", 491950Sbill "DSTACK", 492950Sbill "DTEXT", 493950Sbill "DUDOT", 494950Sbill "DPAGET", 495950Sbill }; 496950Sbill 497950Sbill dprint(d) 498950Sbill register struct dblks *d; 499950Sbill { 500950Sbill 501950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 502950Sbill dnames[d->d_type]); 503950Sbill switch (d->d_type) { 504950Sbill 505950Sbill case DSTACK: 506950Sbill case DDATA: 507950Sbill printf(" pid %d", proc[d->d_index].p_pid); 508950Sbill break; 509950Sbill } 510950Sbill printf("\n"); 511950Sbill } 512950Sbill 513950Sbill getpt(x, i) 514950Sbill int x, i; 515950Sbill { 516950Sbill 517950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 518950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 519950Sbill perror("read"); 520950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 521950Sbill return (0); 522950Sbill } 523950Sbill return (1); 524950Sbill } 525950Sbill 526950Sbill checkpg(p, pte, type) 527950Sbill register struct pte *pte; 528950Sbill register struct proc *p; 529950Sbill int type; 530950Sbill { 531950Sbill char corepg[NBPG], swapg[NBPG]; 532950Sbill register int i, count, dblock; 533950Sbill register int pfnum = pte->pg_pfnum; 534950Sbill 535950Sbill if (type == ZPAGET || type == ZUDOT) 536950Sbill return (0); 537950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 538950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 539950Sbill perror("read"); 540950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 541950Sbill return (0); 542950Sbill } 543950Sbill switch (type) { 544950Sbill 545950Sbill case ZDATA: 546950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 547950Sbill return (0); 548950Sbill break; 549950Sbill 550950Sbill case ZTEXT: 551950Sbill break; 552950Sbill 553950Sbill case ZSTACK: 554950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 555950Sbill return (0); 556950Sbill break; 557950Sbill 558950Sbill default: 559950Sbill return(0); 560950Sbill break; 561950Sbill } 562950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 563950Sbill vprintf(" %x", dblock); 564950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 565950Sbill return (0); 566950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 567950Sbill return (0); 56810809Ssam lseek(fswap, (long)(DEV_BSIZE * dblock), 0); 569950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 570950Sbill fprintf(stderr,"swap page %x: ", dblock); 571950Sbill perror("read"); 572950Sbill } 573950Sbill count = 0; 574950Sbill for (i = 0; i < NBPG; i++) 575950Sbill if (corepg[i] != swapg[i]) 576950Sbill count++; 577950Sbill if (count == 0) 578950Sbill vprintf("\tsame"); 579950Sbill return (count); 580950Sbill } 581950Sbill 582950Sbill getu(p) 583950Sbill register struct proc *p; 584950Sbill { 585950Sbill int i, w, cc, errs = 0; 586950Sbill 5872824Swnj if (uflg && (p->p_flag & SLOAD)) 5882824Swnj printf("pid %d u. pages:", p->p_pid); 589950Sbill for (i = 0; i < UPAGES; i++) { 590950Sbill if (p->p_flag & SLOAD) { 5912824Swnj if (uflg) 5922824Swnj printf(" %x", p->p_addr[i].pg_pfnum); 593950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 594950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 595950Sbill perror("core u. read"), errs++; 596950Sbill } else if (fswap >= 0) { 597950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 598950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 599950Sbill perror("swap u. read"), errs++; 600950Sbill } 601950Sbill } 6022824Swnj if (uflg && (p->p_flag & SLOAD)) 6032824Swnj printf("\n"); 604950Sbill return (errs); 605950Sbill } 606950Sbill 607950Sbill char *typepg[] = { 608950Sbill "lost", 609950Sbill "data", 610950Sbill "stack", 611950Sbill "udot", 612950Sbill "paget", 613950Sbill "text", 614950Sbill "free", 615950Sbill "intransit", 616950Sbill }; 617950Sbill 618950Sbill count(p, pte, type) 619950Sbill struct proc *p; 620950Sbill register struct pte *pte; 621950Sbill int type; 622950Sbill { 623950Sbill register int pfnum = pte->pg_pfnum; 624950Sbill register struct paginfo *zp = &paginfo[pfnum]; 625950Sbill int ndif; 626950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 627950Sbill 628950Sbill if (type == ZINTRAN && pfnum == 0) 629950Sbill return; 630950Sbill zprintf("page %x %s", pfnum, typepg[type]); 631950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 632950Sbill zprintf("\n"); 633950Sbill } else { 634950Sbill if (vflg == 0 && type != ZINTRAN) 635950Sbill printf("page %x %s,", pfnum, typepg[type]); 636950Sbill printf(" %d bytes differ\n",ndif); 637950Sbill } 638950Sbill if (pfnum < firstfree || pfnum > maxfree) { 639950Sbill printf("page number out of range:\n"); 640950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 641950Sbill return; 642950Sbill } 643950Sbill if (bad(zp, type)) { 644950Sbill printf("dup page pte %x", *(int *)pte); 645950Sbill dumpcm("", pte->pg_pfnum); 646950Sbill dump(zp); 647950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 648950Sbill return; 649950Sbill } 650950Sbill zp->z_type = type; 651950Sbill zp->z_count++; 652950Sbill zp->z_pid = pid; 653950Sbill zp->z_pte = *pte; 654950Sbill } 655950Sbill 656950Sbill bad(zp, type) 657950Sbill struct paginfo *zp; 658950Sbill { 659950Sbill if (type == ZTEXT) { 660950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 661950Sbill return (1); 662950Sbill return (0); 663950Sbill } 664950Sbill return (zp->z_count); 665950Sbill } 666950Sbill 667950Sbill dump(zp) 668950Sbill struct paginfo *zp; 669950Sbill { 670950Sbill 671950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 672950Sbill } 673950Sbill 674950Sbill summary() 675950Sbill { 676950Sbill register int i; 677950Sbill register struct paginfo *zp; 678950Sbill register int pfnum; 679950Sbill 6802824Swnj for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 681950Sbill zp = &paginfo[i]; 682950Sbill if (zp->z_type == ZLOST) 683950Sbill dumpcm("lost", i); 684950Sbill pfnum = pgtocm(i); 685950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 686950Sbill dumpcm("locked", i); 687950Sbill if (mflg) 688950Sbill dumpcm("mem", i); 689950Sbill } 690950Sbill } 691950Sbill 692950Sbill char *tynames[] = { 693950Sbill "sys", 694950Sbill "text", 695950Sbill "data", 696950Sbill "stack" 697950Sbill }; 698950Sbill dumpcm(cp, pg) 699950Sbill char *cp; 700950Sbill int pg; 701950Sbill { 702950Sbill int pslot; 703950Sbill int cm; 704950Sbill register struct cmap *c; 705950Sbill 706950Sbill cm = pgtocm(pg); 7072824Swnj printf("cm %x %s page %x ", cm, cp, pg); 708950Sbill c = &cmap[cm]; 709950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 7103795Sroot if (c->c_type == CSYS) 7113795Sroot goto skip; 7123795Sroot if (c->c_type != CTEXT) { 7133795Sroot if (c->c_ndx >= nproc) { 7143795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7153795Sroot goto skip; 7163795Sroot } 717950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 7183795Sroot } else { 7193795Sroot if (c->c_ndx >= ntext) { 7203795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7213795Sroot goto skip; 7223795Sroot } 7233795Sroot pslot= (text[c->c_ndx].x_caddr - aproc); 724950Sbill printf(" (=pid"); 725950Sbill for(;;) { 726950Sbill printf(" %d", proc[pslot].p_pid); 727950Sbill if (proc[pslot].p_xlink == 0) 728950Sbill break; 7293795Sroot pslot= (proc[pslot].p_xlink - aproc); 730950Sbill } 731950Sbill printf(")"); 732950Sbill } 7333795Sroot skip: 734950Sbill printf("] "); 735950Sbill printf(tynames[c->c_type]); 736950Sbill if (c->c_free) 737950Sbill printf(" free"); 738950Sbill if (c->c_gone) 739950Sbill printf(" gone"); 740950Sbill if (c->c_lock) 741950Sbill printf(" lock"); 742950Sbill if (c->c_want) 743950Sbill printf(" want"); 744950Sbill if (c->c_intrans) 745950Sbill printf(" intrans"); 746950Sbill if (c->c_blkno) 747950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 7482824Swnj if (c->c_hlink) { 7492824Swnj printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 7502824Swnj if (c->c_hlink > ecmx) 7512824Swnj printf(" <<<"); 7522824Swnj } 753950Sbill printf("\n"); 754950Sbill } 755950Sbill 756950Sbill fixfree() 757950Sbill { 758950Sbill register int i, next, prev; 759950Sbill 760950Sbill next = CMHEAD; 761950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 762950Sbill prev = next; 763950Sbill next = cmap[next].c_next; 764950Sbill if (cmap[next].c_free == 0) { 765950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 766950Sbill dumpcm("bad free link in", cmtopg(prev)); 767950Sbill dumpcm("to non free block", cmtopg(next)); 768950Sbill } 769950Sbill if (cmtopg(next) > maxfree) { 770950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 771950Sbill dumpcm("bad link in", cmtopg(prev)); 772950Sbill } 773950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 774950Sbill if (fflg) 775950Sbill dumpcm("free", cmtopg(next)); 776950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 777950Sbill if (fflg) 778950Sbill dumpcm("free", cmtopg(next)+1); 779950Sbill } 780950Sbill } 781950Sbill 782950Sbill get(loc) 783950Sbill unsigned loc; 784950Sbill { 785950Sbill int x; 786950Sbill 787950Sbill lseek(fcore, (long)clear(loc), 0); 788950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 789950Sbill perror("read"); 790950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 791950Sbill return (0); 792950Sbill } 793950Sbill return (x); 794950Sbill } 795950Sbill /* 796950Sbill * Convert a virtual page number 797950Sbill * to its corresponding disk block number. 798950Sbill * Used in pagein/pageout to initiate single page transfers. 799950Sbill */ 800950Sbill vtod(p, v, dmap, smap) 801950Sbill register struct proc *p; 802950Sbill register struct dmap *dmap, *smap; 803950Sbill { 804950Sbill struct dblock db; 805950Sbill 80610809Ssam if (isatsv(p, v)) { 80710809Ssam v = ctod(vtotp(p, v)); 808*12702Ssam return(p->p_textp->x_daddr[v / dmtext] + v % dmtext); 80910809Ssam } 810950Sbill if (isassv(p, v)) 81110809Ssam vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1); 812950Sbill else 81310809Ssam vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0); 814950Sbill return (db.db_base); 815950Sbill } 816950Sbill 817950Sbill /* 818950Sbill * Convert a pte pointer to 819950Sbill * a virtual page number. 820950Sbill */ 821950Sbill ptetov(p, pte) 822950Sbill register struct proc *p; 823950Sbill register struct pte *pte; 824950Sbill { 825950Sbill 826950Sbill if (isatpte(p, pte)) 827950Sbill return (tptov(p, ptetotp(p, pte))); 828950Sbill else if (isadpte(p, pte)) 829950Sbill return (dptov(p, ptetodp(p, pte))); 830950Sbill else 831950Sbill return (sptov(p, ptetosp(p, pte))); 832950Sbill } 833950Sbill 834950Sbill /* 835950Sbill * Given a base/size pair in virtual swap area, 836950Sbill * return a physical base/size pair which is the 837950Sbill * (largest) initial, physically contiguous block. 838950Sbill */ 839950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 840950Sbill register int vsbase; 841950Sbill int vssize; 842950Sbill register struct dmap *dmp; 843950Sbill register struct dblock *dbp; 844950Sbill { 845*12702Ssam register int blk = dmmin; 846950Sbill register swblk_t *ip = dmp->dm_map; 847950Sbill 848950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 849950Sbill panic("vstodb"); 850950Sbill while (vsbase >= blk) { 851950Sbill vsbase -= blk; 852*12702Ssam if (blk < dmmax) 853950Sbill blk *= 2; 854950Sbill ip++; 855950Sbill } 856950Sbill dbp->db_size = min(vssize, blk - vsbase); 857950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 858950Sbill } 859950Sbill 860950Sbill panic(cp) 861950Sbill char *cp; 862950Sbill { 863950Sbill printf("panic!: %s\n", cp); 864950Sbill } 865950Sbill 866950Sbill min(a, b) 867950Sbill { 868950Sbill return (a < b ? a : b); 869950Sbill } 870