1*3795Sroot static char *sccsid = "@(#)analyze.c 4.4 (Berkeley) 05/18/81"; 2950Sbill #include <stdio.h> 3950Sbill #include <sys/param.h> 4950Sbill #include <sys/dir.h> 5950Sbill #include <sys/pte.h> 6950Sbill #include <nlist.h> 7950Sbill #include <sys/map.h> 8950Sbill #include <sys/user.h> 9950Sbill #include <sys/proc.h> 10950Sbill #include <sys/text.h> 11950Sbill #include <sys/cmap.h> 12950Sbill #include <sys/vm.h> 13950Sbill 14950Sbill /* 15950Sbill * Analyze - analyze a core (and optional paging area) saved from 16950Sbill * a virtual Unix system crash. 17950Sbill */ 18950Sbill 19950Sbill int Dflg; 20950Sbill int dflg; 21950Sbill int vflg; 22950Sbill int mflg; 23950Sbill int fflg; 24950Sbill int sflg; 252824Swnj int uflg; 26950Sbill 27950Sbill /* use vprintf with care; it plays havoc with ``else's'' */ 28950Sbill #define vprintf if (vflg) printf 29950Sbill 30950Sbill #define clear(x) ((int)x & 0x7fffffff) 31950Sbill 32*3795Sroot struct proc *proc, *aproc; 333526Sroot int nproc; 34*3795Sroot struct text *text, *atext; 353526Sroot int ntext; 363526Sroot struct mapent *swapmap; 373526Sroot int nswapmap; 38950Sbill struct cmap *cmap; 392824Swnj int ecmx; 40950Sbill struct pte *usrpt; 41950Sbill struct pte *Usrptma; 42950Sbill int firstfree; 43950Sbill int maxfree; 44950Sbill int freemem; 45950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 46950Sbill int pid; 47950Sbill 48950Sbill struct paginfo { 49950Sbill char z_type; 50950Sbill char z_count; 51950Sbill short z_pid; 52950Sbill struct pte z_pte; 53950Sbill } *paginfo; 54950Sbill #define ZLOST 0 55950Sbill #define ZDATA 1 56950Sbill #define ZSTACK 2 57950Sbill #define ZUDOT 3 58950Sbill #define ZPAGET 4 59950Sbill #define ZTEXT 5 60950Sbill #define ZFREE 6 61950Sbill #define ZINTRAN 7 62950Sbill 63950Sbill struct dblks { 64950Sbill short d_first; 65950Sbill short d_size; 66950Sbill char d_type; 67950Sbill char d_index; 683526Sroot } *dblks; 69950Sbill int ndblks; 70950Sbill 71950Sbill #define DFREE 0 72950Sbill #define DDATA 1 73950Sbill #define DSTACK 2 74950Sbill #define DTEXT 3 75950Sbill #define DUDOT 4 76950Sbill #define DPAGET 5 77950Sbill 78950Sbill union { 79950Sbill char buf[UPAGES][512]; 80950Sbill struct user U; 81950Sbill } u_area; 82950Sbill #define u u_area.U 83950Sbill 84950Sbill int fcore = -1; 85950Sbill int fswap = -1; 86950Sbill 87950Sbill struct nlist nl[] = { 88950Sbill #define X_PROC 0 89950Sbill { "_proc" }, 90950Sbill #define X_USRPT 1 91950Sbill { "_usrpt" }, 92950Sbill #define X_PTMA 2 932824Swnj { "_Usrptmap" }, 94950Sbill #define X_FIRSTFREE 3 952824Swnj { "_firstfree" }, 96950Sbill #define X_MAXFREE 4 97950Sbill { "_maxfree" }, 98950Sbill #define X_TEXT 5 99950Sbill { "_text" }, 100950Sbill #define X_FREEMEM 6 101950Sbill { "_freemem" }, 102950Sbill #define X_CMAP 7 103950Sbill { "_cmap" }, 104950Sbill #define X_ECMAP 8 105950Sbill { "_ecmap" }, 106950Sbill #define X_SWAPMAP 9 107950Sbill { "_swapmap" }, 1083526Sroot #define X_NPROC 10 1093526Sroot { "_nproc" }, 1103526Sroot #define X_NTEXT 11 1113526Sroot { "_ntext" }, 1123526Sroot #define X_NSWAPMAP 12 1133526Sroot { "_nswapmap" }, 114950Sbill { 0 } 115950Sbill }; 116950Sbill 117950Sbill main(argc, argv) 118950Sbill int argc; 119950Sbill char **argv; 120950Sbill { 121950Sbill register struct nlist *np; 122950Sbill register struct proc *p; 123950Sbill register struct text *xp; 124950Sbill register struct pte *pte; 125950Sbill register int i; 126950Sbill int w, a; 127950Sbill 128950Sbill argc--, argv++; 129950Sbill while (argc > 0 && argv[0][0] == '-') { 130950Sbill register char *cp = *argv++; 131950Sbill argc--; 132950Sbill while (*++cp) switch (*cp) { 133950Sbill 134950Sbill case 'm': 135950Sbill mflg++; 136950Sbill break; 137950Sbill 138950Sbill case 'v': 139950Sbill vflg++; 140950Sbill break; 141950Sbill 142950Sbill case 's': 143950Sbill if (argc < 2) 144950Sbill goto usage; 145950Sbill if ((fswap = open(argv[0], 0)) < 0) { 146950Sbill perror(argv[0]); 147950Sbill exit(1); 148950Sbill } 149950Sbill argc--,argv++; 150950Sbill sflg++; 151950Sbill break; 152950Sbill 153950Sbill case 'f': 154950Sbill fflg++; 155950Sbill break; 156950Sbill 157950Sbill case 'D': 158950Sbill Dflg++; 159950Sbill break; 160950Sbill 161950Sbill case 'd': 162950Sbill dflg++; 163950Sbill break; 164950Sbill 1652824Swnj case 'u': 1662824Swnj uflg++; 1672824Swnj break; 1682824Swnj 169950Sbill default: 170950Sbill goto usage; 171950Sbill } 172950Sbill } 173950Sbill if (argc < 1) { 174950Sbill usage: 175950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 176950Sbill exit(1); 177950Sbill } 178950Sbill close(0); 179950Sbill if ((fcore = open(argv[0], 0)) < 0) { 180950Sbill perror(argv[0]); 181950Sbill exit(1); 182950Sbill } 183950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 184950Sbill if (nl[0].n_value == 0) { 185950Sbill fprintf(stderr, "%s: bad namelist\n", 186950Sbill argc > 1 ? argv[1] : "/vmunix"); 187950Sbill exit(1); 188950Sbill } 189950Sbill for (np = nl; np->n_name[0]; np++) 190950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 191950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 192950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 193950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 194950Sbill maxfree = get(nl[X_MAXFREE].n_value); 195950Sbill freemem = get(nl[X_FREEMEM].n_value); 196950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 197950Sbill if (paginfo == NULL) { 198950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 199950Sbill exit(1); 200950Sbill } 201950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 202950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 203*3795Sroot { 2043526Sroot lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 2053526Sroot read(fcore, (char *)&aproc, sizeof aproc); 2063526Sroot lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0); 2073526Sroot read(fcore, (char *)&nproc, sizeof nproc); 2083526Sroot printf("%d procs\n", nproc); 2093526Sroot proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 2103526Sroot lseek(fcore, (long)clear(aproc), 0); 2113526Sroot if (read(fcore, (char *)proc, nproc * sizeof (struct proc)) 2123526Sroot != nproc * sizeof (struct proc)) { 213950Sbill perror("proc read"); 214950Sbill exit(1); 2153526Sroot } 216950Sbill } 217*3795Sroot { 2183526Sroot lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 2193526Sroot read(fcore, (char *)&atext, sizeof atext); 2203526Sroot lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0); 2213526Sroot read(fcore, (char *)&ntext, sizeof ntext); 2223526Sroot printf("%d texts\n", ntext); 2233526Sroot text = (struct text *)calloc(ntext, sizeof (struct text)); 2243526Sroot lseek(fcore, (long)clear(atext), 0); 2253526Sroot if (read(fcore, (char *)text, ntext * sizeof (struct text)) 2263526Sroot != ntext * sizeof (struct text)) { 227950Sbill perror("text read"); 228950Sbill exit(1); 2293526Sroot } 230950Sbill } 231950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 2322824Swnj ecmx = i / sizeof (struct cmap); 233950Sbill cmap = (struct cmap *)calloc(i, 1); 234950Sbill if (cmap == NULL) { 235950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 236950Sbill exit(1); 237950Sbill } 238950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 239950Sbill if (read(fcore, (char *)cmap, i) != i) { 240950Sbill perror("cmap read"); 241950Sbill exit(1); 242950Sbill } 2433526Sroot { struct mapent *aswapmap; 2443526Sroot lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 2453526Sroot read(fcore, (char *)&aswapmap, sizeof aswapmap); 2463526Sroot lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0); 2473526Sroot read(fcore, (char *)&nswapmap, sizeof nswapmap); 2483526Sroot nswapmap--; 2493526Sroot printf("%d swapmap entries\n", nswapmap); 2503526Sroot swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent)); 2513526Sroot dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks)); 2523526Sroot lseek(fcore, (long)clear(aswapmap+1), 0); 2533526Sroot if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent)) 2543526Sroot != nswapmap * sizeof (struct mapent)) { 255950Sbill perror("swapmap read"); 256950Sbill exit(1); 2573526Sroot } 258950Sbill } 2593526Sroot for (p = &proc[1]; p < proc+nproc; p++) { 260950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 261950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 262950Sbill if (p->p_stat == 0) 263950Sbill continue; 264950Sbill printf("proc %d ", p->p_pid); 265950Sbill if (p->p_stat == SZOMB) { 266950Sbill printf("zombie\n"); 267950Sbill continue; 268950Sbill } 269950Sbill if (p->p_flag & SLOAD) { 270950Sbill printf("loaded, p0br %x, ", p->p_p0br); 271950Sbill printf("%d pages of page tables:", p->p_szpt); 272950Sbill a = btokmx(p->p_p0br); 273950Sbill for (i = 0; i < p->p_szpt; i++) { 274950Sbill w = get(&Usrptma[a + i]); 275950Sbill printf(" %x", w & PG_PFNUM); 276950Sbill } 277950Sbill printf("\n"); 278950Sbill for(i = 0; i < p->p_szpt; i++) { 279950Sbill w = get(&Usrptma[a + i]); 280950Sbill if (getpt(w, i)) 281950Sbill count(p, (struct pte *)&w, ZPAGET); 282950Sbill } 283950Sbill } else { 284950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 285950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 286950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 287950Sbill duse(p->p_swaddr, clrnd(ctod(UPAGES)), DUDOT, p - proc); 288950Sbill duse(p->p_swaddr + ctod(UPAGES), 289950Sbill clrnd(i - p->p_tsize / NPTEPG), DPAGET, p - proc); 290950Sbill /* i, DPAGET, p - proc); */ 291950Sbill } 292950Sbill p->p_p0br = (struct pte *)p0br; 293950Sbill p->p_addr = uaddr(p); 294*3795Sroot p->p_textp = &text[p->p_textp - atext]; 295950Sbill if (p->p_pid == 2) 296950Sbill continue; 297950Sbill if (getu(p)) 298950Sbill continue; 299950Sbill u.u_procp = p; 300950Sbill pdmap(); 301950Sbill if ((p->p_flag & SLOAD) == 0) 302950Sbill continue; 303950Sbill pid = p->p_pid; 304950Sbill for (i = 0; i < p->p_tsize; i++) { 305950Sbill pte = tptopte(p, i); 306950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 307950Sbill continue; 308950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 309950Sbill count(p, pte, ZINTRAN); 310950Sbill else 311950Sbill count(p, pte, ZTEXT); 312950Sbill } 313950Sbill vprintf("\n"); 314950Sbill for (i = 0; i < p->p_dsize; i++) { 315950Sbill pte = dptopte(p, i); 316950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 317950Sbill continue; 318950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 319950Sbill count(p, pte, ZINTRAN); 320950Sbill else 321950Sbill count(p, pte, ZDATA); 322950Sbill } 323950Sbill vprintf("\n"); 324950Sbill for (i = 0; i < p->p_ssize; i++) { 325950Sbill pte = sptopte(p, i); 326950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 327950Sbill continue; 328950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 329950Sbill count(p, pte, ZINTRAN); 330950Sbill else 331950Sbill count(p, pte, ZSTACK); 332950Sbill } 333950Sbill vprintf("\n"); 334950Sbill for (i = 0; i < UPAGES; i++) 335950Sbill count(p, &p->p_addr[i], ZUDOT); 336950Sbill vprintf("\n"); 337950Sbill vprintf("\n"); 338950Sbill } 3393526Sroot for (xp = &text[0]; xp < text+ntext; xp++) 340950Sbill if (xp->x_iptr) { 341950Sbill for (i = 0; i < xp->x_size; i += DMTEXT) 342950Sbill duse(xp->x_daddr[i], 343950Sbill (xp->x_size - i) > DMTEXT 344950Sbill ? DMTEXT : xp->x_size - i, 345950Sbill DTEXT, xp - text); 346950Sbill if (xp->x_flag & XPAGI) 347950Sbill duse(xp->x_ptdaddr, clrnd(ctopt(xp->x_size)), 348950Sbill DTEXT, xp - text); 349950Sbill } 350950Sbill dmcheck(); 351950Sbill fixfree(); 352950Sbill summary(); 353950Sbill exit(0); 354950Sbill } 355950Sbill 356950Sbill pdmap() 357950Sbill { 358950Sbill register struct text *xp; 359950Sbill 360950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 361950Sbill return; 362950Sbill if (Dflg) 363950Sbill printf("disk for pid %d", u.u_procp->p_pid); 364950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 365950Sbill ptdmap(xp->x_daddr, xp->x_size); 366950Sbill pdmseg("data", &u.u_dmap, DDATA); 367950Sbill pdmseg("stack", &u.u_smap, DSTACK); 368950Sbill if (Dflg) 369950Sbill printf("\n"); 370950Sbill } 371950Sbill 372950Sbill ptdmap(dp, size) 373950Sbill register daddr_t *dp; 374950Sbill int size; 375950Sbill { 376950Sbill register int i; 377950Sbill int rem; 378950Sbill 379950Sbill if (Dflg) 380950Sbill printf(" text:"); 381950Sbill for (i = 0, rem = size; rem > 0; i++) { 382950Sbill if (Dflg) 383950Sbill printf(" %x<%x>", dp[i], rem < DMTEXT ? rem : DMTEXT); 384950Sbill rem -= rem < DMTEXT ? rem : DMTEXT; 385950Sbill } 386950Sbill } 387950Sbill 388950Sbill pdmseg(cp, dmp, type) 389950Sbill char *cp; 390950Sbill struct dmap *dmp; 391950Sbill { 392950Sbill register int i; 393950Sbill int b, rem; 394950Sbill 395950Sbill if (Dflg) 396950Sbill printf(", %s:", cp); 397950Sbill b = DMMIN; 398950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 399950Sbill if (Dflg) 400950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 401950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 402950Sbill rem -= b; 403950Sbill if (b < DMMAX) 404950Sbill b *= 2; 405950Sbill } 406950Sbill } 407950Sbill 408950Sbill duse(first, size, type, index) 409950Sbill { 410950Sbill register struct dblks *dp; 411950Sbill 412950Sbill if (fswap == -1) 413950Sbill return; 414950Sbill dp = &dblks[ndblks]; 4153526Sroot if (++ndblks > 2*nswapmap) { 4163526Sroot fprintf(stderr, "too many disk blocks\n"); 417950Sbill exit(1); 418950Sbill } 419950Sbill dp->d_first = first; 420950Sbill dp->d_size = size; 421950Sbill dp->d_type = type; 422950Sbill dp->d_index = index; 423950Sbill } 424950Sbill 425950Sbill dsort(d, e) 426950Sbill register struct dblks *d, *e; 427950Sbill { 428950Sbill 429950Sbill return (e->d_first - d->d_first); 430950Sbill } 431950Sbill 432950Sbill dmcheck() 433950Sbill { 4343526Sroot register struct mapent *smp; 435950Sbill register struct dblks *d, *e; 436950Sbill 437950Sbill for (smp = swapmap; smp->m_size; smp++) 438950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 439950Sbill duse(CLSIZE, DMTEXT - CLSIZE, DFREE, 0); 440950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 441950Sbill d = &dblks[ndblks - 1]; 442950Sbill if (d->d_first > 1) 443950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 444950Sbill for (; d > dblks; d--) { 445950Sbill if (dflg) 446950Sbill dprint(d); 447950Sbill e = d - 1; 448950Sbill if (d->d_first + d->d_size > e->d_first) { 449950Sbill printf("overlap in swap mappings:\n"); 450950Sbill dprint(d); 451950Sbill dprint(e); 452950Sbill } else if (d->d_first + d->d_size < e->d_first) { 453950Sbill printf("lost swap map: start %x size %x\n", 454950Sbill d->d_first + d->d_size, 455950Sbill e->d_first - (d->d_first + d->d_size)); 456950Sbill } 457950Sbill } 458950Sbill if (dflg) 459950Sbill dprint(dblks); 460950Sbill if (sflg) 461950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 462950Sbill } 463950Sbill 464950Sbill char *dnames[] = { 465950Sbill "DFREE", 466950Sbill "DDATA", 467950Sbill "DSTACK", 468950Sbill "DTEXT", 469950Sbill "DUDOT", 470950Sbill "DPAGET", 471950Sbill }; 472950Sbill 473950Sbill dprint(d) 474950Sbill register struct dblks *d; 475950Sbill { 476950Sbill 477950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 478950Sbill dnames[d->d_type]); 479950Sbill switch (d->d_type) { 480950Sbill 481950Sbill case DSTACK: 482950Sbill case DDATA: 483950Sbill printf(" pid %d", proc[d->d_index].p_pid); 484950Sbill break; 485950Sbill } 486950Sbill printf("\n"); 487950Sbill } 488950Sbill 489950Sbill getpt(x, i) 490950Sbill int x, i; 491950Sbill { 492950Sbill 493950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 494950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 495950Sbill perror("read"); 496950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 497950Sbill return (0); 498950Sbill } 499950Sbill return (1); 500950Sbill } 501950Sbill 502950Sbill checkpg(p, pte, type) 503950Sbill register struct pte *pte; 504950Sbill register struct proc *p; 505950Sbill int type; 506950Sbill { 507950Sbill char corepg[NBPG], swapg[NBPG]; 508950Sbill register int i, count, dblock; 509950Sbill register int pfnum = pte->pg_pfnum; 510950Sbill 511950Sbill if (type == ZPAGET || type == ZUDOT) 512950Sbill return (0); 513950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 514950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 515950Sbill perror("read"); 516950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 517950Sbill return (0); 518950Sbill } 519950Sbill switch (type) { 520950Sbill 521950Sbill case ZDATA: 522950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 523950Sbill return (0); 524950Sbill break; 525950Sbill 526950Sbill case ZTEXT: 527950Sbill break; 528950Sbill 529950Sbill case ZSTACK: 530950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 531950Sbill return (0); 532950Sbill break; 533950Sbill 534950Sbill default: 535950Sbill return(0); 536950Sbill break; 537950Sbill } 538950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 539950Sbill vprintf(" %x", dblock); 540950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 541950Sbill return (0); 542950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 543950Sbill return (0); 544950Sbill lseek(fswap, (long)(NBPG * dblock), 0); 545950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 546950Sbill fprintf(stderr,"swap page %x: ", dblock); 547950Sbill perror("read"); 548950Sbill } 549950Sbill count = 0; 550950Sbill for (i = 0; i < NBPG; i++) 551950Sbill if (corepg[i] != swapg[i]) 552950Sbill count++; 553950Sbill if (count == 0) 554950Sbill vprintf("\tsame"); 555950Sbill return (count); 556950Sbill } 557950Sbill 558950Sbill getu(p) 559950Sbill register struct proc *p; 560950Sbill { 561950Sbill int i, w, cc, errs = 0; 562950Sbill 5632824Swnj if (uflg && (p->p_flag & SLOAD)) 5642824Swnj printf("pid %d u. pages:", p->p_pid); 565950Sbill for (i = 0; i < UPAGES; i++) { 566950Sbill if (p->p_flag & SLOAD) { 5672824Swnj if (uflg) 5682824Swnj printf(" %x", p->p_addr[i].pg_pfnum); 569950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 570950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 571950Sbill perror("core u. read"), errs++; 572950Sbill } else if (fswap >= 0) { 573950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 574950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 575950Sbill perror("swap u. read"), errs++; 576950Sbill } 577950Sbill } 5782824Swnj if (uflg && (p->p_flag & SLOAD)) 5792824Swnj printf("\n"); 580950Sbill return (errs); 581950Sbill } 582950Sbill 583950Sbill char *typepg[] = { 584950Sbill "lost", 585950Sbill "data", 586950Sbill "stack", 587950Sbill "udot", 588950Sbill "paget", 589950Sbill "text", 590950Sbill "free", 591950Sbill "intransit", 592950Sbill }; 593950Sbill 594950Sbill count(p, pte, type) 595950Sbill struct proc *p; 596950Sbill register struct pte *pte; 597950Sbill int type; 598950Sbill { 599950Sbill register int pfnum = pte->pg_pfnum; 600950Sbill register struct paginfo *zp = &paginfo[pfnum]; 601950Sbill int ndif; 602950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 603950Sbill 604950Sbill if (type == ZINTRAN && pfnum == 0) 605950Sbill return; 606950Sbill zprintf("page %x %s", pfnum, typepg[type]); 607950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 608950Sbill zprintf("\n"); 609950Sbill } else { 610950Sbill if (vflg == 0 && type != ZINTRAN) 611950Sbill printf("page %x %s,", pfnum, typepg[type]); 612950Sbill printf(" %d bytes differ\n",ndif); 613950Sbill } 614950Sbill if (pfnum < firstfree || pfnum > maxfree) { 615950Sbill printf("page number out of range:\n"); 616950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 617950Sbill return; 618950Sbill } 619950Sbill if (bad(zp, type)) { 620950Sbill printf("dup page pte %x", *(int *)pte); 621950Sbill dumpcm("", pte->pg_pfnum); 622950Sbill dump(zp); 623950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 624950Sbill return; 625950Sbill } 626950Sbill zp->z_type = type; 627950Sbill zp->z_count++; 628950Sbill zp->z_pid = pid; 629950Sbill zp->z_pte = *pte; 630950Sbill } 631950Sbill 632950Sbill bad(zp, type) 633950Sbill struct paginfo *zp; 634950Sbill { 635950Sbill if (type == ZTEXT) { 636950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 637950Sbill return (1); 638950Sbill return (0); 639950Sbill } 640950Sbill return (zp->z_count); 641950Sbill } 642950Sbill 643950Sbill dump(zp) 644950Sbill struct paginfo *zp; 645950Sbill { 646950Sbill 647950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 648950Sbill } 649950Sbill 650950Sbill summary() 651950Sbill { 652950Sbill register int i; 653950Sbill register struct paginfo *zp; 654950Sbill register int pfnum; 655950Sbill 6562824Swnj for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 657950Sbill zp = &paginfo[i]; 658950Sbill if (zp->z_type == ZLOST) 659950Sbill dumpcm("lost", i); 660950Sbill pfnum = pgtocm(i); 661950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 662950Sbill dumpcm("locked", i); 663950Sbill if (mflg) 664950Sbill dumpcm("mem", i); 665950Sbill } 666950Sbill } 667950Sbill 668950Sbill char *tynames[] = { 669950Sbill "sys", 670950Sbill "text", 671950Sbill "data", 672950Sbill "stack" 673950Sbill }; 674950Sbill dumpcm(cp, pg) 675950Sbill char *cp; 676950Sbill int pg; 677950Sbill { 678950Sbill int pslot; 679950Sbill int cm; 680950Sbill register struct cmap *c; 681950Sbill 682950Sbill cm = pgtocm(pg); 6832824Swnj printf("cm %x %s page %x ", cm, cp, pg); 684950Sbill c = &cmap[cm]; 685950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 686*3795Sroot if (c->c_type == CSYS) 687*3795Sroot goto skip; 688*3795Sroot if (c->c_type != CTEXT) { 689*3795Sroot if (c->c_ndx >= nproc) { 690*3795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 691*3795Sroot goto skip; 692*3795Sroot } 693950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 694*3795Sroot } else { 695*3795Sroot if (c->c_ndx >= ntext) { 696*3795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 697*3795Sroot goto skip; 698*3795Sroot } 699*3795Sroot pslot= (text[c->c_ndx].x_caddr - aproc); 700950Sbill printf(" (=pid"); 701950Sbill for(;;) { 702950Sbill printf(" %d", proc[pslot].p_pid); 703950Sbill if (proc[pslot].p_xlink == 0) 704950Sbill break; 705*3795Sroot pslot= (proc[pslot].p_xlink - aproc); 706950Sbill } 707950Sbill printf(")"); 708950Sbill } 709*3795Sroot skip: 710950Sbill printf("] "); 711950Sbill printf(tynames[c->c_type]); 712950Sbill if (c->c_free) 713950Sbill printf(" free"); 714950Sbill if (c->c_gone) 715950Sbill printf(" gone"); 716950Sbill if (c->c_lock) 717950Sbill printf(" lock"); 718950Sbill if (c->c_want) 719950Sbill printf(" want"); 720950Sbill if (c->c_intrans) 721950Sbill printf(" intrans"); 722950Sbill if (c->c_blkno) 723950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 7242824Swnj if (c->c_hlink) { 7252824Swnj printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 7262824Swnj if (c->c_hlink > ecmx) 7272824Swnj printf(" <<<"); 7282824Swnj } 729950Sbill printf("\n"); 730950Sbill } 731950Sbill 732950Sbill fixfree() 733950Sbill { 734950Sbill register int i, next, prev; 735950Sbill 736950Sbill next = CMHEAD; 737950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 738950Sbill prev = next; 739950Sbill next = cmap[next].c_next; 740950Sbill if (cmap[next].c_free == 0) { 741950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 742950Sbill dumpcm("bad free link in", cmtopg(prev)); 743950Sbill dumpcm("to non free block", cmtopg(next)); 744950Sbill } 745950Sbill if (cmtopg(next) > maxfree) { 746950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 747950Sbill dumpcm("bad link in", cmtopg(prev)); 748950Sbill } 749950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 750950Sbill if (fflg) 751950Sbill dumpcm("free", cmtopg(next)); 752950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 753950Sbill if (fflg) 754950Sbill dumpcm("free", cmtopg(next)+1); 755950Sbill } 756950Sbill } 757950Sbill 758950Sbill get(loc) 759950Sbill unsigned loc; 760950Sbill { 761950Sbill int x; 762950Sbill 763950Sbill lseek(fcore, (long)clear(loc), 0); 764950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 765950Sbill perror("read"); 766950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 767950Sbill return (0); 768950Sbill } 769950Sbill return (x); 770950Sbill } 771950Sbill /* 772950Sbill * Convert a virtual page number 773950Sbill * to its corresponding disk block number. 774950Sbill * Used in pagein/pageout to initiate single page transfers. 775950Sbill */ 776950Sbill vtod(p, v, dmap, smap) 777950Sbill register struct proc *p; 778950Sbill register struct dmap *dmap, *smap; 779950Sbill { 780950Sbill struct dblock db; 781950Sbill 782950Sbill if (v < p->p_tsize) 783950Sbill return(p->p_textp->x_daddr[v / DMTEXT] + v % DMTEXT); 784950Sbill if (isassv(p, v)) 785950Sbill vstodb(vtosp(p, v), 1, smap, &db, 1); 786950Sbill else 787950Sbill vstodb(vtodp(p, v), 1, dmap, &db, 0); 788950Sbill return (db.db_base); 789950Sbill } 790950Sbill 791950Sbill /* 792950Sbill * Convert a pte pointer to 793950Sbill * a virtual page number. 794950Sbill */ 795950Sbill ptetov(p, pte) 796950Sbill register struct proc *p; 797950Sbill register struct pte *pte; 798950Sbill { 799950Sbill 800950Sbill if (isatpte(p, pte)) 801950Sbill return (tptov(p, ptetotp(p, pte))); 802950Sbill else if (isadpte(p, pte)) 803950Sbill return (dptov(p, ptetodp(p, pte))); 804950Sbill else 805950Sbill return (sptov(p, ptetosp(p, pte))); 806950Sbill } 807950Sbill 808950Sbill /* 809950Sbill * Given a base/size pair in virtual swap area, 810950Sbill * return a physical base/size pair which is the 811950Sbill * (largest) initial, physically contiguous block. 812950Sbill */ 813950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 814950Sbill register int vsbase; 815950Sbill int vssize; 816950Sbill register struct dmap *dmp; 817950Sbill register struct dblock *dbp; 818950Sbill { 819950Sbill register int blk = DMMIN; 820950Sbill register swblk_t *ip = dmp->dm_map; 821950Sbill 822950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 823950Sbill panic("vstodb"); 824950Sbill while (vsbase >= blk) { 825950Sbill vsbase -= blk; 826950Sbill if (blk < DMMAX) 827950Sbill blk *= 2; 828950Sbill ip++; 829950Sbill } 830950Sbill dbp->db_size = min(vssize, blk - vsbase); 831950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 832950Sbill } 833950Sbill 834950Sbill panic(cp) 835950Sbill char *cp; 836950Sbill { 837950Sbill printf("panic!: %s\n", cp); 838950Sbill } 839950Sbill 840950Sbill min(a, b) 841950Sbill { 842950Sbill return (a < b ? a : b); 843950Sbill } 844