1*2824Swnj static char *sccsid = "@(#)analyze.c 4.2 (Berkeley) 02/28/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; 25*2824Swnj 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 32950Sbill struct proc proc[NPROC]; 33950Sbill struct text text[NTEXT]; 34950Sbill struct map swapmap[SMAPSIZ]; 35950Sbill struct cmap *cmap; 36*2824Swnj int ecmx; 37950Sbill struct pte *usrpt; 38950Sbill struct pte *Usrptma; 39950Sbill int firstfree; 40950Sbill int maxfree; 41950Sbill int freemem; 42950Sbill struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG]; 43950Sbill int pid; 44950Sbill 45950Sbill struct paginfo { 46950Sbill char z_type; 47950Sbill char z_count; 48950Sbill short z_pid; 49950Sbill struct pte z_pte; 50950Sbill } *paginfo; 51950Sbill #define ZLOST 0 52950Sbill #define ZDATA 1 53950Sbill #define ZSTACK 2 54950Sbill #define ZUDOT 3 55950Sbill #define ZPAGET 4 56950Sbill #define ZTEXT 5 57950Sbill #define ZFREE 6 58950Sbill #define ZINTRAN 7 59950Sbill 60950Sbill #define NDBLKS (2*SMAPSIZ) 61950Sbill struct dblks { 62950Sbill short d_first; 63950Sbill short d_size; 64950Sbill char d_type; 65950Sbill char d_index; 66950Sbill } dblks[NDBLKS]; 67950Sbill int ndblks; 68950Sbill 69950Sbill #define DFREE 0 70950Sbill #define DDATA 1 71950Sbill #define DSTACK 2 72950Sbill #define DTEXT 3 73950Sbill #define DUDOT 4 74950Sbill #define DPAGET 5 75950Sbill 76950Sbill union { 77950Sbill char buf[UPAGES][512]; 78950Sbill struct user U; 79950Sbill } u_area; 80950Sbill #define u u_area.U 81950Sbill 82950Sbill int fcore = -1; 83950Sbill int fswap = -1; 84950Sbill 85950Sbill struct nlist nl[] = { 86950Sbill #define X_PROC 0 87950Sbill { "_proc" }, 88950Sbill #define X_USRPT 1 89950Sbill { "_usrpt" }, 90950Sbill #define X_PTMA 2 91*2824Swnj { "_Usrptmap" }, 92950Sbill #define X_FIRSTFREE 3 93*2824Swnj { "_firstfree" }, 94950Sbill #define X_MAXFREE 4 95950Sbill { "_maxfree" }, 96950Sbill #define X_TEXT 5 97950Sbill { "_text" }, 98950Sbill #define X_FREEMEM 6 99950Sbill { "_freemem" }, 100950Sbill #define X_CMAP 7 101950Sbill { "_cmap" }, 102950Sbill #define X_ECMAP 8 103950Sbill { "_ecmap" }, 104950Sbill #define X_SWAPMAP 9 105950Sbill { "_swapmap" }, 106950Sbill { 0 } 107950Sbill }; 108950Sbill 109950Sbill main(argc, argv) 110950Sbill int argc; 111950Sbill char **argv; 112950Sbill { 113950Sbill register struct nlist *np; 114950Sbill register struct proc *p; 115950Sbill register struct text *xp; 116950Sbill register struct pte *pte; 117950Sbill register int i; 118950Sbill int w, a; 119950Sbill 120950Sbill argc--, argv++; 121950Sbill while (argc > 0 && argv[0][0] == '-') { 122950Sbill register char *cp = *argv++; 123950Sbill argc--; 124950Sbill while (*++cp) switch (*cp) { 125950Sbill 126950Sbill case 'm': 127950Sbill mflg++; 128950Sbill break; 129950Sbill 130950Sbill case 'v': 131950Sbill vflg++; 132950Sbill break; 133950Sbill 134950Sbill case 's': 135950Sbill if (argc < 2) 136950Sbill goto usage; 137950Sbill if ((fswap = open(argv[0], 0)) < 0) { 138950Sbill perror(argv[0]); 139950Sbill exit(1); 140950Sbill } 141950Sbill argc--,argv++; 142950Sbill sflg++; 143950Sbill break; 144950Sbill 145950Sbill case 'f': 146950Sbill fflg++; 147950Sbill break; 148950Sbill 149950Sbill case 'D': 150950Sbill Dflg++; 151950Sbill break; 152950Sbill 153950Sbill case 'd': 154950Sbill dflg++; 155950Sbill break; 156950Sbill 157*2824Swnj case 'u': 158*2824Swnj uflg++; 159*2824Swnj break; 160*2824Swnj 161950Sbill default: 162950Sbill goto usage; 163950Sbill } 164950Sbill } 165950Sbill if (argc < 1) { 166950Sbill usage: 167950Sbill fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n"); 168950Sbill exit(1); 169950Sbill } 170950Sbill close(0); 171950Sbill if ((fcore = open(argv[0], 0)) < 0) { 172950Sbill perror(argv[0]); 173950Sbill exit(1); 174950Sbill } 175950Sbill nlist(argc > 1 ? argv[1] : "/vmunix", nl); 176950Sbill if (nl[0].n_value == 0) { 177950Sbill fprintf(stderr, "%s: bad namelist\n", 178950Sbill argc > 1 ? argv[1] : "/vmunix"); 179950Sbill exit(1); 180950Sbill } 181950Sbill for (np = nl; np->n_name[0]; np++) 182950Sbill vprintf("%8.8s %x\n", np->n_name ,np->n_value ); 183950Sbill usrpt = (struct pte *)clear(nl[X_USRPT].n_value); 184950Sbill Usrptma = (struct pte *)clear(nl[X_PTMA].n_value); 185950Sbill firstfree = get(nl[X_FIRSTFREE].n_value); 186950Sbill maxfree = get(nl[X_MAXFREE].n_value); 187950Sbill freemem = get(nl[X_FREEMEM].n_value); 188950Sbill paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo)); 189950Sbill if (paginfo == NULL) { 190950Sbill fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree); 191950Sbill exit(1); 192950Sbill } 193950Sbill vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n", 194950Sbill usrpt, Usrptma, firstfree, maxfree, freemem); 195950Sbill lseek(fcore, (long)clear(nl[X_PROC].n_value), 0); 196950Sbill if (read(fcore, (char *)proc, sizeof proc) != sizeof proc) { 197950Sbill perror("proc read"); 198950Sbill exit(1); 199950Sbill } 200950Sbill lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0); 201950Sbill if (read(fcore, (char *)text, sizeof text) != sizeof text) { 202950Sbill perror("text read"); 203950Sbill exit(1); 204950Sbill } 205950Sbill i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value)); 206*2824Swnj ecmx = i / sizeof (struct cmap); 207950Sbill cmap = (struct cmap *)calloc(i, 1); 208950Sbill if (cmap == NULL) { 209950Sbill fprintf(stderr, "not enough mem for %x bytes of cmap\n", i); 210950Sbill exit(1); 211950Sbill } 212950Sbill lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0); 213950Sbill if (read(fcore, (char *)cmap, i) != i) { 214950Sbill perror("cmap read"); 215950Sbill exit(1); 216950Sbill } 217950Sbill lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0); 218950Sbill if (read(fcore, (char *)swapmap, sizeof swapmap) != sizeof swapmap) { 219950Sbill perror("swapmap read"); 220950Sbill exit(1); 221950Sbill } 222950Sbill for (p = &proc[1]; p < &proc[NPROC]; p++) { 223950Sbill p->p_p0br = (struct pte *)clear(p->p_p0br); 224950Sbill p->p_addr = (struct pte *)clear(p->p_addr); 225950Sbill if (p->p_stat == 0) 226950Sbill continue; 227950Sbill printf("proc %d ", p->p_pid); 228950Sbill if (p->p_stat == SZOMB) { 229950Sbill printf("zombie\n"); 230950Sbill continue; 231950Sbill } 232950Sbill if (p->p_flag & SLOAD) { 233950Sbill printf("loaded, p0br %x, ", p->p_p0br); 234950Sbill printf("%d pages of page tables:", p->p_szpt); 235950Sbill a = btokmx(p->p_p0br); 236950Sbill for (i = 0; i < p->p_szpt; i++) { 237950Sbill w = get(&Usrptma[a + i]); 238950Sbill printf(" %x", w & PG_PFNUM); 239950Sbill } 240950Sbill printf("\n"); 241950Sbill for(i = 0; i < p->p_szpt; i++) { 242950Sbill w = get(&Usrptma[a + i]); 243950Sbill if (getpt(w, i)) 244950Sbill count(p, (struct pte *)&w, ZPAGET); 245950Sbill } 246950Sbill } else { 247950Sbill /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */ 248950Sbill i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize)); 249950Sbill printf("swapped, swaddr %x\n", p->p_swaddr); 250950Sbill duse(p->p_swaddr, clrnd(ctod(UPAGES)), DUDOT, p - proc); 251950Sbill duse(p->p_swaddr + ctod(UPAGES), 252950Sbill clrnd(i - p->p_tsize / NPTEPG), DPAGET, p - proc); 253950Sbill /* i, DPAGET, p - proc); */ 254950Sbill } 255950Sbill p->p_p0br = (struct pte *)p0br; 256950Sbill p->p_addr = uaddr(p); 257950Sbill p->p_textp = &text[p->p_textp - (struct text *)nl[X_TEXT].n_value]; 258950Sbill if (p->p_pid == 2) 259950Sbill continue; 260950Sbill if (getu(p)) 261950Sbill continue; 262950Sbill u.u_procp = p; 263950Sbill pdmap(); 264950Sbill if ((p->p_flag & SLOAD) == 0) 265950Sbill continue; 266950Sbill pid = p->p_pid; 267950Sbill for (i = 0; i < p->p_tsize; i++) { 268950Sbill pte = tptopte(p, i); 269950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 270950Sbill continue; 271950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 272950Sbill count(p, pte, ZINTRAN); 273950Sbill else 274950Sbill count(p, pte, ZTEXT); 275950Sbill } 276950Sbill vprintf("\n"); 277950Sbill for (i = 0; i < p->p_dsize; i++) { 278950Sbill pte = dptopte(p, i); 279950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 280950Sbill continue; 281950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 282950Sbill count(p, pte, ZINTRAN); 283950Sbill else 284950Sbill count(p, pte, ZDATA); 285950Sbill } 286950Sbill vprintf("\n"); 287950Sbill for (i = 0; i < p->p_ssize; i++) { 288950Sbill pte = sptopte(p, i); 289950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 290950Sbill continue; 291950Sbill if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans) 292950Sbill count(p, pte, ZINTRAN); 293950Sbill else 294950Sbill count(p, pte, ZSTACK); 295950Sbill } 296950Sbill vprintf("\n"); 297950Sbill for (i = 0; i < UPAGES; i++) 298950Sbill count(p, &p->p_addr[i], ZUDOT); 299950Sbill vprintf("\n"); 300950Sbill vprintf("\n"); 301950Sbill } 302950Sbill for (xp = &text[0]; xp < &text[NTEXT]; xp++) 303950Sbill if (xp->x_iptr) { 304950Sbill for (i = 0; i < xp->x_size; i += DMTEXT) 305950Sbill duse(xp->x_daddr[i], 306950Sbill (xp->x_size - i) > DMTEXT 307950Sbill ? DMTEXT : xp->x_size - i, 308950Sbill DTEXT, xp - text); 309950Sbill if (xp->x_flag & XPAGI) 310950Sbill duse(xp->x_ptdaddr, clrnd(ctopt(xp->x_size)), 311950Sbill DTEXT, xp - text); 312950Sbill } 313950Sbill dmcheck(); 314950Sbill fixfree(); 315950Sbill summary(); 316950Sbill exit(0); 317950Sbill } 318950Sbill 319950Sbill pdmap() 320950Sbill { 321950Sbill register struct text *xp; 322950Sbill 323950Sbill if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0) 324950Sbill return; 325950Sbill if (Dflg) 326950Sbill printf("disk for pid %d", u.u_procp->p_pid); 327950Sbill if ((xp = u.u_procp->p_textp) && Dflg) 328950Sbill ptdmap(xp->x_daddr, xp->x_size); 329950Sbill pdmseg("data", &u.u_dmap, DDATA); 330950Sbill pdmseg("stack", &u.u_smap, DSTACK); 331950Sbill if (Dflg) 332950Sbill printf("\n"); 333950Sbill } 334950Sbill 335950Sbill ptdmap(dp, size) 336950Sbill register daddr_t *dp; 337950Sbill int size; 338950Sbill { 339950Sbill register int i; 340950Sbill int rem; 341950Sbill 342950Sbill if (Dflg) 343950Sbill printf(" text:"); 344950Sbill for (i = 0, rem = size; rem > 0; i++) { 345950Sbill if (Dflg) 346950Sbill printf(" %x<%x>", dp[i], rem < DMTEXT ? rem : DMTEXT); 347950Sbill rem -= rem < DMTEXT ? rem : DMTEXT; 348950Sbill } 349950Sbill } 350950Sbill 351950Sbill pdmseg(cp, dmp, type) 352950Sbill char *cp; 353950Sbill struct dmap *dmp; 354950Sbill { 355950Sbill register int i; 356950Sbill int b, rem; 357950Sbill 358950Sbill if (Dflg) 359950Sbill printf(", %s:", cp); 360950Sbill b = DMMIN; 361950Sbill for (i = 0, rem = dmp->dm_size; rem > 0; i++) { 362950Sbill if (Dflg) 363950Sbill printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b); 364950Sbill duse(dmp->dm_map[i], b, type, u.u_procp - proc); 365950Sbill rem -= b; 366950Sbill if (b < DMMAX) 367950Sbill b *= 2; 368950Sbill } 369950Sbill } 370950Sbill 371950Sbill duse(first, size, type, index) 372950Sbill { 373950Sbill register struct dblks *dp; 374950Sbill 375950Sbill if (fswap == -1) 376950Sbill return; 377950Sbill dp = &dblks[ndblks]; 378950Sbill if (++ndblks > NDBLKS) { 379950Sbill fprintf(stderr, "too many disk blocks, increase NDBLKS\n"); 380950Sbill exit(1); 381950Sbill } 382950Sbill dp->d_first = first; 383950Sbill dp->d_size = size; 384950Sbill dp->d_type = type; 385950Sbill dp->d_index = index; 386950Sbill } 387950Sbill 388950Sbill dsort(d, e) 389950Sbill register struct dblks *d, *e; 390950Sbill { 391950Sbill 392950Sbill return (e->d_first - d->d_first); 393950Sbill } 394950Sbill 395950Sbill dmcheck() 396950Sbill { 397950Sbill register struct map *smp; 398950Sbill register struct dblks *d, *e; 399950Sbill 400950Sbill for (smp = swapmap; smp->m_size; smp++) 401950Sbill duse(smp->m_addr, smp->m_size, DFREE, 0); 402950Sbill duse(CLSIZE, DMTEXT - CLSIZE, DFREE, 0); 403950Sbill qsort(dblks, ndblks, sizeof (struct dblks), dsort); 404950Sbill d = &dblks[ndblks - 1]; 405950Sbill if (d->d_first > 1) 406950Sbill printf("lost swap map: start %x size %x\n", 1, d->d_first); 407950Sbill for (; d > dblks; d--) { 408950Sbill if (dflg) 409950Sbill dprint(d); 410950Sbill e = d - 1; 411950Sbill if (d->d_first + d->d_size > e->d_first) { 412950Sbill printf("overlap in swap mappings:\n"); 413950Sbill dprint(d); 414950Sbill dprint(e); 415950Sbill } else if (d->d_first + d->d_size < e->d_first) { 416950Sbill printf("lost swap map: start %x size %x\n", 417950Sbill d->d_first + d->d_size, 418950Sbill e->d_first - (d->d_first + d->d_size)); 419950Sbill } 420950Sbill } 421950Sbill if (dflg) 422950Sbill dprint(dblks); 423950Sbill if (sflg) 424950Sbill printf("swap space ends at %x\n", d->d_first + d->d_size); 425950Sbill } 426950Sbill 427950Sbill char *dnames[] = { 428950Sbill "DFREE", 429950Sbill "DDATA", 430950Sbill "DSTACK", 431950Sbill "DTEXT", 432950Sbill "DUDOT", 433950Sbill "DPAGET", 434950Sbill }; 435950Sbill 436950Sbill dprint(d) 437950Sbill register struct dblks *d; 438950Sbill { 439950Sbill 440950Sbill printf("at %4x size %4x type %s", d->d_first, d->d_size, 441950Sbill dnames[d->d_type]); 442950Sbill switch (d->d_type) { 443950Sbill 444950Sbill case DSTACK: 445950Sbill case DDATA: 446950Sbill printf(" pid %d", proc[d->d_index].p_pid); 447950Sbill break; 448950Sbill } 449950Sbill printf("\n"); 450950Sbill } 451950Sbill 452950Sbill getpt(x, i) 453950Sbill int x, i; 454950Sbill { 455950Sbill 456950Sbill lseek(fcore, (long)ctob((x & PG_PFNUM)), 0); 457950Sbill if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) { 458950Sbill perror("read"); 459950Sbill fprintf(stderr, "getpt error reading frame %x\n", clear(x)); 460950Sbill return (0); 461950Sbill } 462950Sbill return (1); 463950Sbill } 464950Sbill 465950Sbill checkpg(p, pte, type) 466950Sbill register struct pte *pte; 467950Sbill register struct proc *p; 468950Sbill int type; 469950Sbill { 470950Sbill char corepg[NBPG], swapg[NBPG]; 471950Sbill register int i, count, dblock; 472950Sbill register int pfnum = pte->pg_pfnum; 473950Sbill 474950Sbill if (type == ZPAGET || type == ZUDOT) 475950Sbill return (0); 476950Sbill lseek(fcore, (long)(NBPG * pfnum), 0); 477950Sbill if (read(fcore, corepg, NBPG) != NBPG){ 478950Sbill perror("read"); 479950Sbill fprintf(stderr, "Error reading core page %x\n", pfnum); 480950Sbill return (0); 481950Sbill } 482950Sbill switch (type) { 483950Sbill 484950Sbill case ZDATA: 485950Sbill if (ptetodp(p, pte) >= u.u_dmap.dm_size) 486950Sbill return (0); 487950Sbill break; 488950Sbill 489950Sbill case ZTEXT: 490950Sbill break; 491950Sbill 492950Sbill case ZSTACK: 493950Sbill if (ptetosp(p, pte) >= u.u_smap.dm_size) 494950Sbill return (0); 495950Sbill break; 496950Sbill 497950Sbill default: 498950Sbill return(0); 499950Sbill break; 500950Sbill } 501950Sbill dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap); 502950Sbill vprintf(" %x", dblock); 503950Sbill if (pte->pg_fod || pte->pg_pfnum == 0) 504950Sbill return (0); 505950Sbill if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm) 506950Sbill return (0); 507950Sbill lseek(fswap, (long)(NBPG * dblock), 0); 508950Sbill if (read(fswap, swapg, NBPG) != NBPG) { 509950Sbill fprintf(stderr,"swap page %x: ", dblock); 510950Sbill perror("read"); 511950Sbill } 512950Sbill count = 0; 513950Sbill for (i = 0; i < NBPG; i++) 514950Sbill if (corepg[i] != swapg[i]) 515950Sbill count++; 516950Sbill if (count == 0) 517950Sbill vprintf("\tsame"); 518950Sbill return (count); 519950Sbill } 520950Sbill 521950Sbill getu(p) 522950Sbill register struct proc *p; 523950Sbill { 524950Sbill int i, w, cc, errs = 0; 525950Sbill 526*2824Swnj if (uflg && (p->p_flag & SLOAD)) 527*2824Swnj printf("pid %d u. pages:", p->p_pid); 528950Sbill for (i = 0; i < UPAGES; i++) { 529950Sbill if (p->p_flag & SLOAD) { 530*2824Swnj if (uflg) 531*2824Swnj printf(" %x", p->p_addr[i].pg_pfnum); 532950Sbill lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0); 533950Sbill if (read(fcore, u_area.buf[i], NBPG) != NBPG) 534950Sbill perror("core u. read"), errs++; 535950Sbill } else if (fswap >= 0) { 536950Sbill lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0); 537950Sbill if (read(fswap, u_area.buf[i], NBPG) != NBPG) 538950Sbill perror("swap u. read"), errs++; 539950Sbill } 540950Sbill } 541*2824Swnj if (uflg && (p->p_flag & SLOAD)) 542*2824Swnj printf("\n"); 543950Sbill return (errs); 544950Sbill } 545950Sbill 546950Sbill char *typepg[] = { 547950Sbill "lost", 548950Sbill "data", 549950Sbill "stack", 550950Sbill "udot", 551950Sbill "paget", 552950Sbill "text", 553950Sbill "free", 554950Sbill "intransit", 555950Sbill }; 556950Sbill 557950Sbill count(p, pte, type) 558950Sbill struct proc *p; 559950Sbill register struct pte *pte; 560950Sbill int type; 561950Sbill { 562950Sbill register int pfnum = pte->pg_pfnum; 563950Sbill register struct paginfo *zp = &paginfo[pfnum]; 564950Sbill int ndif; 565950Sbill #define zprintf if (type==ZINTRAN || vflg) printf 566950Sbill 567950Sbill if (type == ZINTRAN && pfnum == 0) 568950Sbill return; 569950Sbill zprintf("page %x %s", pfnum, typepg[type]); 570950Sbill if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) { 571950Sbill zprintf("\n"); 572950Sbill } else { 573950Sbill if (vflg == 0 && type != ZINTRAN) 574950Sbill printf("page %x %s,", pfnum, typepg[type]); 575950Sbill printf(" %d bytes differ\n",ndif); 576950Sbill } 577950Sbill if (pfnum < firstfree || pfnum > maxfree) { 578950Sbill printf("page number out of range:\n"); 579950Sbill printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid); 580950Sbill return; 581950Sbill } 582950Sbill if (bad(zp, type)) { 583950Sbill printf("dup page pte %x", *(int *)pte); 584950Sbill dumpcm("", pte->pg_pfnum); 585950Sbill dump(zp); 586950Sbill printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid); 587950Sbill return; 588950Sbill } 589950Sbill zp->z_type = type; 590950Sbill zp->z_count++; 591950Sbill zp->z_pid = pid; 592950Sbill zp->z_pte = *pte; 593950Sbill } 594950Sbill 595950Sbill bad(zp, type) 596950Sbill struct paginfo *zp; 597950Sbill { 598950Sbill if (type == ZTEXT) { 599950Sbill if (zp->z_type != 0 && zp->z_type != ZTEXT) 600950Sbill return (1); 601950Sbill return (0); 602950Sbill } 603950Sbill return (zp->z_count); 604950Sbill } 605950Sbill 606950Sbill dump(zp) 607950Sbill struct paginfo *zp; 608950Sbill { 609950Sbill 610950Sbill printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid); 611950Sbill } 612950Sbill 613950Sbill summary() 614950Sbill { 615950Sbill register int i; 616950Sbill register struct paginfo *zp; 617950Sbill register int pfnum; 618950Sbill 619*2824Swnj for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) { 620950Sbill zp = &paginfo[i]; 621950Sbill if (zp->z_type == ZLOST) 622950Sbill dumpcm("lost", i); 623950Sbill pfnum = pgtocm(i); 624950Sbill if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS) 625950Sbill dumpcm("locked", i); 626950Sbill if (mflg) 627950Sbill dumpcm("mem", i); 628950Sbill } 629950Sbill } 630950Sbill 631950Sbill char *tynames[] = { 632950Sbill "sys", 633950Sbill "text", 634950Sbill "data", 635950Sbill "stack" 636950Sbill }; 637950Sbill dumpcm(cp, pg) 638950Sbill char *cp; 639950Sbill int pg; 640950Sbill { 641950Sbill int pslot; 642950Sbill int cm; 643950Sbill register struct cmap *c; 644950Sbill 645950Sbill cm = pgtocm(pg); 646*2824Swnj printf("cm %x %s page %x ", cm, cp, pg); 647950Sbill c = &cmap[cm]; 648950Sbill printf("\t[%x, %x", c->c_page, c->c_ndx); 649950Sbill if (c->c_type != CTEXT) 650950Sbill printf(" (=pid %d)", proc[c->c_ndx].p_pid); 651950Sbill else { 652950Sbill pslot=(text[c->c_ndx].x_caddr - (struct proc *)nl[X_PROC].n_value); 653950Sbill printf(" (=pid"); 654950Sbill for(;;) { 655950Sbill printf(" %d", proc[pslot].p_pid); 656950Sbill if (proc[pslot].p_xlink == 0) 657950Sbill break; 658950Sbill pslot=(proc[pslot].p_xlink - (struct proc *)nl[X_PROC].n_value); 659950Sbill } 660950Sbill printf(")"); 661950Sbill } 662950Sbill printf("] "); 663950Sbill printf(tynames[c->c_type]); 664950Sbill if (c->c_free) 665950Sbill printf(" free"); 666950Sbill if (c->c_gone) 667950Sbill printf(" gone"); 668950Sbill if (c->c_lock) 669950Sbill printf(" lock"); 670950Sbill if (c->c_want) 671950Sbill printf(" want"); 672950Sbill if (c->c_intrans) 673950Sbill printf(" intrans"); 674950Sbill if (c->c_blkno) 675950Sbill printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev); 676*2824Swnj if (c->c_hlink) { 677*2824Swnj printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink)); 678*2824Swnj if (c->c_hlink > ecmx) 679*2824Swnj printf(" <<<"); 680*2824Swnj } 681950Sbill printf("\n"); 682950Sbill } 683950Sbill 684950Sbill fixfree() 685950Sbill { 686950Sbill register int i, next, prev; 687950Sbill 688950Sbill next = CMHEAD; 689950Sbill for (i=freemem/CLSIZE; --i >=0; ) { 690950Sbill prev = next; 691950Sbill next = cmap[next].c_next; 692950Sbill if (cmap[next].c_free == 0) { 693950Sbill printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next)); 694950Sbill dumpcm("bad free link in", cmtopg(prev)); 695950Sbill dumpcm("to non free block", cmtopg(next)); 696950Sbill } 697950Sbill if (cmtopg(next) > maxfree) { 698950Sbill printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next)); 699950Sbill dumpcm("bad link in", cmtopg(prev)); 700950Sbill } 701950Sbill paginfo[cmtopg(next)].z_type = ZFREE; 702950Sbill if (fflg) 703950Sbill dumpcm("free", cmtopg(next)); 704950Sbill paginfo[cmtopg(next)+1].z_type = ZFREE; 705950Sbill if (fflg) 706950Sbill dumpcm("free", cmtopg(next)+1); 707950Sbill } 708950Sbill } 709950Sbill 710950Sbill get(loc) 711950Sbill unsigned loc; 712950Sbill { 713950Sbill int x; 714950Sbill 715950Sbill lseek(fcore, (long)clear(loc), 0); 716950Sbill if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) { 717950Sbill perror("read"); 718950Sbill fprintf(stderr, "get failed on %x\n", clear(loc)); 719950Sbill return (0); 720950Sbill } 721950Sbill return (x); 722950Sbill } 723950Sbill /* 724950Sbill * Convert a virtual page number 725950Sbill * to its corresponding disk block number. 726950Sbill * Used in pagein/pageout to initiate single page transfers. 727950Sbill */ 728950Sbill vtod(p, v, dmap, smap) 729950Sbill register struct proc *p; 730950Sbill register struct dmap *dmap, *smap; 731950Sbill { 732950Sbill struct dblock db; 733950Sbill 734950Sbill if (v < p->p_tsize) 735950Sbill return(p->p_textp->x_daddr[v / DMTEXT] + v % DMTEXT); 736950Sbill if (isassv(p, v)) 737950Sbill vstodb(vtosp(p, v), 1, smap, &db, 1); 738950Sbill else 739950Sbill vstodb(vtodp(p, v), 1, dmap, &db, 0); 740950Sbill return (db.db_base); 741950Sbill } 742950Sbill 743950Sbill /* 744950Sbill * Convert a pte pointer to 745950Sbill * a virtual page number. 746950Sbill */ 747950Sbill ptetov(p, pte) 748950Sbill register struct proc *p; 749950Sbill register struct pte *pte; 750950Sbill { 751950Sbill 752950Sbill if (isatpte(p, pte)) 753950Sbill return (tptov(p, ptetotp(p, pte))); 754950Sbill else if (isadpte(p, pte)) 755950Sbill return (dptov(p, ptetodp(p, pte))); 756950Sbill else 757950Sbill return (sptov(p, ptetosp(p, pte))); 758950Sbill } 759950Sbill 760950Sbill /* 761950Sbill * Given a base/size pair in virtual swap area, 762950Sbill * return a physical base/size pair which is the 763950Sbill * (largest) initial, physically contiguous block. 764950Sbill */ 765950Sbill vstodb(vsbase, vssize, dmp, dbp, rev) 766950Sbill register int vsbase; 767950Sbill int vssize; 768950Sbill register struct dmap *dmp; 769950Sbill register struct dblock *dbp; 770950Sbill { 771950Sbill register int blk = DMMIN; 772950Sbill register swblk_t *ip = dmp->dm_map; 773950Sbill 774950Sbill if (vsbase < 0 || vsbase + vssize > dmp->dm_size) 775950Sbill panic("vstodb"); 776950Sbill while (vsbase >= blk) { 777950Sbill vsbase -= blk; 778950Sbill if (blk < DMMAX) 779950Sbill blk *= 2; 780950Sbill ip++; 781950Sbill } 782950Sbill dbp->db_size = min(vssize, blk - vsbase); 783950Sbill dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase); 784950Sbill } 785950Sbill 786950Sbill panic(cp) 787950Sbill char *cp; 788950Sbill { 789950Sbill printf("panic!: %s\n", cp); 790950Sbill } 791950Sbill 792950Sbill min(a, b) 793950Sbill { 794950Sbill return (a < b ? a : b); 795950Sbill } 796