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

Defined functions

bad defined in line 668; used 1 times
checkpg defined in line 538; used 1 times
count defined in line 630; used 13 times
dmcheck defined in line 468; used 1 times
dprint defined in line 509; used 4 times
dsort defined in line 461; used 1 times
dump defined in line 679; used 1 times
dumpcm defined in line 710; used 9 times
duse defined in line 444; used 7 times
fixfree defined in line 768; used 1 times
get defined in line 794; used 11 times
getpt defined in line 525; used 1 times
getu defined in line 594; used 1 times
main defined in line 142; never used
min defined in line 878; used 1 times
panic defined in line 872; used 1 times
pdmap defined in line 392; used 1 times
pdmseg defined in line 424; used 2 times
ptdmap defined in line 408; used 1 times
ptetov defined in line 833; used 1 times
summary defined in line 686; used 1 times
vstodb defined in line 851; used 2 times
vtod defined in line 812; used 1 times

Defined variables

Dflg defined in line 33; used 8 times
Usrptma defined in line 60; used 4 times
aproc defined in line 50; used 5 times
atext defined in line 52; used 4 times
cmap defined in line 57; used 12 times
copyright defined in line 8; never used
dblks defined in line 87; used 6 times
dflg defined in line 34; used 3 times
dmmax defined in line 56; used 3 times
dmmin defined in line 56; used 3 times
dmtext defined in line 56; used 11 times
dnames defined in line 500; used 1 times
ecmx defined in line 58; used 2 times
fcore defined in line 103; used 29 times
fflg defined in line 37; used 3 times
firstfree defined in line 61; used 7 times
freemem defined in line 63; used 3 times
fswap defined in line 104; used 8 times
maxfree defined in line 62; used 10 times
mflg defined in line 36; used 2 times
ndblks defined in line 88; used 4 times
nl defined in line 106; used 20 times
nproc defined in line 51; used 8 times
nswapmap defined in line 55; used 9 times
ntext defined in line 53; used 8 times
p0br defined in line 64; used 2 times
paginfo defined in line 72; used 7 times
pid defined in line 65; used 4 times
proc defined in line 50; used 12 times
sccsid defined in line 14; never used
sflg defined in line 38; used 3 times
swapmap defined in line 54; used 3 times
text defined in line 52; used 8 times
tynames defined in line 704; used 1 times
typepg defined in line 619; used 5 times
uflg defined in line 39; used 4 times
usrpt defined in line 59; used 2 times
vflg defined in line 35; used 4 times

Defined struct's

dblks defined in line 82; used 14 times
paginfo defined in line 67; used 12 times

Defined macros

DDATA defined in line 91; used 1 times
DFREE defined in line 90; used 2 times
DPAGET defined in line 95; used 1 times
DSTACK defined in line 92; used 1 times
DTEXT defined in line 93; used 2 times
DUDOT defined in line 94; used 1 times
X_CMAP defined in line 121; used 2 times
X_DMMAX defined in line 135; used 1 times
X_DMMIN defined in line 133; used 1 times
X_DMTEXT defined in line 137; used 1 times
X_ECMAP defined in line 123; used 1 times
X_FIRSTFREE defined in line 113; used 1 times
X_FREEMEM defined in line 119; used 1 times
X_MAXFREE defined in line 115; used 1 times
X_NPROC defined in line 127; used 1 times
X_NSWAPMAP defined in line 131; used 1 times
X_NTEXT defined in line 129; used 1 times
X_PROC defined in line 107; used 1 times
X_PTMA defined in line 111; used 1 times
X_SWAPMAP defined in line 125; used 1 times
X_TEXT defined in line 117; used 1 times
X_USRPT defined in line 109; used 1 times
ZDATA defined in line 74; used 1 times
ZFREE defined in line 79; used 2 times
ZINTRAN defined in line 80; used 6 times
ZLOST defined in line 73; used 1 times
ZPAGET defined in line 77; used 2 times
ZSTACK defined in line 75; used 1 times
ZTEXT defined in line 78; used 3 times
ZUDOT defined in line 76; used 2 times
clear defined in line 47; used 17 times
u defined in line 101; used 11 times
vprintf defined in line 42; used 9 times
zprintf defined in line 638; used 2 times
Last modified: 1986-05-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3055
Valid CSS Valid XHTML 1.0 Strict