1*950Sbill static char *sccsid = "@(#)analyze.c 4.1 (Berkeley) 10/01/80"; 2*950Sbill #include <stdio.h> 3*950Sbill #include <sys/param.h> 4*950Sbill #include <sys/dir.h> 5*950Sbill #include <sys/pte.h> 6*950Sbill #include <nlist.h> 7*950Sbill #include <sys/map.h> 8*950Sbill #include <sys/user.h> 9*950Sbill #include <sys/proc.h> 10*950Sbill #include <sys/text.h> 11*950Sbill #include <sys/cmap.h> 12*950Sbill #include <sys/vm.h> 13*950Sbill 14*950Sbill /* 15*950Sbill * Analyze - analyze a core (and optional paging area) saved from 16*950Sbill * a virtual Unix system crash. 17*950Sbill */ 18*950Sbill 19*950Sbill int Dflg; 20*950Sbill int dflg; 21*950Sbill int vflg; 22*950Sbill int mflg; 23*950Sbill int fflg; 24*950Sbill int sflg; 25*950Sbill 26*950Sbill /* use vprintf with care; it plays havoc with ``else's'' */ 27*950Sbill #define vprintf if (vflg) printf 28*950Sbill 29*950Sbill #define clear(x) ((int)x & 0x7fffffff) 30*950Sbill 31*950Sbill struct proc proc[NPROC]; 32*950Sbill struct text text[NTEXT]; 33*950Sbill struct map swapmap[SMAPSIZ]; 34*950Sbill struct cmap *cmap; 35*950Sbill struct pte *usrpt; 36*950Sbill struct pte *Usrptma; 37*950Sbill int firstfree; 38*950Sbill int maxfree; 39*950Sbill int freemem; 40*950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 41*950Sbill int pid; 42*950Sbill 43*950Sbill struct paginfo { 44*950Sbill char z_type; 45*950Sbill char z_count; 46*950Sbill short z_pid; 47*950Sbill struct pte z_pte; 48*950Sbill } *paginfo; 49*950Sbill #define ZLOST 0 50*950Sbill #define ZDATA 1 51*950Sbill #define ZSTACK 2 52*950Sbill #define ZUDOT 3 53*950Sbill #define ZPAGET 4 54*950Sbill #define ZTEXT 5 55*950Sbill #define ZFREE 6 56*950Sbill #define ZINTRAN 7 57*950Sbill 58*950Sbill #define NDBLKS (2*SMAPSIZ) 59*950Sbill struct dblks { 60*950Sbill short d_first; 61*950Sbill short d_size; 62*950Sbill char d_type; 63*950Sbill char d_index; 64*950Sbill } dblks[NDBLKS]; 65*950Sbill int ndblks; 66*950Sbill 67*950Sbill #define DFREE 0 68*950Sbill #define DDATA 1 69*950Sbill #define DSTACK 2 70*950Sbill #define DTEXT 3 71*950Sbill #define DUDOT 4 72*950Sbill #define DPAGET 5 73*950Sbill 74*950Sbill union { 75*950Sbill char buf[UPAGES][512]; 76*950Sbill struct user U; 77*950Sbill } u_area; 78*950Sbill #define u u_area.U 79*950Sbill 80*950Sbill int fcore = -1; 81*950Sbill int fswap = -1; 82*950Sbill 83*950Sbill struct nlist nl[] = { 84*950Sbill #define X_PROC 0 85*950Sbill { "_proc" }, 86*950Sbill #define X_USRPT 1 87*950Sbill { "_usrpt" }, 88*950Sbill #define X_PTMA 2 89*950Sbill { "_Usrptma" }, 90*950Sbill #define X_FIRSTFREE 3 91*950Sbill { "_firstfr" }, 92*950Sbill #define X_MAXFREE 4 93*950Sbill { "_maxfree" }, 94*950Sbill #define X_TEXT 5 95*950Sbill { "_text" }, 96*950Sbill #define X_FREEMEM 6 97*950Sbill { "_freemem" }, 98*950Sbill #define X_CMAP 7 99*950Sbill { "_cmap" }, 100*950Sbill #define X_ECMAP 8 101*950Sbill { "_ecmap" }, 102*950Sbill #define X_SWAPMAP 9 103*950Sbill { "_swapmap" }, 104*950Sbill { 0 } 105*950Sbill }; 106*950Sbill 107*950Sbill main(argc, argv) 108*950Sbill int argc; 109*950Sbill char **argv; 110*950Sbill { 111*950Sbill register struct nlist *np; 112*950Sbill register struct proc *p; 113*950Sbill register struct text *xp; 114*950Sbill register struct pte *pte; 115*950Sbill register int i; 116*950Sbill int w, a; 117*950Sbill 118*950Sbill argc--, argv++; 119*950Sbill while (argc > 0 && argv[0][0] == '-') { 120*950Sbill register char *cp = *argv++; 121*950Sbill argc--; 122*950Sbill while (*++cp) switch (*cp) { 123*950Sbill 124*950Sbill case 'm': 125*950Sbill mflg++; 126*950Sbill break; 127*950Sbill 128*950Sbill case 'v': 129*950Sbill vflg++; 130*950Sbill break; 131*950Sbill 132*950Sbill case 's': 133*950Sbill if (argc < 2) 134*950Sbill goto usage; 135*950Sbill if ((fswap = open(argv[0], 0)) < 0) { 136*950Sbill perror(argv[0]); 137*950Sbill exit(1); 138*950Sbill } 139*950Sbill argc--,argv++; 140*950Sbill sflg++; 141*950Sbill break; 142*950Sbill 143*950Sbill case 'f': 144*950Sbill fflg++; 145*950Sbill break; 146*950Sbill 147*950Sbill case 'D': 148*950Sbill Dflg++; 149*950Sbill break; 150*950Sbill 151*950Sbill case 'd': 152*950Sbill dflg++; 153*950Sbill break; 154*950Sbill 155*950Sbill default: 156*950Sbill goto usage; 157*950Sbill } 158*950Sbill } 159*950Sbill if (argc < 1) { 160*950Sbill usage: 161*950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 162*950Sbill exit(1); 163*950Sbill } 164*950Sbill close(0); 165*950Sbill if ((fcore = open(argv[0], 0)) < 0) { 166*950Sbill perror(argv[0]); 167*950Sbill exit(1); 168*950Sbill } 169*950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 170*950Sbill if (nl[0].n_value == 0) { 171*950Sbill fprintf(stderr, "%s: bad namelist\n", 172*950Sbill argc > 1 ? argv[1] : "/vmunix"); 173*950Sbill exit(1); 174*950Sbill } 175*950Sbill for (np = nl; np->n_name[0]; np++) 176*950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 177*950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 178*950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 179*950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 180*950Sbill maxfree = get(nl[X_MAXFREE].n_value); 181*950Sbill freemem = get(nl[X_FREEMEM].n_value); 182*950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 183*950Sbill if (paginfo == NULL) { 184*950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 185*950Sbill exit(1); 186*950Sbill } 187*950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 188*950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 189*950Sbill lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 190*950Sbill if (read(fcore, (char *)proc, sizeof proc) != sizeof proc) { 191*950Sbill perror("proc read"); 192*950Sbill exit(1); 193*950Sbill } 194*950Sbill lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 195*950Sbill if (read(fcore, (char *)text, sizeof text) != sizeof text) { 196*950Sbill perror("text read"); 197*950Sbill exit(1); 198*950Sbill } 199*950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 200*950Sbill cmap = (struct cmap *)calloc(i, 1); 201*950Sbill if (cmap == NULL) { 202*950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 203*950Sbill exit(1); 204*950Sbill } 205*950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 206*950Sbill if (read(fcore, (char *)cmap, i) != i) { 207*950Sbill perror("cmap read"); 208*950Sbill exit(1); 209*950Sbill } 210*950Sbill lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 211*950Sbill if (read(fcore, (char *)swapmap, sizeof swapmap) != sizeof swapmap) { 212*950Sbill perror("swapmap read"); 213*950Sbill exit(1); 214*950Sbill } 215*950Sbill for (p = &proc[1]; p < &proc[NPROC]; p++) { 216*950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 217*950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 218*950Sbill if (p->p_stat == 0) 219*950Sbill continue; 220*950Sbill printf("proc %d ", p->p_pid); 221*950Sbill if (p->p_stat == SZOMB) { 222*950Sbill printf("zombie\n"); 223*950Sbill continue; 224*950Sbill } 225*950Sbill if (p->p_flag & SLOAD) { 226*950Sbill printf("loaded, p0br %x, ", p->p_p0br); 227*950Sbill printf("%d pages of page tables:", p->p_szpt); 228*950Sbill a = btokmx(p->p_p0br); 229*950Sbill for (i = 0; i < p->p_szpt; i++) { 230*950Sbill w = get(&Usrptma[a + i]); 231*950Sbill printf(" %x", w & PG_PFNUM); 232*950Sbill } 233*950Sbill printf("\n"); 234*950Sbill for(i = 0; i < p->p_szpt; i++) { 235*950Sbill w = get(&Usrptma[a + i]); 236*950Sbill if (getpt(w, i)) 237*950Sbill count(p, (struct pte *)&w, ZPAGET); 238*950Sbill } 239*950Sbill } else { 240*950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 241*950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 242*950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 243*950Sbill duse(p->p_swaddr, clrnd(ctod(UPAGES)), DUDOT, p - proc); 244*950Sbill duse(p->p_swaddr + ctod(UPAGES), 245*950Sbill clrnd(i - p->p_tsize / NPTEPG), DPAGET, p - proc); 246*950Sbill /* i, DPAGET, p - proc); */ 247*950Sbill } 248*950Sbill p->p_p0br = (struct pte *)p0br; 249*950Sbill p->p_addr = uaddr(p); 250*950Sbill p->p_textp = &text[p->p_textp - (struct text *)nl[X_TEXT].n_value]; 251*950Sbill if (p->p_pid == 2) 252*950Sbill continue; 253*950Sbill if (getu(p)) 254*950Sbill continue; 255*950Sbill u.u_procp = p; 256*950Sbill pdmap(); 257*950Sbill if ((p->p_flag & SLOAD) == 0) 258*950Sbill continue; 259*950Sbill pid = p->p_pid; 260*950Sbill for (i = 0; i < p->p_tsize; i++) { 261*950Sbill pte = tptopte(p, i); 262*950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 263*950Sbill continue; 264*950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 265*950Sbill count(p, pte, ZINTRAN); 266*950Sbill else 267*950Sbill count(p, pte, ZTEXT); 268*950Sbill } 269*950Sbill vprintf("\n"); 270*950Sbill for (i = 0; i < p->p_dsize; i++) { 271*950Sbill pte = dptopte(p, i); 272*950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 273*950Sbill continue; 274*950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 275*950Sbill count(p, pte, ZINTRAN); 276*950Sbill else 277*950Sbill count(p, pte, ZDATA); 278*950Sbill } 279*950Sbill vprintf("\n"); 280*950Sbill for (i = 0; i < p->p_ssize; i++) { 281*950Sbill pte = sptopte(p, i); 282*950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 283*950Sbill continue; 284*950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 285*950Sbill count(p, pte, ZINTRAN); 286*950Sbill else 287*950Sbill count(p, pte, ZSTACK); 288*950Sbill } 289*950Sbill vprintf("\n"); 290*950Sbill for (i = 0; i < UPAGES; i++) 291*950Sbill count(p, &p->p_addr[i], ZUDOT); 292*950Sbill vprintf("\n"); 293*950Sbill vprintf("\n"); 294*950Sbill } 295*950Sbill for (xp = &text[0]; xp < &text[NTEXT]; xp++) 296*950Sbill if (xp->x_iptr) { 297*950Sbill for (i = 0; i < xp->x_size; i += DMTEXT) 298*950Sbill duse(xp->x_daddr[i], 299*950Sbill (xp->x_size - i) > DMTEXT 300*950Sbill ? DMTEXT : xp->x_size - i, 301*950Sbill DTEXT, xp - text); 302*950Sbill if (xp->x_flag & XPAGI) 303*950Sbill duse(xp->x_ptdaddr, clrnd(ctopt(xp->x_size)), 304*950Sbill DTEXT, xp - text); 305*950Sbill } 306*950Sbill dmcheck(); 307*950Sbill fixfree(); 308*950Sbill summary(); 309*950Sbill exit(0); 310*950Sbill } 311*950Sbill 312*950Sbill pdmap() 313*950Sbill { 314*950Sbill register struct text *xp; 315*950Sbill 316*950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 317*950Sbill return; 318*950Sbill if (Dflg) 319*950Sbill printf("disk for pid %d", u.u_procp->p_pid); 320*950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 321*950Sbill ptdmap(xp->x_daddr, xp->x_size); 322*950Sbill pdmseg("data", &u.u_dmap, DDATA); 323*950Sbill pdmseg("stack", &u.u_smap, DSTACK); 324*950Sbill if (Dflg) 325*950Sbill printf("\n"); 326*950Sbill } 327*950Sbill 328*950Sbill ptdmap(dp, size) 329*950Sbill register daddr_t *dp; 330*950Sbill int size; 331*950Sbill { 332*950Sbill register int i; 333*950Sbill int rem; 334*950Sbill 335*950Sbill if (Dflg) 336*950Sbill printf(" text:"); 337*950Sbill for (i = 0, rem = size; rem > 0; i++) { 338*950Sbill if (Dflg) 339*950Sbill printf(" %x<%x>", dp[i], rem < DMTEXT ? rem : DMTEXT); 340*950Sbill rem -= rem < DMTEXT ? rem : DMTEXT; 341*950Sbill } 342*950Sbill } 343*950Sbill 344*950Sbill pdmseg(cp, dmp, type) 345*950Sbill char *cp; 346*950Sbill struct dmap *dmp; 347*950Sbill { 348*950Sbill register int i; 349*950Sbill int b, rem; 350*950Sbill 351*950Sbill if (Dflg) 352*950Sbill printf(", %s:", cp); 353*950Sbill b = DMMIN; 354*950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 355*950Sbill if (Dflg) 356*950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 357*950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 358*950Sbill rem -= b; 359*950Sbill if (b < DMMAX) 360*950Sbill b *= 2; 361*950Sbill } 362*950Sbill } 363*950Sbill 364*950Sbill duse(first, size, type, index) 365*950Sbill { 366*950Sbill register struct dblks *dp; 367*950Sbill 368*950Sbill if (fswap == -1) 369*950Sbill return; 370*950Sbill dp = &dblks[ndblks]; 371*950Sbill if (++ndblks > NDBLKS) { 372*950Sbill fprintf(stderr, "too many disk blocks, increase NDBLKS\n"); 373*950Sbill exit(1); 374*950Sbill } 375*950Sbill dp->d_first = first; 376*950Sbill dp->d_size = size; 377*950Sbill dp->d_type = type; 378*950Sbill dp->d_index = index; 379*950Sbill } 380*950Sbill 381*950Sbill dsort(d, e) 382*950Sbill register struct dblks *d, *e; 383*950Sbill { 384*950Sbill 385*950Sbill return (e->d_first - d->d_first); 386*950Sbill } 387*950Sbill 388*950Sbill dmcheck() 389*950Sbill { 390*950Sbill register struct map *smp; 391*950Sbill register struct dblks *d, *e; 392*950Sbill 393*950Sbill for (smp = swapmap; smp->m_size; smp++) 394*950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 395*950Sbill duse(CLSIZE, DMTEXT - CLSIZE, DFREE, 0); 396*950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 397*950Sbill d = &dblks[ndblks - 1]; 398*950Sbill if (d->d_first > 1) 399*950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 400*950Sbill for (; d > dblks; d--) { 401*950Sbill if (dflg) 402*950Sbill dprint(d); 403*950Sbill e = d - 1; 404*950Sbill if (d->d_first + d->d_size > e->d_first) { 405*950Sbill printf("overlap in swap mappings:\n"); 406*950Sbill dprint(d); 407*950Sbill dprint(e); 408*950Sbill } else if (d->d_first + d->d_size < e->d_first) { 409*950Sbill printf("lost swap map: start %x size %x\n", 410*950Sbill d->d_first + d->d_size, 411*950Sbill e->d_first - (d->d_first + d->d_size)); 412*950Sbill } 413*950Sbill } 414*950Sbill if (dflg) 415*950Sbill dprint(dblks); 416*950Sbill if (sflg) 417*950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 418*950Sbill } 419*950Sbill 420*950Sbill char *dnames[] = { 421*950Sbill "DFREE", 422*950Sbill "DDATA", 423*950Sbill "DSTACK", 424*950Sbill "DTEXT", 425*950Sbill "DUDOT", 426*950Sbill "DPAGET", 427*950Sbill }; 428*950Sbill 429*950Sbill dprint(d) 430*950Sbill register struct dblks *d; 431*950Sbill { 432*950Sbill 433*950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 434*950Sbill dnames[d->d_type]); 435*950Sbill switch (d->d_type) { 436*950Sbill 437*950Sbill case DSTACK: 438*950Sbill case DDATA: 439*950Sbill printf(" pid %d", proc[d->d_index].p_pid); 440*950Sbill break; 441*950Sbill } 442*950Sbill printf("\n"); 443*950Sbill } 444*950Sbill 445*950Sbill getpt(x, i) 446*950Sbill int x, i; 447*950Sbill { 448*950Sbill 449*950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 450*950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 451*950Sbill perror("read"); 452*950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 453*950Sbill return (0); 454*950Sbill } 455*950Sbill return (1); 456*950Sbill } 457*950Sbill 458*950Sbill checkpg(p, pte, type) 459*950Sbill register struct pte *pte; 460*950Sbill register struct proc *p; 461*950Sbill int type; 462*950Sbill { 463*950Sbill char corepg[NBPG], swapg[NBPG]; 464*950Sbill register int i, count, dblock; 465*950Sbill register int pfnum = pte->pg_pfnum; 466*950Sbill 467*950Sbill if (type == ZPAGET || type == ZUDOT) 468*950Sbill return (0); 469*950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 470*950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 471*950Sbill perror("read"); 472*950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 473*950Sbill return (0); 474*950Sbill } 475*950Sbill switch (type) { 476*950Sbill 477*950Sbill case ZDATA: 478*950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 479*950Sbill return (0); 480*950Sbill break; 481*950Sbill 482*950Sbill case ZTEXT: 483*950Sbill break; 484*950Sbill 485*950Sbill case ZSTACK: 486*950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 487*950Sbill return (0); 488*950Sbill break; 489*950Sbill 490*950Sbill default: 491*950Sbill return(0); 492*950Sbill break; 493*950Sbill } 494*950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 495*950Sbill vprintf(" %x", dblock); 496*950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 497*950Sbill return (0); 498*950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 499*950Sbill return (0); 500*950Sbill lseek(fswap, (long)(NBPG * dblock), 0); 501*950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 502*950Sbill fprintf(stderr,"swap page %x: ", dblock); 503*950Sbill perror("read"); 504*950Sbill } 505*950Sbill count = 0; 506*950Sbill for (i = 0; i < NBPG; i++) 507*950Sbill if (corepg[i] != swapg[i]) 508*950Sbill count++; 509*950Sbill if (count == 0) 510*950Sbill vprintf("\tsame"); 511*950Sbill return (count); 512*950Sbill } 513*950Sbill 514*950Sbill getu(p) 515*950Sbill register struct proc *p; 516*950Sbill { 517*950Sbill int i, w, cc, errs = 0; 518*950Sbill 519*950Sbill for (i = 0; i < UPAGES; i++) { 520*950Sbill if (p->p_flag & SLOAD) { 521*950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 522*950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 523*950Sbill perror("core u. read"), errs++; 524*950Sbill } else if (fswap >= 0) { 525*950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 526*950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 527*950Sbill perror("swap u. read"), errs++; 528*950Sbill } 529*950Sbill } 530*950Sbill return (errs); 531*950Sbill } 532*950Sbill 533*950Sbill char *typepg[] = { 534*950Sbill "lost", 535*950Sbill "data", 536*950Sbill "stack", 537*950Sbill "udot", 538*950Sbill "paget", 539*950Sbill "text", 540*950Sbill "free", 541*950Sbill "intransit", 542*950Sbill }; 543*950Sbill 544*950Sbill count(p, pte, type) 545*950Sbill struct proc *p; 546*950Sbill register struct pte *pte; 547*950Sbill int type; 548*950Sbill { 549*950Sbill register int pfnum = pte->pg_pfnum; 550*950Sbill register struct paginfo *zp = &paginfo[pfnum]; 551*950Sbill int ndif; 552*950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 553*950Sbill 554*950Sbill if (type == ZINTRAN && pfnum == 0) 555*950Sbill return; 556*950Sbill zprintf("page %x %s", pfnum, typepg[type]); 557*950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 558*950Sbill zprintf("\n"); 559*950Sbill } else { 560*950Sbill if (vflg == 0 && type != ZINTRAN) 561*950Sbill printf("page %x %s,", pfnum, typepg[type]); 562*950Sbill printf(" %d bytes differ\n",ndif); 563*950Sbill } 564*950Sbill if (pfnum < firstfree || pfnum > maxfree) { 565*950Sbill printf("page number out of range:\n"); 566*950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 567*950Sbill return; 568*950Sbill } 569*950Sbill if (bad(zp, type)) { 570*950Sbill printf("dup page pte %x", *(int *)pte); 571*950Sbill dumpcm("", pte->pg_pfnum); 572*950Sbill dump(zp); 573*950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 574*950Sbill return; 575*950Sbill } 576*950Sbill zp->z_type = type; 577*950Sbill zp->z_count++; 578*950Sbill zp->z_pid = pid; 579*950Sbill zp->z_pte = *pte; 580*950Sbill } 581*950Sbill 582*950Sbill bad(zp, type) 583*950Sbill struct paginfo *zp; 584*950Sbill { 585*950Sbill if (type == ZTEXT) { 586*950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 587*950Sbill return (1); 588*950Sbill return (0); 589*950Sbill } 590*950Sbill return (zp->z_count); 591*950Sbill } 592*950Sbill 593*950Sbill dump(zp) 594*950Sbill struct paginfo *zp; 595*950Sbill { 596*950Sbill 597*950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 598*950Sbill } 599*950Sbill 600*950Sbill summary() 601*950Sbill { 602*950Sbill register int i; 603*950Sbill register struct paginfo *zp; 604*950Sbill register int pfnum; 605*950Sbill 606*950Sbill for (i = firstfree + UPAGES; i < maxfree; i++) { 607*950Sbill zp = &paginfo[i]; 608*950Sbill if (zp->z_type == ZLOST) 609*950Sbill dumpcm("lost", i); 610*950Sbill pfnum = pgtocm(i); 611*950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 612*950Sbill dumpcm("locked", i); 613*950Sbill if (mflg) 614*950Sbill dumpcm("mem", i); 615*950Sbill } 616*950Sbill } 617*950Sbill 618*950Sbill char *tynames[] = { 619*950Sbill "sys", 620*950Sbill "text", 621*950Sbill "data", 622*950Sbill "stack" 623*950Sbill }; 624*950Sbill dumpcm(cp, pg) 625*950Sbill char *cp; 626*950Sbill int pg; 627*950Sbill { 628*950Sbill int pslot; 629*950Sbill int cm; 630*950Sbill register struct cmap *c; 631*950Sbill 632*950Sbill printf("%s page %x ", cp, pg); 633*950Sbill cm = pgtocm(pg); 634*950Sbill c = &cmap[cm]; 635*950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 636*950Sbill if (c->c_type != CTEXT) 637*950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 638*950Sbill else { 639*950Sbill pslot=(text[c->c_ndx].x_caddr - (struct proc *)nl[X_PROC].n_value); 640*950Sbill printf(" (=pid"); 641*950Sbill for(;;) { 642*950Sbill printf(" %d", proc[pslot].p_pid); 643*950Sbill if (proc[pslot].p_xlink == 0) 644*950Sbill break; 645*950Sbill pslot=(proc[pslot].p_xlink - (struct proc *)nl[X_PROC].n_value); 646*950Sbill } 647*950Sbill printf(")"); 648*950Sbill } 649*950Sbill printf("] "); 650*950Sbill printf(tynames[c->c_type]); 651*950Sbill if (c->c_free) 652*950Sbill printf(" free"); 653*950Sbill if (c->c_gone) 654*950Sbill printf(" gone"); 655*950Sbill if (c->c_lock) 656*950Sbill printf(" lock"); 657*950Sbill if (c->c_want) 658*950Sbill printf(" want"); 659*950Sbill if (c->c_intrans) 660*950Sbill printf(" intrans"); 661*950Sbill if (c->c_blkno) 662*950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 663*950Sbill printf("\n"); 664*950Sbill } 665*950Sbill 666*950Sbill fixfree() 667*950Sbill { 668*950Sbill register int i, next, prev; 669*950Sbill 670*950Sbill next = CMHEAD; 671*950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 672*950Sbill prev = next; 673*950Sbill next = cmap[next].c_next; 674*950Sbill if (cmap[next].c_free == 0) { 675*950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 676*950Sbill dumpcm("bad free link in", cmtopg(prev)); 677*950Sbill dumpcm("to non free block", cmtopg(next)); 678*950Sbill } 679*950Sbill if (cmtopg(next) > maxfree) { 680*950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 681*950Sbill dumpcm("bad link in", cmtopg(prev)); 682*950Sbill } 683*950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 684*950Sbill if (fflg) 685*950Sbill dumpcm("free", cmtopg(next)); 686*950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 687*950Sbill if (fflg) 688*950Sbill dumpcm("free", cmtopg(next)+1); 689*950Sbill } 690*950Sbill } 691*950Sbill 692*950Sbill get(loc) 693*950Sbill unsigned loc; 694*950Sbill { 695*950Sbill int x; 696*950Sbill 697*950Sbill lseek(fcore, (long)clear(loc), 0); 698*950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 699*950Sbill perror("read"); 700*950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 701*950Sbill return (0); 702*950Sbill } 703*950Sbill return (x); 704*950Sbill } 705*950Sbill /* 706*950Sbill * Convert a virtual page number 707*950Sbill * to its corresponding disk block number. 708*950Sbill * Used in pagein/pageout to initiate single page transfers. 709*950Sbill */ 710*950Sbill vtod(p, v, dmap, smap) 711*950Sbill register struct proc *p; 712*950Sbill register struct dmap *dmap, *smap; 713*950Sbill { 714*950Sbill struct dblock db; 715*950Sbill 716*950Sbill if (v < p->p_tsize) 717*950Sbill return(p->p_textp->x_daddr[v / DMTEXT] + v % DMTEXT); 718*950Sbill if (isassv(p, v)) 719*950Sbill vstodb(vtosp(p, v), 1, smap, &db, 1); 720*950Sbill else 721*950Sbill vstodb(vtodp(p, v), 1, dmap, &db, 0); 722*950Sbill return (db.db_base); 723*950Sbill } 724*950Sbill 725*950Sbill /* 726*950Sbill * Convert a pte pointer to 727*950Sbill * a virtual page number. 728*950Sbill */ 729*950Sbill ptetov(p, pte) 730*950Sbill register struct proc *p; 731*950Sbill register struct pte *pte; 732*950Sbill { 733*950Sbill 734*950Sbill if (isatpte(p, pte)) 735*950Sbill return (tptov(p, ptetotp(p, pte))); 736*950Sbill else if (isadpte(p, pte)) 737*950Sbill return (dptov(p, ptetodp(p, pte))); 738*950Sbill else 739*950Sbill return (sptov(p, ptetosp(p, pte))); 740*950Sbill } 741*950Sbill 742*950Sbill /* 743*950Sbill * Given a base/size pair in virtual swap area, 744*950Sbill * return a physical base/size pair which is the 745*950Sbill * (largest) initial, physically contiguous block. 746*950Sbill */ 747*950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 748*950Sbill register int vsbase; 749*950Sbill int vssize; 750*950Sbill register struct dmap *dmp; 751*950Sbill register struct dblock *dbp; 752*950Sbill { 753*950Sbill register int blk = DMMIN; 754*950Sbill register swblk_t *ip = dmp->dm_map; 755*950Sbill 756*950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 757*950Sbill panic("vstodb"); 758*950Sbill while (vsbase >= blk) { 759*950Sbill vsbase -= blk; 760*950Sbill if (blk < DMMAX) 761*950Sbill blk *= 2; 762*950Sbill ip++; 763*950Sbill } 764*950Sbill dbp->db_size = min(vssize, blk - vsbase); 765*950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 766*950Sbill } 767*950Sbill 768*950Sbill panic(cp) 769*950Sbill char *cp; 770*950Sbill { 771*950Sbill printf("panic!: %s\n", cp); 772*950Sbill } 773*950Sbill 774*950Sbill min(a, b) 775*950Sbill { 776*950Sbill return (a < b ? a : b); 777*950Sbill } 778