1*22482Sdist /* 2*22482Sdist * Copyright (c) 1980 Regents of the University of California. 3*22482Sdist * All rights reserved. The Berkeley software License Agreement 4*22482Sdist * specifies the terms and conditions for redistribution. 5*22482Sdist */ 6*22482Sdist 712702Ssam #ifndef lint 8*22482Sdist char copyright[] = 9*22482Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*22482Sdist All rights reserved.\n"; 11*22482Sdist #endif not lint 1212702Ssam 13*22482Sdist #ifndef lint 14*22482Sdist static char sccsid[] = "@(#)analyze.c 5.1 (Berkeley) 06/06/85"; 15*22482Sdist #endif not lint 16*22482Sdist 1712702Ssam /* 1812702Ssam * Analyze - analyze a core (and optional paging area) saved from 1912702Ssam * a virtual Unix system crash. 2012702Ssam */ 21950Sbill #include <stdio.h> 22950Sbill #include <sys/param.h> 23950Sbill #include <sys/dir.h> 249891Ssam #include <machine/pte.h> 25950Sbill #include <nlist.h> 26950Sbill #include <sys/map.h> 27950Sbill #include <sys/user.h> 28950Sbill #include <sys/proc.h> 29950Sbill #include <sys/text.h> 30950Sbill #include <sys/cmap.h> 31950Sbill #include <sys/vm.h> 32950Sbill 33950Sbill int Dflg; 34950Sbill int dflg; 35950Sbill int vflg; 36950Sbill int mflg; 37950Sbill int fflg; 38950Sbill int sflg; 392824Swnj int uflg; 40950Sbill 41950Sbill /* use vprintf with care; it plays havoc with ``else's'' */ 42950Sbill #define vprintf if (vflg) printf 43950Sbill 4410809Ssam #ifdef vax 45950Sbill #define clear(x) ((int)x & 0x7fffffff) 4610809Ssam #else 4710809Ssam #define clear(x) ((int)x) 4810809Ssam #endif 49950Sbill 503795Sroot struct proc *proc, *aproc; 513526Sroot int nproc; 523795Sroot struct text *text, *atext; 533526Sroot int ntext; 543526Sroot struct mapent *swapmap; 553526Sroot int nswapmap; 5612702Ssam int dmmin, dmmax, dmtext; 57950Sbill struct cmap *cmap; 582824Swnj int ecmx; 59950Sbill struct pte *usrpt; 60950Sbill struct pte *Usrptma; 61950Sbill int firstfree; 62950Sbill int maxfree; 63950Sbill int freemem; 64950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 65950Sbill int pid; 66950Sbill 67950Sbill struct paginfo { 68950Sbill char z_type; 69950Sbill char z_count; 70950Sbill short z_pid; 71950Sbill struct pte z_pte; 72950Sbill } *paginfo; 73950Sbill #define ZLOST 0 74950Sbill #define ZDATA 1 75950Sbill #define ZSTACK 2 76950Sbill #define ZUDOT 3 77950Sbill #define ZPAGET 4 78950Sbill #define ZTEXT 5 79950Sbill #define ZFREE 6 80950Sbill #define ZINTRAN 7 81950Sbill 82950Sbill struct dblks { 83950Sbill short d_first; 84950Sbill short d_size; 85950Sbill char d_type; 86950Sbill char d_index; 873526Sroot } *dblks; 88950Sbill int ndblks; 89950Sbill 90950Sbill #define DFREE 0 91950Sbill #define DDATA 1 92950Sbill #define DSTACK 2 93950Sbill #define DTEXT 3 94950Sbill #define DUDOT 4 95950Sbill #define DPAGET 5 96950Sbill 97950Sbill union { 9810809Ssam char buf[UPAGES][NBPG]; 99950Sbill struct user U; 100950Sbill } u_area; 101950Sbill #define u u_area.U 102950Sbill 103950Sbill int fcore = -1; 104950Sbill int fswap = -1; 105950Sbill 106950Sbill struct nlist nl[] = { 107950Sbill #define X_PROC 0 108950Sbill { "_proc" }, 109950Sbill #define X_USRPT 1 110950Sbill { "_usrpt" }, 111950Sbill #define X_PTMA 2 1122824Swnj { "_Usrptmap" }, 113950Sbill #define X_FIRSTFREE 3 1142824Swnj { "_firstfree" }, 115950Sbill #define X_MAXFREE 4 116950Sbill { "_maxfree" }, 117950Sbill #define X_TEXT 5 118950Sbill { "_text" }, 119950Sbill #define X_FREEMEM 6 120950Sbill { "_freemem" }, 121950Sbill #define X_CMAP 7 122950Sbill { "_cmap" }, 123950Sbill #define X_ECMAP 8 124950Sbill { "_ecmap" }, 125950Sbill #define X_SWAPMAP 9 126950Sbill { "_swapmap" }, 1273526Sroot #define X_NPROC 10 1283526Sroot { "_nproc" }, 1293526Sroot #define X_NTEXT 11 1303526Sroot { "_ntext" }, 1313526Sroot #define X_NSWAPMAP 12 1323526Sroot { "_nswapmap" }, 13312702Ssam #define X_DMMIN 13 13412702Ssam { "_dmmin" }, 13512702Ssam #define X_DMMAX 14 13612702Ssam { "_dmmax" }, 13712702Ssam #define X_DMTEXT 15 13812702Ssam { "_dmtext" }, 13912702Ssam { "" } 140950Sbill }; 141950Sbill 142950Sbill main(argc, argv) 143950Sbill int argc; 144950Sbill char **argv; 145950Sbill { 146950Sbill register struct nlist *np; 147950Sbill register struct proc *p; 148950Sbill register struct text *xp; 149950Sbill register struct pte *pte; 150950Sbill register int i; 151950Sbill int w, a; 152950Sbill 15310809Ssam #ifdef DEBUG 15410809Ssam setbuf(stdout, NULL); 15510809Ssam #endif 156950Sbill argc--, argv++; 157950Sbill while (argc > 0 && argv[0][0] == '-') { 158950Sbill register char *cp = *argv++; 159950Sbill argc--; 160950Sbill while (*++cp) switch (*cp) { 161950Sbill 162950Sbill case 'm': 163950Sbill mflg++; 164950Sbill break; 165950Sbill 166950Sbill case 'v': 167950Sbill vflg++; 168950Sbill break; 169950Sbill 170950Sbill case 's': 171950Sbill if (argc < 2) 172950Sbill goto usage; 173950Sbill if ((fswap = open(argv[0], 0)) < 0) { 174950Sbill perror(argv[0]); 175950Sbill exit(1); 176950Sbill } 177950Sbill argc--,argv++; 178950Sbill sflg++; 179950Sbill break; 180950Sbill 181950Sbill case 'f': 182950Sbill fflg++; 183950Sbill break; 184950Sbill 185950Sbill case 'D': 186950Sbill Dflg++; 187950Sbill break; 188950Sbill 189950Sbill case 'd': 190950Sbill dflg++; 191950Sbill break; 192950Sbill 1932824Swnj case 'u': 1942824Swnj uflg++; 1952824Swnj break; 1962824Swnj 197950Sbill default: 198950Sbill goto usage; 199950Sbill } 200950Sbill } 201950Sbill if (argc < 1) { 202950Sbill usage: 203950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 204950Sbill exit(1); 205950Sbill } 206950Sbill close(0); 207950Sbill if ((fcore = open(argv[0], 0)) < 0) { 208950Sbill perror(argv[0]); 209950Sbill exit(1); 210950Sbill } 211950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 212950Sbill if (nl[0].n_value == 0) { 213950Sbill fprintf(stderr, "%s: bad namelist\n", 214950Sbill argc > 1 ? argv[1] : "/vmunix"); 215950Sbill exit(1); 216950Sbill } 21712702Ssam for (np = nl; np->n_name && *np->n_name; np++) 218950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 219950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 220950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 221950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 222950Sbill maxfree = get(nl[X_MAXFREE].n_value); 223950Sbill freemem = get(nl[X_FREEMEM].n_value); 22412702Ssam dmmin = get(nl[X_DMMIN]); 22512702Ssam dmmax = get(nl[X_DMMAX]); 22612702Ssam dmtext = get(nl[X_DMTEXT]); 227950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 228950Sbill if (paginfo == NULL) { 229950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 230950Sbill exit(1); 231950Sbill } 232950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 233950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 2343795Sroot { 2353526Sroot lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 2363526Sroot read(fcore, (char *)&aproc, sizeof aproc); 2373526Sroot lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0); 2383526Sroot read(fcore, (char *)&nproc, sizeof nproc); 2393526Sroot printf("%d procs\n", nproc); 2403526Sroot proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 2413526Sroot lseek(fcore, (long)clear(aproc), 0); 2423526Sroot if (read(fcore, (char *)proc, nproc * sizeof (struct proc)) 2433526Sroot != nproc * sizeof (struct proc)) { 244950Sbill perror("proc read"); 245950Sbill exit(1); 2463526Sroot } 247950Sbill } 2483795Sroot { 2493526Sroot lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 2503526Sroot read(fcore, (char *)&atext, sizeof atext); 2513526Sroot lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0); 2523526Sroot read(fcore, (char *)&ntext, sizeof ntext); 2533526Sroot printf("%d texts\n", ntext); 2543526Sroot text = (struct text *)calloc(ntext, sizeof (struct text)); 2553526Sroot lseek(fcore, (long)clear(atext), 0); 2563526Sroot if (read(fcore, (char *)text, ntext * sizeof (struct text)) 2573526Sroot != ntext * sizeof (struct text)) { 258950Sbill perror("text read"); 259950Sbill exit(1); 2603526Sroot } 261950Sbill } 262950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 2632824Swnj ecmx = i / sizeof (struct cmap); 264950Sbill cmap = (struct cmap *)calloc(i, 1); 265950Sbill if (cmap == NULL) { 266950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 267950Sbill exit(1); 268950Sbill } 269950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 270950Sbill if (read(fcore, (char *)cmap, i) != i) { 271950Sbill perror("cmap read"); 272950Sbill exit(1); 273950Sbill } 2743526Sroot { struct mapent *aswapmap; 2753526Sroot lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 2763526Sroot read(fcore, (char *)&aswapmap, sizeof aswapmap); 2773526Sroot lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0); 2783526Sroot read(fcore, (char *)&nswapmap, sizeof nswapmap); 2793526Sroot nswapmap--; 2803526Sroot printf("%d swapmap entries\n", nswapmap); 2813526Sroot swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent)); 2823526Sroot dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks)); 2833526Sroot lseek(fcore, (long)clear(aswapmap+1), 0); 2843526Sroot if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent)) 2853526Sroot != nswapmap * sizeof (struct mapent)) { 286950Sbill perror("swapmap read"); 287950Sbill exit(1); 2883526Sroot } 289950Sbill } 2903526Sroot for (p = &proc[1]; p < proc+nproc; p++) { 291950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 292950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 293950Sbill if (p->p_stat == 0) 294950Sbill continue; 295950Sbill printf("proc %d ", p->p_pid); 296950Sbill if (p->p_stat == SZOMB) { 297950Sbill printf("zombie\n"); 298950Sbill continue; 299950Sbill } 300950Sbill if (p->p_flag & SLOAD) { 301950Sbill printf("loaded, p0br %x, ", p->p_p0br); 302950Sbill printf("%d pages of page tables:", p->p_szpt); 303950Sbill a = btokmx(p->p_p0br); 304950Sbill for (i = 0; i < p->p_szpt; i++) { 305950Sbill w = get(&Usrptma[a + i]); 306950Sbill printf(" %x", w & PG_PFNUM); 307950Sbill } 308950Sbill printf("\n"); 309950Sbill for(i = 0; i < p->p_szpt; i++) { 310950Sbill w = get(&Usrptma[a + i]); 311950Sbill if (getpt(w, i)) 312950Sbill count(p, (struct pte *)&w, ZPAGET); 313950Sbill } 314950Sbill } else { 315950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 316950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 317950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 31810809Ssam duse(p->p_swaddr, ctod(clrnd(UPAGES)), DUDOT, p - proc); 319950Sbill duse(p->p_swaddr + ctod(UPAGES), 32010809Ssam ctod(clrnd(i - p->p_tsize / NPTEPG)), 32110809Ssam DPAGET, p - proc); 322950Sbill /* i, DPAGET, p - proc); */ 323950Sbill } 324950Sbill p->p_p0br = (struct pte *)p0br; 325950Sbill p->p_addr = uaddr(p); 32610809Ssam if (p->p_textp) 32710809Ssam p->p_textp = &text[p->p_textp - atext]; 328950Sbill if (p->p_pid == 2) 329950Sbill continue; 330950Sbill if (getu(p)) 331950Sbill continue; 332950Sbill u.u_procp = p; 333950Sbill pdmap(); 334950Sbill if ((p->p_flag & SLOAD) == 0) 335950Sbill continue; 336950Sbill pid = p->p_pid; 337950Sbill for (i = 0; i < p->p_tsize; i++) { 338950Sbill pte = tptopte(p, i); 339950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 340950Sbill continue; 341950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 342950Sbill count(p, pte, ZINTRAN); 343950Sbill else 344950Sbill count(p, pte, ZTEXT); 345950Sbill } 346950Sbill vprintf("\n"); 347950Sbill for (i = 0; i < p->p_dsize; i++) { 348950Sbill pte = dptopte(p, i); 349950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 350950Sbill continue; 351950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 352950Sbill count(p, pte, ZINTRAN); 353950Sbill else 354950Sbill count(p, pte, ZDATA); 355950Sbill } 356950Sbill vprintf("\n"); 357950Sbill for (i = 0; i < p->p_ssize; i++) { 358950Sbill pte = sptopte(p, i); 359950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 360950Sbill continue; 361950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 362950Sbill count(p, pte, ZINTRAN); 363950Sbill else 364950Sbill count(p, pte, ZSTACK); 365950Sbill } 366950Sbill vprintf("\n"); 367950Sbill for (i = 0; i < UPAGES; i++) 368950Sbill count(p, &p->p_addr[i], ZUDOT); 369950Sbill vprintf("\n"); 370950Sbill vprintf("\n"); 371950Sbill } 3723526Sroot for (xp = &text[0]; xp < text+ntext; xp++) 373950Sbill if (xp->x_iptr) { 37410809Ssam int size = ctod(xp->x_size); 37510809Ssam 37612702Ssam for (i = 0; i < size; i += dmtext) 377950Sbill duse(xp->x_daddr[i], 37812702Ssam (size - i) > dmtext 37912702Ssam ? dmtext : size - i, 380950Sbill DTEXT, xp - text); 381950Sbill if (xp->x_flag & XPAGI) 38210809Ssam duse(xp->x_ptdaddr, 38310809Ssam ctod(clrnd(ctopt(xp->x_size))), 384950Sbill DTEXT, xp - text); 385950Sbill } 386950Sbill dmcheck(); 387950Sbill fixfree(); 388950Sbill summary(); 389950Sbill exit(0); 390950Sbill } 391950Sbill 392950Sbill pdmap() 393950Sbill { 394950Sbill register struct text *xp; 395950Sbill 396950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 397950Sbill return; 398950Sbill if (Dflg) 399950Sbill printf("disk for pid %d", u.u_procp->p_pid); 400950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 401950Sbill ptdmap(xp->x_daddr, xp->x_size); 402950Sbill pdmseg("data", &u.u_dmap, DDATA); 403950Sbill pdmseg("stack", &u.u_smap, DSTACK); 404950Sbill if (Dflg) 405950Sbill printf("\n"); 406950Sbill } 407950Sbill 408950Sbill ptdmap(dp, size) 409950Sbill register daddr_t *dp; 410950Sbill int size; 411950Sbill { 412950Sbill register int i; 413950Sbill int rem; 414950Sbill 415950Sbill if (Dflg) 416950Sbill printf(" text:"); 417950Sbill for (i = 0, rem = size; rem > 0; i++) { 418950Sbill if (Dflg) 41912702Ssam printf(" %x<%x>", dp[i], rem < dmtext ? rem : dmtext); 42012702Ssam rem -= rem < dmtext ? rem : dmtext; 421950Sbill } 422950Sbill } 423950Sbill 424950Sbill pdmseg(cp, dmp, type) 425950Sbill char *cp; 426950Sbill struct dmap *dmp; 427950Sbill { 428950Sbill register int i; 429950Sbill int b, rem; 430950Sbill 431950Sbill if (Dflg) 432950Sbill printf(", %s:", cp); 43312702Ssam b = dmmin; 434950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 435950Sbill if (Dflg) 436950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 437950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 438950Sbill rem -= b; 43912702Ssam if (b < dmmax) 440950Sbill b *= 2; 441950Sbill } 442950Sbill } 443950Sbill 444950Sbill duse(first, size, type, index) 445950Sbill { 446950Sbill register struct dblks *dp; 447950Sbill 448950Sbill if (fswap == -1) 449950Sbill return; 450950Sbill dp = &dblks[ndblks]; 4513526Sroot if (++ndblks > 2*nswapmap) { 4523526Sroot fprintf(stderr, "too many disk blocks\n"); 453950Sbill exit(1); 454950Sbill } 455950Sbill dp->d_first = first; 456950Sbill dp->d_size = size; 457950Sbill dp->d_type = type; 458950Sbill dp->d_index = index; 459950Sbill } 460950Sbill 461950Sbill dsort(d, e) 462950Sbill register struct dblks *d, *e; 463950Sbill { 464950Sbill 465950Sbill return (e->d_first - d->d_first); 466950Sbill } 467950Sbill 468950Sbill dmcheck() 469950Sbill { 4703526Sroot register struct mapent *smp; 471950Sbill register struct dblks *d, *e; 472950Sbill 473950Sbill for (smp = swapmap; smp->m_size; smp++) 474950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 47512702Ssam duse(ctod(CLSIZE), dmtext - ctod(CLSIZE), DFREE, 0); 476950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 477950Sbill d = &dblks[ndblks - 1]; 478950Sbill if (d->d_first > 1) 479950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 480950Sbill for (; d > dblks; d--) { 481950Sbill if (dflg) 482950Sbill dprint(d); 483950Sbill e = d - 1; 484950Sbill if (d->d_first + d->d_size > e->d_first) { 485950Sbill printf("overlap in swap mappings:\n"); 486950Sbill dprint(d); 487950Sbill dprint(e); 488950Sbill } else if (d->d_first + d->d_size < e->d_first) { 489950Sbill printf("lost swap map: start %x size %x\n", 490950Sbill d->d_first + d->d_size, 491950Sbill e->d_first - (d->d_first + d->d_size)); 492950Sbill } 493950Sbill } 494950Sbill if (dflg) 495950Sbill dprint(dblks); 496950Sbill if (sflg) 497950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 498950Sbill } 499950Sbill 500950Sbill char *dnames[] = { 501950Sbill "DFREE", 502950Sbill "DDATA", 503950Sbill "DSTACK", 504950Sbill "DTEXT", 505950Sbill "DUDOT", 506950Sbill "DPAGET", 507950Sbill }; 508950Sbill 509950Sbill dprint(d) 510950Sbill register struct dblks *d; 511950Sbill { 512950Sbill 513950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 514950Sbill dnames[d->d_type]); 515950Sbill switch (d->d_type) { 516950Sbill 517950Sbill case DSTACK: 518950Sbill case DDATA: 519950Sbill printf(" pid %d", proc[d->d_index].p_pid); 520950Sbill break; 521950Sbill } 522950Sbill printf("\n"); 523950Sbill } 524950Sbill 525950Sbill getpt(x, i) 526950Sbill int x, i; 527950Sbill { 528950Sbill 529950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 530950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 531950Sbill perror("read"); 532950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 533950Sbill return (0); 534950Sbill } 535950Sbill return (1); 536950Sbill } 537950Sbill 538950Sbill checkpg(p, pte, type) 539950Sbill register struct pte *pte; 540950Sbill register struct proc *p; 541950Sbill int type; 542950Sbill { 543950Sbill char corepg[NBPG], swapg[NBPG]; 544950Sbill register int i, count, dblock; 545950Sbill register int pfnum = pte->pg_pfnum; 546950Sbill 547950Sbill if (type == ZPAGET || type == ZUDOT) 548950Sbill return (0); 549950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 550950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 551950Sbill perror("read"); 552950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 553950Sbill return (0); 554950Sbill } 555950Sbill switch (type) { 556950Sbill 557950Sbill case ZDATA: 558950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 559950Sbill return (0); 560950Sbill break; 561950Sbill 562950Sbill case ZTEXT: 563950Sbill break; 564950Sbill 565950Sbill case ZSTACK: 566950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 567950Sbill return (0); 568950Sbill break; 569950Sbill 570950Sbill default: 571950Sbill return(0); 572950Sbill break; 573950Sbill } 574950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 575950Sbill vprintf(" %x", dblock); 576950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 577950Sbill return (0); 578950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 579950Sbill return (0); 58010809Ssam lseek(fswap, (long)(DEV_BSIZE * dblock), 0); 581950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 582950Sbill fprintf(stderr,"swap page %x: ", dblock); 583950Sbill perror("read"); 584950Sbill } 585950Sbill count = 0; 586950Sbill for (i = 0; i < NBPG; i++) 587950Sbill if (corepg[i] != swapg[i]) 588950Sbill count++; 589950Sbill if (count == 0) 590950Sbill vprintf("\tsame"); 591950Sbill return (count); 592950Sbill } 593950Sbill 594950Sbill getu(p) 595950Sbill register struct proc *p; 596950Sbill { 597950Sbill int i, w, cc, errs = 0; 598950Sbill 5992824Swnj if (uflg && (p->p_flag & SLOAD)) 6002824Swnj printf("pid %d u. pages:", p->p_pid); 601950Sbill for (i = 0; i < UPAGES; i++) { 602950Sbill if (p->p_flag & SLOAD) { 6032824Swnj if (uflg) 6042824Swnj printf(" %x", p->p_addr[i].pg_pfnum); 605950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 606950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 607950Sbill perror("core u. read"), errs++; 608950Sbill } else if (fswap >= 0) { 609950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 610950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 611950Sbill perror("swap u. read"), errs++; 612950Sbill } 613950Sbill } 6142824Swnj if (uflg && (p->p_flag & SLOAD)) 6152824Swnj printf("\n"); 616950Sbill return (errs); 617950Sbill } 618950Sbill 619950Sbill char *typepg[] = { 620950Sbill "lost", 621950Sbill "data", 622950Sbill "stack", 623950Sbill "udot", 624950Sbill "paget", 625950Sbill "text", 626950Sbill "free", 627950Sbill "intransit", 628950Sbill }; 629950Sbill 630950Sbill count(p, pte, type) 631950Sbill struct proc *p; 632950Sbill register struct pte *pte; 633950Sbill int type; 634950Sbill { 635950Sbill register int pfnum = pte->pg_pfnum; 636950Sbill register struct paginfo *zp = &paginfo[pfnum]; 637950Sbill int ndif; 638950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 639950Sbill 640950Sbill if (type == ZINTRAN && pfnum == 0) 641950Sbill return; 642950Sbill zprintf("page %x %s", pfnum, typepg[type]); 643950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 644950Sbill zprintf("\n"); 645950Sbill } else { 646950Sbill if (vflg == 0 && type != ZINTRAN) 647950Sbill printf("page %x %s,", pfnum, typepg[type]); 648950Sbill printf(" %d bytes differ\n",ndif); 649950Sbill } 650950Sbill if (pfnum < firstfree || pfnum > maxfree) { 651950Sbill printf("page number out of range:\n"); 652950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 653950Sbill return; 654950Sbill } 655950Sbill if (bad(zp, type)) { 656950Sbill printf("dup page pte %x", *(int *)pte); 657950Sbill dumpcm("", pte->pg_pfnum); 658950Sbill dump(zp); 659950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 660950Sbill return; 661950Sbill } 662950Sbill zp->z_type = type; 663950Sbill zp->z_count++; 664950Sbill zp->z_pid = pid; 665950Sbill zp->z_pte = *pte; 666950Sbill } 667950Sbill 668950Sbill bad(zp, type) 669950Sbill struct paginfo *zp; 670950Sbill { 671950Sbill if (type == ZTEXT) { 672950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 673950Sbill return (1); 674950Sbill return (0); 675950Sbill } 676950Sbill return (zp->z_count); 677950Sbill } 678950Sbill 679950Sbill dump(zp) 680950Sbill struct paginfo *zp; 681950Sbill { 682950Sbill 683950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 684950Sbill } 685950Sbill 686950Sbill summary() 687950Sbill { 688950Sbill register int i; 689950Sbill register struct paginfo *zp; 690950Sbill register int pfnum; 691950Sbill 6922824Swnj for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 693950Sbill zp = &paginfo[i]; 694950Sbill if (zp->z_type == ZLOST) 695950Sbill dumpcm("lost", i); 696950Sbill pfnum = pgtocm(i); 697950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 698950Sbill dumpcm("locked", i); 699950Sbill if (mflg) 700950Sbill dumpcm("mem", i); 701950Sbill } 702950Sbill } 703950Sbill 704950Sbill char *tynames[] = { 705950Sbill "sys", 706950Sbill "text", 707950Sbill "data", 708950Sbill "stack" 709950Sbill }; 710950Sbill dumpcm(cp, pg) 711950Sbill char *cp; 712950Sbill int pg; 713950Sbill { 714950Sbill int pslot; 715950Sbill int cm; 716950Sbill register struct cmap *c; 717950Sbill 718950Sbill cm = pgtocm(pg); 7192824Swnj printf("cm %x %s page %x ", cm, cp, pg); 720950Sbill c = &cmap[cm]; 721950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 7223795Sroot if (c->c_type == CSYS) 7233795Sroot goto skip; 7243795Sroot if (c->c_type != CTEXT) { 7253795Sroot if (c->c_ndx >= nproc) { 7263795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7273795Sroot goto skip; 7283795Sroot } 729950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 7303795Sroot } else { 7313795Sroot if (c->c_ndx >= ntext) { 7323795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7333795Sroot goto skip; 7343795Sroot } 7353795Sroot pslot= (text[c->c_ndx].x_caddr - aproc); 736950Sbill printf(" (=pid"); 737950Sbill for(;;) { 738950Sbill printf(" %d", proc[pslot].p_pid); 739950Sbill if (proc[pslot].p_xlink == 0) 740950Sbill break; 7413795Sroot pslot= (proc[pslot].p_xlink - aproc); 742950Sbill } 743950Sbill printf(")"); 744950Sbill } 7453795Sroot skip: 746950Sbill printf("] "); 747950Sbill printf(tynames[c->c_type]); 748950Sbill if (c->c_free) 749950Sbill printf(" free"); 750950Sbill if (c->c_gone) 751950Sbill printf(" gone"); 752950Sbill if (c->c_lock) 753950Sbill printf(" lock"); 754950Sbill if (c->c_want) 755950Sbill printf(" want"); 756950Sbill if (c->c_intrans) 757950Sbill printf(" intrans"); 758950Sbill if (c->c_blkno) 759950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 7602824Swnj if (c->c_hlink) { 7612824Swnj printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 7622824Swnj if (c->c_hlink > ecmx) 7632824Swnj printf(" <<<"); 7642824Swnj } 765950Sbill printf("\n"); 766950Sbill } 767950Sbill 768950Sbill fixfree() 769950Sbill { 770950Sbill register int i, next, prev; 771950Sbill 772950Sbill next = CMHEAD; 773950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 774950Sbill prev = next; 775950Sbill next = cmap[next].c_next; 776950Sbill if (cmap[next].c_free == 0) { 777950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 778950Sbill dumpcm("bad free link in", cmtopg(prev)); 779950Sbill dumpcm("to non free block", cmtopg(next)); 780950Sbill } 781950Sbill if (cmtopg(next) > maxfree) { 782950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 783950Sbill dumpcm("bad link in", cmtopg(prev)); 784950Sbill } 785950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 786950Sbill if (fflg) 787950Sbill dumpcm("free", cmtopg(next)); 788950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 789950Sbill if (fflg) 790950Sbill dumpcm("free", cmtopg(next)+1); 791950Sbill } 792950Sbill } 793950Sbill 794950Sbill get(loc) 795950Sbill unsigned loc; 796950Sbill { 797950Sbill int x; 798950Sbill 799950Sbill lseek(fcore, (long)clear(loc), 0); 800950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 801950Sbill perror("read"); 802950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 803950Sbill return (0); 804950Sbill } 805950Sbill return (x); 806950Sbill } 807950Sbill /* 808950Sbill * Convert a virtual page number 809950Sbill * to its corresponding disk block number. 810950Sbill * Used in pagein/pageout to initiate single page transfers. 811950Sbill */ 812950Sbill vtod(p, v, dmap, smap) 813950Sbill register struct proc *p; 814950Sbill register struct dmap *dmap, *smap; 815950Sbill { 816950Sbill struct dblock db; 817950Sbill 81810809Ssam if (isatsv(p, v)) { 81910809Ssam v = ctod(vtotp(p, v)); 82012702Ssam return(p->p_textp->x_daddr[v / dmtext] + v % dmtext); 82110809Ssam } 822950Sbill if (isassv(p, v)) 82310809Ssam vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1); 824950Sbill else 82510809Ssam vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0); 826950Sbill return (db.db_base); 827950Sbill } 828950Sbill 829950Sbill /* 830950Sbill * Convert a pte pointer to 831950Sbill * a virtual page number. 832950Sbill */ 833950Sbill ptetov(p, pte) 834950Sbill register struct proc *p; 835950Sbill register struct pte *pte; 836950Sbill { 837950Sbill 838950Sbill if (isatpte(p, pte)) 839950Sbill return (tptov(p, ptetotp(p, pte))); 840950Sbill else if (isadpte(p, pte)) 841950Sbill return (dptov(p, ptetodp(p, pte))); 842950Sbill else 843950Sbill return (sptov(p, ptetosp(p, pte))); 844950Sbill } 845950Sbill 846950Sbill /* 847950Sbill * Given a base/size pair in virtual swap area, 848950Sbill * return a physical base/size pair which is the 849950Sbill * (largest) initial, physically contiguous block. 850950Sbill */ 851950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 852950Sbill register int vsbase; 853950Sbill int vssize; 854950Sbill register struct dmap *dmp; 855950Sbill register struct dblock *dbp; 856950Sbill { 85712702Ssam register int blk = dmmin; 858950Sbill register swblk_t *ip = dmp->dm_map; 859950Sbill 860950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 861950Sbill panic("vstodb"); 862950Sbill while (vsbase >= blk) { 863950Sbill vsbase -= blk; 86412702Ssam if (blk < dmmax) 865950Sbill blk *= 2; 866950Sbill ip++; 867950Sbill } 868950Sbill dbp->db_size = min(vssize, blk - vsbase); 869950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 870950Sbill } 871950Sbill 872950Sbill panic(cp) 873950Sbill char *cp; 874950Sbill { 875950Sbill printf("panic!: %s\n", cp); 876950Sbill } 877950Sbill 878950Sbill min(a, b) 879950Sbill { 880950Sbill return (a < b ? a : b); 881950Sbill } 882