1*10809Ssam static char *sccsid = "@(#)analyze.c 4.6 (Berkeley) 02/09/83"; 2950Sbill #include <stdio.h> 3950Sbill #include <sys/param.h> 4950Sbill #include <sys/dir.h> 59891Ssam #include <machine/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 30*10809Ssam #ifdef vax 31950Sbill #define clear(x) ((int)x & 0x7fffffff) 32*10809Ssam #else 33*10809Ssam #define clear(x) ((int)x) 34*10809Ssam #endif 35950Sbill 363795Sroot struct proc *proc, *aproc; 373526Sroot int nproc; 383795Sroot struct text *text, *atext; 393526Sroot int ntext; 403526Sroot struct mapent *swapmap; 413526Sroot int nswapmap; 42950Sbill struct cmap *cmap; 432824Swnj int ecmx; 44950Sbill struct pte *usrpt; 45950Sbill struct pte *Usrptma; 46950Sbill int firstfree; 47950Sbill int maxfree; 48950Sbill int freemem; 49950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 50950Sbill int pid; 51950Sbill 52950Sbill struct paginfo { 53950Sbill char z_type; 54950Sbill char z_count; 55950Sbill short z_pid; 56950Sbill struct pte z_pte; 57950Sbill } *paginfo; 58950Sbill #define ZLOST 0 59950Sbill #define ZDATA 1 60950Sbill #define ZSTACK 2 61950Sbill #define ZUDOT 3 62950Sbill #define ZPAGET 4 63950Sbill #define ZTEXT 5 64950Sbill #define ZFREE 6 65950Sbill #define ZINTRAN 7 66950Sbill 67950Sbill struct dblks { 68950Sbill short d_first; 69950Sbill short d_size; 70950Sbill char d_type; 71950Sbill char d_index; 723526Sroot } *dblks; 73950Sbill int ndblks; 74950Sbill 75950Sbill #define DFREE 0 76950Sbill #define DDATA 1 77950Sbill #define DSTACK 2 78950Sbill #define DTEXT 3 79950Sbill #define DUDOT 4 80950Sbill #define DPAGET 5 81950Sbill 82950Sbill union { 83*10809Ssam char buf[UPAGES][NBPG]; 84950Sbill struct user U; 85950Sbill } u_area; 86950Sbill #define u u_area.U 87950Sbill 88950Sbill int fcore = -1; 89950Sbill int fswap = -1; 90950Sbill 91950Sbill struct nlist nl[] = { 92950Sbill #define X_PROC 0 93950Sbill { "_proc" }, 94950Sbill #define X_USRPT 1 95950Sbill { "_usrpt" }, 96950Sbill #define X_PTMA 2 972824Swnj { "_Usrptmap" }, 98950Sbill #define X_FIRSTFREE 3 992824Swnj { "_firstfree" }, 100950Sbill #define X_MAXFREE 4 101950Sbill { "_maxfree" }, 102950Sbill #define X_TEXT 5 103950Sbill { "_text" }, 104950Sbill #define X_FREEMEM 6 105950Sbill { "_freemem" }, 106950Sbill #define X_CMAP 7 107950Sbill { "_cmap" }, 108950Sbill #define X_ECMAP 8 109950Sbill { "_ecmap" }, 110950Sbill #define X_SWAPMAP 9 111950Sbill { "_swapmap" }, 1123526Sroot #define X_NPROC 10 1133526Sroot { "_nproc" }, 1143526Sroot #define X_NTEXT 11 1153526Sroot { "_ntext" }, 1163526Sroot #define X_NSWAPMAP 12 1173526Sroot { "_nswapmap" }, 118950Sbill { 0 } 119950Sbill }; 120950Sbill 121950Sbill main(argc, argv) 122950Sbill int argc; 123950Sbill char **argv; 124950Sbill { 125950Sbill register struct nlist *np; 126950Sbill register struct proc *p; 127950Sbill register struct text *xp; 128950Sbill register struct pte *pte; 129950Sbill register int i; 130950Sbill int w, a; 131950Sbill 132*10809Ssam #ifdef DEBUG 133*10809Ssam setbuf(stdout, NULL); 134*10809Ssam #endif 135950Sbill argc--, argv++; 136950Sbill while (argc > 0 && argv[0][0] == '-') { 137950Sbill register char *cp = *argv++; 138950Sbill argc--; 139950Sbill while (*++cp) switch (*cp) { 140950Sbill 141950Sbill case 'm': 142950Sbill mflg++; 143950Sbill break; 144950Sbill 145950Sbill case 'v': 146950Sbill vflg++; 147950Sbill break; 148950Sbill 149950Sbill case 's': 150950Sbill if (argc < 2) 151950Sbill goto usage; 152950Sbill if ((fswap = open(argv[0], 0)) < 0) { 153950Sbill perror(argv[0]); 154950Sbill exit(1); 155950Sbill } 156950Sbill argc--,argv++; 157950Sbill sflg++; 158950Sbill break; 159950Sbill 160950Sbill case 'f': 161950Sbill fflg++; 162950Sbill break; 163950Sbill 164950Sbill case 'D': 165950Sbill Dflg++; 166950Sbill break; 167950Sbill 168950Sbill case 'd': 169950Sbill dflg++; 170950Sbill break; 171950Sbill 1722824Swnj case 'u': 1732824Swnj uflg++; 1742824Swnj break; 1752824Swnj 176950Sbill default: 177950Sbill goto usage; 178950Sbill } 179950Sbill } 180950Sbill if (argc < 1) { 181950Sbill usage: 182950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 183950Sbill exit(1); 184950Sbill } 185950Sbill close(0); 186950Sbill if ((fcore = open(argv[0], 0)) < 0) { 187950Sbill perror(argv[0]); 188950Sbill exit(1); 189950Sbill } 190950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 191950Sbill if (nl[0].n_value == 0) { 192950Sbill fprintf(stderr, "%s: bad namelist\n", 193950Sbill argc > 1 ? argv[1] : "/vmunix"); 194950Sbill exit(1); 195950Sbill } 196*10809Ssam for (np = nl; np->n_name; np++) 197950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 198950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 199950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 200950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 201950Sbill maxfree = get(nl[X_MAXFREE].n_value); 202950Sbill freemem = get(nl[X_FREEMEM].n_value); 203950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 204950Sbill if (paginfo == NULL) { 205950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 206950Sbill exit(1); 207950Sbill } 208950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 209950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 2103795Sroot { 2113526Sroot lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 2123526Sroot read(fcore, (char *)&aproc, sizeof aproc); 2133526Sroot lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0); 2143526Sroot read(fcore, (char *)&nproc, sizeof nproc); 2153526Sroot printf("%d procs\n", nproc); 2163526Sroot proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 2173526Sroot lseek(fcore, (long)clear(aproc), 0); 2183526Sroot if (read(fcore, (char *)proc, nproc * sizeof (struct proc)) 2193526Sroot != nproc * sizeof (struct proc)) { 220950Sbill perror("proc read"); 221950Sbill exit(1); 2223526Sroot } 223950Sbill } 2243795Sroot { 2253526Sroot lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 2263526Sroot read(fcore, (char *)&atext, sizeof atext); 2273526Sroot lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0); 2283526Sroot read(fcore, (char *)&ntext, sizeof ntext); 2293526Sroot printf("%d texts\n", ntext); 2303526Sroot text = (struct text *)calloc(ntext, sizeof (struct text)); 2313526Sroot lseek(fcore, (long)clear(atext), 0); 2323526Sroot if (read(fcore, (char *)text, ntext * sizeof (struct text)) 2333526Sroot != ntext * sizeof (struct text)) { 234950Sbill perror("text read"); 235950Sbill exit(1); 2363526Sroot } 237950Sbill } 238950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 2392824Swnj ecmx = i / sizeof (struct cmap); 240950Sbill cmap = (struct cmap *)calloc(i, 1); 241950Sbill if (cmap == NULL) { 242950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 243950Sbill exit(1); 244950Sbill } 245950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 246950Sbill if (read(fcore, (char *)cmap, i) != i) { 247950Sbill perror("cmap read"); 248950Sbill exit(1); 249950Sbill } 2503526Sroot { struct mapent *aswapmap; 2513526Sroot lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 2523526Sroot read(fcore, (char *)&aswapmap, sizeof aswapmap); 2533526Sroot lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0); 2543526Sroot read(fcore, (char *)&nswapmap, sizeof nswapmap); 2553526Sroot nswapmap--; 2563526Sroot printf("%d swapmap entries\n", nswapmap); 2573526Sroot swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent)); 2583526Sroot dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks)); 2593526Sroot lseek(fcore, (long)clear(aswapmap+1), 0); 2603526Sroot if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent)) 2613526Sroot != nswapmap * sizeof (struct mapent)) { 262950Sbill perror("swapmap read"); 263950Sbill exit(1); 2643526Sroot } 265950Sbill } 2663526Sroot for (p = &proc[1]; p < proc+nproc; p++) { 267950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 268950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 269950Sbill if (p->p_stat == 0) 270950Sbill continue; 271950Sbill printf("proc %d ", p->p_pid); 272950Sbill if (p->p_stat == SZOMB) { 273950Sbill printf("zombie\n"); 274950Sbill continue; 275950Sbill } 276950Sbill if (p->p_flag & SLOAD) { 277950Sbill printf("loaded, p0br %x, ", p->p_p0br); 278950Sbill printf("%d pages of page tables:", p->p_szpt); 279950Sbill a = btokmx(p->p_p0br); 280950Sbill for (i = 0; i < p->p_szpt; i++) { 281950Sbill w = get(&Usrptma[a + i]); 282950Sbill printf(" %x", w & PG_PFNUM); 283950Sbill } 284950Sbill printf("\n"); 285950Sbill for(i = 0; i < p->p_szpt; i++) { 286950Sbill w = get(&Usrptma[a + i]); 287950Sbill if (getpt(w, i)) 288950Sbill count(p, (struct pte *)&w, ZPAGET); 289950Sbill } 290950Sbill } else { 291950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 292950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 293950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 294*10809Ssam duse(p->p_swaddr, ctod(clrnd(UPAGES)), DUDOT, p - proc); 295950Sbill duse(p->p_swaddr + ctod(UPAGES), 296*10809Ssam ctod(clrnd(i - p->p_tsize / NPTEPG)), 297*10809Ssam DPAGET, p - proc); 298950Sbill /* i, DPAGET, p - proc); */ 299950Sbill } 300950Sbill p->p_p0br = (struct pte *)p0br; 301950Sbill p->p_addr = uaddr(p); 302*10809Ssam if (p->p_textp) 303*10809Ssam p->p_textp = &text[p->p_textp - atext]; 304950Sbill if (p->p_pid == 2) 305950Sbill continue; 306950Sbill if (getu(p)) 307950Sbill continue; 308950Sbill u.u_procp = p; 309950Sbill pdmap(); 310950Sbill if ((p->p_flag & SLOAD) == 0) 311950Sbill continue; 312950Sbill pid = p->p_pid; 313950Sbill for (i = 0; i < p->p_tsize; i++) { 314950Sbill pte = tptopte(p, i); 315950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 316950Sbill continue; 317950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 318950Sbill count(p, pte, ZINTRAN); 319950Sbill else 320950Sbill count(p, pte, ZTEXT); 321950Sbill } 322950Sbill vprintf("\n"); 323950Sbill for (i = 0; i < p->p_dsize; i++) { 324950Sbill pte = dptopte(p, i); 325950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 326950Sbill continue; 327950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 328950Sbill count(p, pte, ZINTRAN); 329950Sbill else 330950Sbill count(p, pte, ZDATA); 331950Sbill } 332950Sbill vprintf("\n"); 333950Sbill for (i = 0; i < p->p_ssize; i++) { 334950Sbill pte = sptopte(p, i); 335950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 336950Sbill continue; 337950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 338950Sbill count(p, pte, ZINTRAN); 339950Sbill else 340950Sbill count(p, pte, ZSTACK); 341950Sbill } 342950Sbill vprintf("\n"); 343950Sbill for (i = 0; i < UPAGES; i++) 344950Sbill count(p, &p->p_addr[i], ZUDOT); 345950Sbill vprintf("\n"); 346950Sbill vprintf("\n"); 347950Sbill } 3483526Sroot for (xp = &text[0]; xp < text+ntext; xp++) 349950Sbill if (xp->x_iptr) { 350*10809Ssam int size = ctod(xp->x_size); 351*10809Ssam 352*10809Ssam for (i = 0; i < size; i += DMTEXT) 353950Sbill duse(xp->x_daddr[i], 354*10809Ssam (size - i) > DMTEXT 355*10809Ssam ? DMTEXT : size - i, 356950Sbill DTEXT, xp - text); 357950Sbill if (xp->x_flag & XPAGI) 358*10809Ssam duse(xp->x_ptdaddr, 359*10809Ssam ctod(clrnd(ctopt(xp->x_size))), 360950Sbill DTEXT, xp - text); 361950Sbill } 362950Sbill dmcheck(); 363950Sbill fixfree(); 364950Sbill summary(); 365950Sbill exit(0); 366950Sbill } 367950Sbill 368950Sbill pdmap() 369950Sbill { 370950Sbill register struct text *xp; 371950Sbill 372950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 373950Sbill return; 374950Sbill if (Dflg) 375950Sbill printf("disk for pid %d", u.u_procp->p_pid); 376950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 377950Sbill ptdmap(xp->x_daddr, xp->x_size); 378950Sbill pdmseg("data", &u.u_dmap, DDATA); 379950Sbill pdmseg("stack", &u.u_smap, DSTACK); 380950Sbill if (Dflg) 381950Sbill printf("\n"); 382950Sbill } 383950Sbill 384950Sbill ptdmap(dp, size) 385950Sbill register daddr_t *dp; 386950Sbill int size; 387950Sbill { 388950Sbill register int i; 389950Sbill int rem; 390950Sbill 391950Sbill if (Dflg) 392950Sbill printf(" text:"); 393950Sbill for (i = 0, rem = size; rem > 0; i++) { 394950Sbill if (Dflg) 395950Sbill printf(" %x<%x>", dp[i], rem < DMTEXT ? rem : DMTEXT); 396950Sbill rem -= rem < DMTEXT ? rem : DMTEXT; 397950Sbill } 398950Sbill } 399950Sbill 400950Sbill pdmseg(cp, dmp, type) 401950Sbill char *cp; 402950Sbill struct dmap *dmp; 403950Sbill { 404950Sbill register int i; 405950Sbill int b, rem; 406950Sbill 407950Sbill if (Dflg) 408950Sbill printf(", %s:", cp); 409950Sbill b = DMMIN; 410950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 411950Sbill if (Dflg) 412950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 413950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 414950Sbill rem -= b; 415950Sbill if (b < DMMAX) 416950Sbill b *= 2; 417950Sbill } 418950Sbill } 419950Sbill 420950Sbill duse(first, size, type, index) 421950Sbill { 422950Sbill register struct dblks *dp; 423950Sbill 424950Sbill if (fswap == -1) 425950Sbill return; 426950Sbill dp = &dblks[ndblks]; 4273526Sroot if (++ndblks > 2*nswapmap) { 4283526Sroot fprintf(stderr, "too many disk blocks\n"); 429950Sbill exit(1); 430950Sbill } 431950Sbill dp->d_first = first; 432950Sbill dp->d_size = size; 433950Sbill dp->d_type = type; 434950Sbill dp->d_index = index; 435950Sbill } 436950Sbill 437950Sbill dsort(d, e) 438950Sbill register struct dblks *d, *e; 439950Sbill { 440950Sbill 441950Sbill return (e->d_first - d->d_first); 442950Sbill } 443950Sbill 444950Sbill dmcheck() 445950Sbill { 4463526Sroot register struct mapent *smp; 447950Sbill register struct dblks *d, *e; 448950Sbill 449950Sbill for (smp = swapmap; smp->m_size; smp++) 450950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 451*10809Ssam duse(ctod(CLSIZE), DMTEXT - ctod(CLSIZE), DFREE, 0); 452950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 453950Sbill d = &dblks[ndblks - 1]; 454950Sbill if (d->d_first > 1) 455950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 456950Sbill for (; d > dblks; d--) { 457950Sbill if (dflg) 458950Sbill dprint(d); 459950Sbill e = d - 1; 460950Sbill if (d->d_first + d->d_size > e->d_first) { 461950Sbill printf("overlap in swap mappings:\n"); 462950Sbill dprint(d); 463950Sbill dprint(e); 464950Sbill } else if (d->d_first + d->d_size < e->d_first) { 465950Sbill printf("lost swap map: start %x size %x\n", 466950Sbill d->d_first + d->d_size, 467950Sbill e->d_first - (d->d_first + d->d_size)); 468950Sbill } 469950Sbill } 470950Sbill if (dflg) 471950Sbill dprint(dblks); 472950Sbill if (sflg) 473950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 474950Sbill } 475950Sbill 476950Sbill char *dnames[] = { 477950Sbill "DFREE", 478950Sbill "DDATA", 479950Sbill "DSTACK", 480950Sbill "DTEXT", 481950Sbill "DUDOT", 482950Sbill "DPAGET", 483950Sbill }; 484950Sbill 485950Sbill dprint(d) 486950Sbill register struct dblks *d; 487950Sbill { 488950Sbill 489950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 490950Sbill dnames[d->d_type]); 491950Sbill switch (d->d_type) { 492950Sbill 493950Sbill case DSTACK: 494950Sbill case DDATA: 495950Sbill printf(" pid %d", proc[d->d_index].p_pid); 496950Sbill break; 497950Sbill } 498950Sbill printf("\n"); 499950Sbill } 500950Sbill 501950Sbill getpt(x, i) 502950Sbill int x, i; 503950Sbill { 504950Sbill 505950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 506950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 507950Sbill perror("read"); 508950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 509950Sbill return (0); 510950Sbill } 511950Sbill return (1); 512950Sbill } 513950Sbill 514950Sbill checkpg(p, pte, type) 515950Sbill register struct pte *pte; 516950Sbill register struct proc *p; 517950Sbill int type; 518950Sbill { 519950Sbill char corepg[NBPG], swapg[NBPG]; 520950Sbill register int i, count, dblock; 521950Sbill register int pfnum = pte->pg_pfnum; 522950Sbill 523950Sbill if (type == ZPAGET || type == ZUDOT) 524950Sbill return (0); 525950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 526950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 527950Sbill perror("read"); 528950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 529950Sbill return (0); 530950Sbill } 531950Sbill switch (type) { 532950Sbill 533950Sbill case ZDATA: 534950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 535950Sbill return (0); 536950Sbill break; 537950Sbill 538950Sbill case ZTEXT: 539950Sbill break; 540950Sbill 541950Sbill case ZSTACK: 542950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 543950Sbill return (0); 544950Sbill break; 545950Sbill 546950Sbill default: 547950Sbill return(0); 548950Sbill break; 549950Sbill } 550950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 551950Sbill vprintf(" %x", dblock); 552950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 553950Sbill return (0); 554950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 555950Sbill return (0); 556*10809Ssam lseek(fswap, (long)(DEV_BSIZE * dblock), 0); 557950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 558950Sbill fprintf(stderr,"swap page %x: ", dblock); 559950Sbill perror("read"); 560950Sbill } 561950Sbill count = 0; 562950Sbill for (i = 0; i < NBPG; i++) 563950Sbill if (corepg[i] != swapg[i]) 564950Sbill count++; 565950Sbill if (count == 0) 566950Sbill vprintf("\tsame"); 567950Sbill return (count); 568950Sbill } 569950Sbill 570950Sbill getu(p) 571950Sbill register struct proc *p; 572950Sbill { 573950Sbill int i, w, cc, errs = 0; 574950Sbill 5752824Swnj if (uflg && (p->p_flag & SLOAD)) 5762824Swnj printf("pid %d u. pages:", p->p_pid); 577950Sbill for (i = 0; i < UPAGES; i++) { 578950Sbill if (p->p_flag & SLOAD) { 5792824Swnj if (uflg) 5802824Swnj printf(" %x", p->p_addr[i].pg_pfnum); 581950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 582950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 583950Sbill perror("core u. read"), errs++; 584950Sbill } else if (fswap >= 0) { 585950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 586950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 587950Sbill perror("swap u. read"), errs++; 588950Sbill } 589950Sbill } 5902824Swnj if (uflg && (p->p_flag & SLOAD)) 5912824Swnj printf("\n"); 592950Sbill return (errs); 593950Sbill } 594950Sbill 595950Sbill char *typepg[] = { 596950Sbill "lost", 597950Sbill "data", 598950Sbill "stack", 599950Sbill "udot", 600950Sbill "paget", 601950Sbill "text", 602950Sbill "free", 603950Sbill "intransit", 604950Sbill }; 605950Sbill 606950Sbill count(p, pte, type) 607950Sbill struct proc *p; 608950Sbill register struct pte *pte; 609950Sbill int type; 610950Sbill { 611950Sbill register int pfnum = pte->pg_pfnum; 612950Sbill register struct paginfo *zp = &paginfo[pfnum]; 613950Sbill int ndif; 614950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 615950Sbill 616950Sbill if (type == ZINTRAN && pfnum == 0) 617950Sbill return; 618950Sbill zprintf("page %x %s", pfnum, typepg[type]); 619950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 620950Sbill zprintf("\n"); 621950Sbill } else { 622950Sbill if (vflg == 0 && type != ZINTRAN) 623950Sbill printf("page %x %s,", pfnum, typepg[type]); 624950Sbill printf(" %d bytes differ\n",ndif); 625950Sbill } 626950Sbill if (pfnum < firstfree || pfnum > maxfree) { 627950Sbill printf("page number out of range:\n"); 628950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 629950Sbill return; 630950Sbill } 631950Sbill if (bad(zp, type)) { 632950Sbill printf("dup page pte %x", *(int *)pte); 633950Sbill dumpcm("", pte->pg_pfnum); 634950Sbill dump(zp); 635950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 636950Sbill return; 637950Sbill } 638950Sbill zp->z_type = type; 639950Sbill zp->z_count++; 640950Sbill zp->z_pid = pid; 641950Sbill zp->z_pte = *pte; 642950Sbill } 643950Sbill 644950Sbill bad(zp, type) 645950Sbill struct paginfo *zp; 646950Sbill { 647950Sbill if (type == ZTEXT) { 648950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 649950Sbill return (1); 650950Sbill return (0); 651950Sbill } 652950Sbill return (zp->z_count); 653950Sbill } 654950Sbill 655950Sbill dump(zp) 656950Sbill struct paginfo *zp; 657950Sbill { 658950Sbill 659950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 660950Sbill } 661950Sbill 662950Sbill summary() 663950Sbill { 664950Sbill register int i; 665950Sbill register struct paginfo *zp; 666950Sbill register int pfnum; 667950Sbill 6682824Swnj for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 669950Sbill zp = &paginfo[i]; 670950Sbill if (zp->z_type == ZLOST) 671950Sbill dumpcm("lost", i); 672950Sbill pfnum = pgtocm(i); 673950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 674950Sbill dumpcm("locked", i); 675950Sbill if (mflg) 676950Sbill dumpcm("mem", i); 677950Sbill } 678950Sbill } 679950Sbill 680950Sbill char *tynames[] = { 681950Sbill "sys", 682950Sbill "text", 683950Sbill "data", 684950Sbill "stack" 685950Sbill }; 686950Sbill dumpcm(cp, pg) 687950Sbill char *cp; 688950Sbill int pg; 689950Sbill { 690950Sbill int pslot; 691950Sbill int cm; 692950Sbill register struct cmap *c; 693950Sbill 694950Sbill cm = pgtocm(pg); 6952824Swnj printf("cm %x %s page %x ", cm, cp, pg); 696950Sbill c = &cmap[cm]; 697950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 6983795Sroot if (c->c_type == CSYS) 6993795Sroot goto skip; 7003795Sroot if (c->c_type != CTEXT) { 7013795Sroot if (c->c_ndx >= nproc) { 7023795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7033795Sroot goto skip; 7043795Sroot } 705950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 7063795Sroot } else { 7073795Sroot if (c->c_ndx >= ntext) { 7083795Sroot printf(" [text c->c_ndx %d?]", c->c_ndx); 7093795Sroot goto skip; 7103795Sroot } 7113795Sroot pslot= (text[c->c_ndx].x_caddr - aproc); 712950Sbill printf(" (=pid"); 713950Sbill for(;;) { 714950Sbill printf(" %d", proc[pslot].p_pid); 715950Sbill if (proc[pslot].p_xlink == 0) 716950Sbill break; 7173795Sroot pslot= (proc[pslot].p_xlink - aproc); 718950Sbill } 719950Sbill printf(")"); 720950Sbill } 7213795Sroot skip: 722950Sbill printf("] "); 723950Sbill printf(tynames[c->c_type]); 724950Sbill if (c->c_free) 725950Sbill printf(" free"); 726950Sbill if (c->c_gone) 727950Sbill printf(" gone"); 728950Sbill if (c->c_lock) 729950Sbill printf(" lock"); 730950Sbill if (c->c_want) 731950Sbill printf(" want"); 732950Sbill if (c->c_intrans) 733950Sbill printf(" intrans"); 734950Sbill if (c->c_blkno) 735950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 7362824Swnj if (c->c_hlink) { 7372824Swnj printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 7382824Swnj if (c->c_hlink > ecmx) 7392824Swnj printf(" <<<"); 7402824Swnj } 741950Sbill printf("\n"); 742950Sbill } 743950Sbill 744950Sbill fixfree() 745950Sbill { 746950Sbill register int i, next, prev; 747950Sbill 748950Sbill next = CMHEAD; 749950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 750950Sbill prev = next; 751950Sbill next = cmap[next].c_next; 752950Sbill if (cmap[next].c_free == 0) { 753950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 754950Sbill dumpcm("bad free link in", cmtopg(prev)); 755950Sbill dumpcm("to non free block", cmtopg(next)); 756950Sbill } 757950Sbill if (cmtopg(next) > maxfree) { 758950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 759950Sbill dumpcm("bad link in", cmtopg(prev)); 760950Sbill } 761950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 762950Sbill if (fflg) 763950Sbill dumpcm("free", cmtopg(next)); 764950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 765950Sbill if (fflg) 766950Sbill dumpcm("free", cmtopg(next)+1); 767950Sbill } 768950Sbill } 769950Sbill 770950Sbill get(loc) 771950Sbill unsigned loc; 772950Sbill { 773950Sbill int x; 774950Sbill 775950Sbill lseek(fcore, (long)clear(loc), 0); 776950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 777950Sbill perror("read"); 778950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 779950Sbill return (0); 780950Sbill } 781950Sbill return (x); 782950Sbill } 783950Sbill /* 784950Sbill * Convert a virtual page number 785950Sbill * to its corresponding disk block number. 786950Sbill * Used in pagein/pageout to initiate single page transfers. 787950Sbill */ 788950Sbill vtod(p, v, dmap, smap) 789950Sbill register struct proc *p; 790950Sbill register struct dmap *dmap, *smap; 791950Sbill { 792950Sbill struct dblock db; 793950Sbill 794*10809Ssam if (isatsv(p, v)) { 795*10809Ssam v = ctod(vtotp(p, v)); 796950Sbill return(p->p_textp->x_daddr[v / DMTEXT] + v % DMTEXT); 797*10809Ssam } 798950Sbill if (isassv(p, v)) 799*10809Ssam vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1); 800950Sbill else 801*10809Ssam vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0); 802950Sbill return (db.db_base); 803950Sbill } 804950Sbill 805950Sbill /* 806950Sbill * Convert a pte pointer to 807950Sbill * a virtual page number. 808950Sbill */ 809950Sbill ptetov(p, pte) 810950Sbill register struct proc *p; 811950Sbill register struct pte *pte; 812950Sbill { 813950Sbill 814950Sbill if (isatpte(p, pte)) 815950Sbill return (tptov(p, ptetotp(p, pte))); 816950Sbill else if (isadpte(p, pte)) 817950Sbill return (dptov(p, ptetodp(p, pte))); 818950Sbill else 819950Sbill return (sptov(p, ptetosp(p, pte))); 820950Sbill } 821950Sbill 822950Sbill /* 823950Sbill * Given a base/size pair in virtual swap area, 824950Sbill * return a physical base/size pair which is the 825950Sbill * (largest) initial, physically contiguous block. 826950Sbill */ 827950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 828950Sbill register int vsbase; 829950Sbill int vssize; 830950Sbill register struct dmap *dmp; 831950Sbill register struct dblock *dbp; 832950Sbill { 833950Sbill register int blk = DMMIN; 834950Sbill register swblk_t *ip = dmp->dm_map; 835950Sbill 836950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 837950Sbill panic("vstodb"); 838950Sbill while (vsbase >= blk) { 839950Sbill vsbase -= blk; 840950Sbill if (blk < DMMAX) 841950Sbill blk *= 2; 842950Sbill ip++; 843950Sbill } 844950Sbill dbp->db_size = min(vssize, blk - vsbase); 845950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 846950Sbill } 847950Sbill 848950Sbill panic(cp) 849950Sbill char *cp; 850950Sbill { 851950Sbill printf("panic!: %s\n", cp); 852950Sbill } 853950Sbill 854950Sbill min(a, b) 855950Sbill { 856950Sbill return (a < b ? a : b); 857950Sbill } 858