1: /*
   2:  *	U N I X   2 . 9 B S D   C R A S H   A N A L Y Z E R
   3:  *
   4:  *
   5:  * Name -
   6:  *	crash -- analyze post-mortem or active system image
   7:  *
   8:  * Author -
   9:  *	Mike Muuss, JHU EE
  10:  *
  11:  * Synopsis of options -
  12:  *
  13:  *	-b	Brief mode; skip general display of processes
  14:  *	-d	Crash dump contains swap image.  (default?)
  15:  *	-v	Verbose; dump much information about each proc [future]
  16:  *	-t	TTY structs to be dumpped
  17:  *	-i	Incore inode table to be printed
  18:  *	-c FILE	Provide non-standard file name for system image input
  19:  *	-s FILE Provide non-standard symboltable input
  20:  *	-u ADDR	Trace a process other than currently selected one
  21:  *	-z	Interrupt Trace displayed
  22:  *	APS	Print PS & PC at time of interupt
  23:  *
  24:  *
  25:  *
  26:  *	synopsis:	crash [aps] [-s sfile] [-c cfile]
  27:  *
  28:  *	It examines a dump of unix which it looks for in the file
  29:  *	sysdump.  It prints out the contents of the general
  30:  *	registers, the kernel stack and a traceback through the
  31:  *	kernel stack.  If an aps is specified, the ps and pc at
  32:  *	time of interrupt are also printed out.  The dump of the
  33:  *	stack commences from a "reasonable" address and all addresses
  34:  *	are relocated to virtual addresses by using the value of
  35:  *	kdsa6 found in the dump.
  36:  *	  If the -s argument is found the following argument is taken
  37:  *	to be the name of a file, containing a symbol table which
  38:  *	should be used in interpreting text addresses.  The default
  39:  *	is "/unix".  If the -c argument is found, the following argument
  40:  *	is taken to be the name of a file which should be used instead
  41:  *	of the default.
  42:  *
  43:  *		R E V I S I O N   H I S T O R Y
  44:  *
  45:  *	??/??/??  MJM	More than I can tell
  46:  *
  47:  *	01/09/80  MJM	Added C-list printing for JHU/UNIX clists.
  48:  *
  49:  *	12/11/80 MJM+RSM Modified to use new MOUNT structure.
  50:  *
  51:  *	12/16/80  RSM	Ability to ask for text or data symbol on printout.
  52:  *
  53:  *	12/21/80  RSM	Added ability to name-list an overlay file.
  54:  *
  55:  *	10/07/81  RSM	Can now print longs in decimal format.
  56:  *		I don't think this works--JCS
  57:  *
  58:  *	12/08/81 JCP+MJM The SYS Group
  59:  *			Modified to work for Version 7 Vanilla UNIX
  60:  *
  61:  *	03/03/83  JCS	Modified for 2.81 kernel
  62:  *		Another new mount structure
  63:  *		Made stack traces work with SRI overlaid kernel
  64:  *		New p_flag values, uses USIZE
  65:  *		Dump of some network stats (broke tty dump--Ritchie
  66:  *		compiler is a crock)
  67:  *		Print longs in octal format.
  68:  *
  69:  *	2/10/84 GLS Modified for 2.9 kernel
  70:  *		Made it work with MENLO_KOV
  71:  *		Output 2.9 clists.
  72:  *
  73:  */
  74: 
  75: #include <sys/param.h>
  76: #include <stdio.h>
  77: #include <sys/stat.h>
  78: #include <sys/buf.h>
  79: #include <sys/clist.h>
  80: #include <sys/callout.h>
  81: #include <sys/file.h>
  82: #include <sys/fs.h>
  83: #include <sys/ioctl.h>
  84: 
  85: #define USIZEB  (64*USIZE)
  86: 
  87: /*
  88:  *-----The following three lines *must* remain together
  89:  */
  90: #include <sys/user.h>
  91: struct  user    u;
  92: char u_wasteXX[USIZEB-sizeof(struct user)]; /* STORAGE FOR KERNEL STACKS
  93: 						 * TO LOAD--must follow user.h
  94: 						 */
  95: #include <sys/proc.h>
  96: #include <sys/text.h>
  97: #include <sys/tty.h>
  98: #include <sys/inode.h>
  99: #include <sys/mount.h>
 100: #include <sys/map.h>
 101: #include <sys/msgbuf.h>
 102: #include "crash.h"
 103: 
 104: struct  buf bfreelist;
 105: struct  proc    *proc;      /* NPROC */
 106: struct  callout *callout;   /* NCALL */
 107: 
 108: /*
 109:  * Interrupt Tracing Strutures - The SYS Group
 110:  */
 111: #ifdef  INTRPT
 112: /*
 113:  * to preserve the integrity of the trace information, the pointer and data
 114:  * area are fetched in the same read.  This means the following two lines
 115:  * *MUST* appear in this order
 116:  */
 117: char    *itrptr;            /* pointer to next structure to use */
 118: struct  itrace  itrace[100];        /* max size of trace area */
 119: /* related kernel variables */
 120: char    *itrstr;            /* start of tracing area */
 121: char    *itrend;            /* end of tracing area */
 122: #endif	INTRPT
 123: 
 124: /* Actual core allocation for tty structures */
 125: int ndh11 = 0;
 126: struct tty *dh11;   /* NDH11 */
 127: int ndz11 = 0;
 128: struct tty *dz11;   /* NDZ11 */
 129: int nkl11 = 0;
 130: struct tty *kl11;   /* NKL11 */
 131: 
 132: 
 133: /* Global Variables */
 134: 
 135: struct msgbuf msgbuf;
 136: char *panicstr;
 137: unsigned saveps;    /* ps after trap */
 138: long    dumplo;     /* Offset of swapspace on dump */
 139: unsigned nbuf;      /* size of buffer cache */
 140: int ncallout;   /* max simultaneous callouts */
 141: int nfile;      /* Stored value of NFILE */
 142: int ninode;     /* Stored value of NINODE */
 143: int nproc;      /* Stored value of NPROC */
 144: int ntext;      /* Stored value of NTEXT */
 145: int nswap;      /* Number of swap blocks */
 146: int nmount;     /* number of mountable file systems */
 147: int nclist;     /* number of clists */
 148: long    stime;      /* crash time */
 149: long    bootime;    /* when system was booted */
 150: unsigned bpaddr;    /* Location of actual buffers (clicks) */
 151: dev_t   rootdev;    /* device of the root */
 152: dev_t   swapdev;    /* swapping device */
 153: dev_t   pipedev;    /* pipe device */
 154: unsigned bsize;     /* size of buffers */
 155: int cputype;    /* type of cpu = 40, 44, 45, 60, or 70 */
 156: struct  inode   *rootdir;   /* pointer to inode of root directory */
 157: struct  proc    *runq;      /* head of linked list of running processes */
 158: int lbolt;          /* clock ticks since time was last updated */
 159: int mpid;           /* generic for unique process id's */
 160: bool_t  runin;          /* set when sched wants to swap someone in */
 161: bool_t  runout;         /* set when sched is out of work */
 162: bool_t  runrun;         /* reschedule at next opportunity */
 163: char    curpri;         /* p_pri of current process */
 164: size_t  maxmem;         /* actual max memory per process */
 165: size_t  physmem;        /* physical memory */
 166: u_short *lks;           /* pointer to clock device */
 167: int updlock;        /* lock for sync */
 168: daddr_t rablock;        /* block to be read ahead */
 169: memaddr clststrt;       /* Location of actual clists (clicks) */
 170: memaddr cfreebase;      /* base of clists in kernel */
 171: unsigned clsize;        /* Size of clists */
 172: short   ucbclist;       /* mapped out clist flag */
 173: 
 174: /*
 175:  * V7 (Stone knives & bear skins memorial) Clist structures.  "cfree" conflicts
 176:  * with calloc's cfree ...
 177:  */
 178: struct  cblock  *cfree_;    /* NCLIST */
 179: struct  cblock  *cfreelist;
 180: int cbad;
 181: 
 182: char    *subhead;           /* pntr to sub-heading */
 183: int line = 0;               /* current line number */
 184: int kmem;               /* Global FD of dump file */
 185: 
 186: int overlay;            /* overlays found flag */
 187: int ovno, ovend;            /* current overlay number */
 188: u_int       aova, aovd;     /* addresses of ova and ovd in core */
 189: unsigned    ova[8], ovd[8];     /* overlay addresses and sizes */
 190: 
 191: /* Display table for Mounted Files */
 192: struct display mnt_tab[] = {
 193:     "\n\nDevice",    (char *) &((struct mount *)0)->m_dev,  DEV, 0,
 194:     "\tOn Inode",    (char *) &((struct mount *)0)->m_inodp, OCT, 0,
 195:     END
 196: };
 197: 
 198: #ifdef  INTRPT
 199: /* Display for Interrupt Tracing Feature (the SYS Group) */
 200: struct  display itr_buf[] {
 201:     "",     &itrace[0].intpc,   OCT, 0,
 202:     "",     &itrace[0].intpc,   TADDR, 0,
 203:     "",     &itrace[0].intps,   OCT, 0,
 204:     "",     &itrace[0].r0,      OCT, 0,
 205:     "",     &itrace[0].r0,      TADDR, 0,
 206:     "",     &itrace[0].savps,   OCT, 0,
 207:     END
 208: };
 209: #endif	INTRPT
 210: 
 211: /* Display table for Callouts */
 212: struct display cal_buf[] = {
 213:     "\nfunc",   (char *) &((struct callout *)0)->c_func, OCT, 0,
 214:     " ",        (char *) &((struct callout *)0)->c_func, TADDR, 0,
 215:     "\targ",    (char *) &((struct callout *)0)->c_arg, DEC, 0,
 216:     "\ttime",   (char *) &((struct callout *)0)->c_time,DEC, 0,
 217:     END
 218: };
 219: 
 220: 
 221: /* Display for C-list display */
 222: struct display cl_buf[] = {
 223:     ": link",   (char *) &((struct cblock *)0)->c_next, OCT, 0,
 224:     "\tCh",     (char *) ((struct cblock *)0)->c_info,  CHARS, 0,
 225:     END
 226: };
 227: 
 228: int ttyflg(), ttystat();
 229: 
 230: /* Display for tty structures */
 231: struct display tty_buf[] = {
 232:     "\n\nMaj/Min",  (char *) &((struct tty *)0)->t_dev, DEV, 0,
 233:     "\nFlags",  (char *) &((struct tty *)0)->t_flags,   OCT, ttyflg,
 234:     "\nAddr",   (char *) &((struct tty *)0)->t_addr,    OCT, 0,
 235:     "",     (char *) &((struct tty *)0)->t_addr,    DADDR, 0,
 236:     "\nDelct",  (char *) &((struct tty *)0)->t_delct,   HALFDEC, 0,
 237:     "\nLine",   (char *) &((struct tty *)0)->t_line,    HALFDEC, 0,
 238:     "\nCol",    (char *) &((struct tty *)0)->t_col, HALFDEC, 0,
 239:     "\nState",  (char *) &((struct tty *)0)->t_state,   OCT, ttystat,
 240:     "\nIspeed", (char *) &((struct tty *)0)->t_ispeed,  HALFDEC, 0,
 241:     "\tOspeed", (char *) &((struct tty *)0)->t_ospeed,  HALFDEC, 0,
 242:     "\nRAW",    (char *) &((struct tty *)0)->t_rawq.c_cc,DEC, 0,
 243:     "\tc_cf",   (char *) &((struct tty *)0)->t_rawq.c_cf,OCT, 0,
 244:     "\tc_cl",   (char *) &((struct tty *)0)->t_rawq.c_cl,OCT, 0,
 245:     "\nOUT",    (char *) &((struct tty *)0)->t_outq.c_cc,DEC, 0,
 246:     "\tc_cf",   (char *) &((struct tty *)0)->t_outq.c_cf,OCT, 0,
 247:     "\tc_cl",   (char *) &((struct tty *)0)->t_outq.c_cl,OCT, 0,
 248:     "\nCAN",    (char *) &((struct tty *)0)->t_canq.c_cc,DEC, 0,
 249:     "\tc_cf",   (char *) &((struct tty *)0)->t_canq.c_cf,OCT, 0,
 250:     "\tc_cl",   (char *) &((struct tty *)0)->t_canq.c_cl,OCT, 0,
 251:     END
 252: };
 253: 
 254: /* Display table for Random Variables */
 255: struct display rv_tab[] = {
 256:     "\nRoot directory", (char *) &rootdir,  OCT, 0,
 257:     "\nLightningbolt",  (char *) &lbolt,        DEC, 0,
 258:     "\nNext PID",       (char *) &mpid,     DEC, 0,
 259:     "\n   runrun",      &runrun,    OCT, 0,
 260:     "\n   runout",      &runout,    OCT, 0,
 261:     "\n   runin",       &runin,     OCT, 0,
 262:     "\n   curpri",      &curpri,    OCT, 0,
 263:     "\n   maxmem",      (char *) &maxmem,   OCT, 0,
 264:     "\n   physmem",     (char *) &physmem,  OCT, 0,
 265:     "\nClock addr",     (char *) &lks,      OCT, 0,
 266:     "\nRoot dev",       (char *) &rootdev,  DEV, 0,
 267:     "\nSwap Dev",       (char *) &swapdev,  DEV, 0,
 268:     "\nPipe Dev",       (char *) &pipedev,  DEV, 0,
 269:     "\nSwap Size",      (char *) &nswap,        DEC, 0,
 270:     "\nupdate() lock",      (char *) &updlock,  DEC, 0,
 271:     "\nReadahead blk",  (char *) &rablock,  OCT, 0,
 272:     "\n    Max procs",      (char *) &nproc,    DEC, 0,
 273:     "\n    Max inodes",     (char *) &ninode,   DEC, 0,
 274:     "\n    Max files",      (char *) &nfile,    DEC, 0,
 275:     "\n    Max texts",      (char *) &ntext,    DEC, 0,
 276:     "\n*cfreelist",     (char *) &cfreelist,    OCT, 0,
 277:     "\nSystem Buffer start click",  (char *) &bpaddr,   OCT, 0,
 278:     "\tNo. Buffers",    (char *) &nbuf, DEC, 0,
 279:     "\tSize",   (char *) &bsize,    OCT, 0,
 280:     "\nClist start click",  (char *) &clststrt,     OCT, 0,
 281:     "\nClist start address",(char *) &cfreebase,        OCT, 0,
 282:     "\tSize of area",   (char *) &clsize,       DEC, 0,
 283:     END
 284: };
 285: 
 286: int pdrprint(), printuid(), printgid();
 287: 
 288: struct  display ov_tab[] = {
 289: "\n\nThe Kernel Overlay Information and Variables:\n\t__ovno",
 290:             (char *) &ovno,     DEC, 0,
 291:     "\n\tOverlay #0 PAR",       (char *) &ova[0],   OCT, 0,
 292:     "\tPDR",            (char *) &ovd[0],   OCT, pdrprint,
 293:     "\n\tOverlay #1 PAR",       (char *) &ova[1],   OCT, 0,
 294:     "\tPDR",            (char *) &ovd[1],   OCT, pdrprint,
 295:     "\n\tOverlay #2 PAR",       (char *) &ova[2],   OCT, 0,
 296:     "\tPDR",            (char *) &ovd[2],   OCT, pdrprint,
 297:     "\n\tOverlay #3 PAR",       (char *) &ova[3],   OCT, 0,
 298:     "\tPDR",            (char *) &ovd[3],   OCT, pdrprint,
 299:     "\n\tOverlay #4 PAR",       (char *) &ova[4],   OCT, 0,
 300:     "\tPDR",            (char *) &ovd[4],   OCT, pdrprint,
 301:     "\n\tOverlay #5 PAR",       (char *) &ova[5],   OCT, 0,
 302:     "\tPDR",            (char *) &ovd[5],   OCT, pdrprint,
 303:     "\n\tOverlay #6 PAR",       (char *) &ova[6],   OCT, 0,
 304:     "\tPDR",            (char *) &ovd[6],   OCT, pdrprint,
 305:     "\n\tOverlay #7 PAR",       (char *) &ova[7],   OCT, 0,
 306:     "\tPDR",            (char *) &ovd[7],   OCT, pdrprint,
 307: 
 308:     "\n\tOverlay #8 PAR",       (char *) &ova[8],   OCT, 0,
 309:     "\tPDR",            (char *) &ovd[8],   OCT, pdrprint,
 310:     "\n\tOverlay #9 PAR",       (char *) &ova[9],   OCT, 0,
 311:     "\tPDR",            (char *) &ovd[9],   OCT, pdrprint,
 312:     "\n\tOverlay #a PAR",       (char *) &ova[10],  OCT, 0,
 313:     "\tPDR",            (char *) &ovd[10],  OCT, pdrprint,
 314:     "\n\tOverlay #b PAR",       (char *) &ova[11],  OCT, 0,
 315:     "\tPDR",            (char *) &ovd[11],  OCT, pdrprint,
 316:     "\n\tOverlay #c PAR",       (char *) &ova[12],  OCT, 0,
 317:     "\tPDR",            (char *) &ovd[12],  OCT, pdrprint,
 318:     "\n\tOverlay #d PAR",       (char *) &ova[13],  OCT, 0,
 319:     "\tPDR",            (char *) &ovd[13],  OCT, pdrprint,
 320:     "\n\tOverlay #e PAR",       (char *) &ova[14],  OCT, 0,
 321:     "\tPDR",            (char *) &ovd[14],  OCT, pdrprint,
 322:     "\n\tOverlay #f PAR",       (char *) &ova[15],  OCT, 0,
 323:     "\tPDR",            (char *) &ovd[15],  OCT, pdrprint,
 324:     END
 325: };
 326: 
 327: int bufflg();
 328: 
 329: struct display buf_tab[] = {
 330:     "\nFlags",  (char *) &((struct buf *)0)->b_flags,   OCT, bufflg,
 331:     "\tdev",    (char *) &((struct buf *)0)->b_dev, DEV, 0,
 332:     "\tbcount", (char *) &((struct buf *)0)->b_bcount,  DEC, 0,
 333:     "\nxmem",   &((struct buf *)0)->b_xmem, ONEBYTE, 0,
 334:     "\taddr",   (char *) &((struct buf *)0)->b_un.b_addr, OCT, 0,
 335:     "\tblkno",  (char *) &((struct buf *)0)->b_blkno,   LONGDEC, 0,
 336:     "\nerror",  &((struct buf *)0)->b_error,    ONEBYTE, 0,
 337:     "\tresid",  (char *) &((struct buf *)0)->b_resid,   OCT, 0,
 338:     END
 339: };
 340: 
 341: int inoflg(), inomod();
 342: 
 343: struct display inode_tab[] = {
 344:     "\ndev",    (char *) &((struct inode *)0)->i_dev,DEV, 0,
 345:     "\tnumber", (char *) &((struct inode *)0)->i_number,DEC,0,
 346:     "\tcount",  (char *) &((struct inode *)0)->i_count, DEC,0,
 347:     "\tflag",   (char *) &((struct inode *)0)->i_flag,  OCT,inoflg,
 348:     "\nnlink",  (char *) &((struct inode *)0)->i_nlink, DEC,0,
 349:     "\tuid",    (char *) &((struct inode *)0)->i_uid,   UDEC,printuid,
 350:     "\tgid",    (char *) &((struct inode *)0)->i_gid,   UDEC,printgid,
 351:     "\nmode",   (char *) NULL,  IGNORE, inomod,
 352:     END
 353: };
 354: 
 355: /* Display the USER Structure */
 356: /*
 357:  * note that on V7, the u.u_ar0 and u.u_qsav areas contain more than
 358:  * they do on V6 UNIX
 359:  *
 360:  *	On V6	u.u_ar0[0]  = saved R5
 361:  *		u.u_ar0[1]  = saved R6
 362:  *
 363:  *	On V7	u.u_ar0[0]  = saved R2
 364:  *		u.u_ar0[1]  = saved R3
 365:  *		u.u_ar0[2]  = saved R4
 366:  *		u.u_ar0[3]  = saved R5
 367:  *		u.u_ar0[4]  = saved R6 (stack pointer)
 368:  *
 369:  * for this reason, we declare the following labels, which must be used
 370:  * anywhere the saved registers are referenced
 371:  */
 372: #define R2  0   /* index of saved R2 */
 373: #define R3  1
 374: #define R4  2
 375: #define R5  3
 376: #define R6  4
 377: #define R1  5
 378: 
 379: struct display u_tab[] = {
 380:     "\nsaved R5",   (char *) &(u.u_rsave.val[R5]),  OCT, 0,
 381:     "\tsaved R6",   (char *) &(u.u_rsave.val[R6]),  OCT, 0,
 382:     "\tsegflg", &(u.u_segflg),          ONEBYTE, 0,
 383:     "\terror",  &(u.u_error),           HALFDEC, 0,
 384:     "\nuid",    (char *) &(u.u_uid),        UDEC, printuid,
 385:     "\nsvuid",  (char *) &(u.u_svuid),      UDEC, printuid,
 386:     "\nruid",   (char *) &(u.u_ruid),       UDEC, printuid,
 387:     "\tsvgid",  (char *) &(u.u_svgid),      UDEC, printgid,
 388:     "\trgid",   (char *) &(u.u_rgid),       UDEC, printgid,
 389:     "\tgroups", (char *) u.u_groups,        UDEC, printgid,
 390:     "\nprocp",  (char *) &(u.u_procp),      OCT, 0,
 391:     "\tbase",   (char *) &(u.u_base),       OCT, 0,
 392:     "\tcount",  (char *) &(u.u_count),      DEC, 0,
 393:     "\toff",    (char *) &(u.u_offset),     HEXL, 0,
 394:     "\ncdir",   (char *) &(u.u_cdir),       OCT, 0,
 395:     "\tdirp",   (char *) &(u.u_dirp),       OCT, 0,
 396:     "\tpdir",   (char *) &(u.u_pdir),       OCT, 0,
 397:     "\targ0",   (char *) &(u.u_arg[0]),     OCT, 0,
 398:     "\narg1",   (char *) &(u.u_arg[1]),     OCT, 0,
 399:     "\targ2",   (char *) &(u.u_arg[2]),     OCT, 0,
 400:     "\targ3",   (char *) &(u.u_arg[3]),     OCT, 0,
 401:     "\targ4",   (char *) &(u.u_arg[4]),     OCT, 0,
 402:     "\narg5",   (char *) &(u.u_arg[5]),     OCT, 0,
 403:     "\ttsize",  (char *) &(u.u_tsize),      DEC, 0,
 404:     "\tdsize",  (char *) &(u.u_dsize),      DEC, 0,
 405:     "\tssize",  (char *) &(u.u_ssize),      DEC, 0,
 406:     "\nctty",   (char *) &(u.u_ttyp),       OCT, 0,
 407:     "\tttydev", (char *) &(u.u_ttyd),       DEV, 0,
 408:     "\nsep",    &(u.u_sep),     ONEBYTE, 0,
 409:     "\tar0",    (char *) &(u.u_ar0),    OCT, 0,
 410:     END
 411: };
 412: 
 413: int procflg(), prtsig();
 414: 
 415: /* Display table for Proc Structure */
 416: struct display proc_tab[] = {
 417:     "\nStat",   (char *) &((struct proc *)0)->p_stat,   ONEBYTE, 0,
 418:     "\tFlags",  (char *) &((struct proc *)0)->p_flag,   HEX, procflg,
 419:     "\nPri",    (char *) &((struct proc *)0)->p_pri,    HALFDEC, 0,
 420:     "\tSig",    (char *) &((struct proc *)0)->p_sig,    HEXL, 0,
 421:     "\tCursig", (char *) &((struct proc *)0)->p_cursig, HALFDEC, 0,
 422:     "\tUid",    (char *) &((struct proc *)0)->p_uid,    DEC, printuid,
 423:     "\nsigmask",    (char *) &((struct proc *)0)->p_sigmask,HEXL, prtsig,
 424:     "\nsigignore",  (char *) &((struct proc *)0)->p_sigignore,HEXL, prtsig,
 425:     "\nsigcatch",   (char *) &((struct proc *)0)->p_sigcatch,HEXL, prtsig,
 426:     "\nTime",   (char *) &((struct proc *)0)->p_time,   HALFDEC, 0,
 427:     "\tcpu",    (char *) &((struct proc *)0)->p_cpu,    HALFDEC, 0,
 428:     "\tnice",   (char *) &((struct proc *)0)->p_nice,   HALFDEC, 0,
 429:     "\tpgrp",   (char *) &((struct proc *)0)->p_pgrp,   OCT, 0,
 430:     "\nPid",    (char *) &((struct proc *)0)->p_pid,    DEC, 0,
 431:     "\tPpid",   (char *) &((struct proc *)0)->p_ppid,   DEC, 0,
 432:     "\taddr",   (char *) &((struct proc *)0)->p_addr,   OCT, 0,
 433:     "\tdaddr",  (char *) &((struct proc *)0)->p_daddr,  OCT, 0,
 434:     "\tsaddr",  (char *) &((struct proc *)0)->p_saddr,  OCT, 0,
 435:     "\tdsize",  (char *) &((struct proc *)0)->p_dsize,  OCT, 0,
 436:     "\tssize",  (char *) &((struct proc *)0)->p_ssize,  OCT, 0,
 437:     "\ntextp",  (char *) &((struct proc *)0)->p_textp,  OCT, 0,
 438:     "\tWchan",  (char *) &((struct proc *)0)->p_wchan,  OCT, 0,
 439:     "",     (char *) &((struct proc *)0)->p_wchan,  DADDR, 0,
 440:     "\nRlink",  (char *) &((struct proc *)0)->p_link,   OCT, 0,
 441:     "\tClktim", (char *) &((struct proc *)0)->p_clktim, DEC, 0,
 442:     "\tSlptim", (char *) &((struct proc *)0)->p_slptime, HALFDEC, 0,
 443:     END
 444: };
 445: 
 446: /* The Process Status word interpretation */
 447: char *pmsg1[] = {
 448:     "<null>",
 449:     "Sleeping (all cases)",
 450:     "Abandoned Wait State",
 451:     "*** Running ***",
 452:     "Being created",
 453:     "Being Terminated (ZOMB)",
 454:     "Ptrace Stopped",
 455:     "<eh?>"
 456: };
 457: 
 458: /* The Process Flag Word bit table */
 459: char *p_bits[] = {
 460:     "in core, ",
 461:     "scheduler proc, ",
 462:     "locked in core, ",
 463:     "being swapped, ",
 464:     "being traced, ",
 465:     "WTED, ",
 466:     "ULOCK, ",
 467:     "OMASK,",
 468:     "VFORK, ",
 469:     "VFPRINT, ",
 470:     "VFDONE, ",
 471:     "timing out, ",
 472:     "detached, ",
 473:     "OUSIG, ",
 474:     "selecting, ",
 475: };
 476: #define FLAG_MASK   037777
 477: 
 478: 
 479: /*
 480:  *	This table lists all of the dump variables to be fetched.
 481:  */
 482: 
 483: struct fetch fetchtab[] = {
 484: 
 485: #ifdef  INTRPT
 486:     /* interrupt tracing feature - The SYS Group */
 487:     "_savptr",  &itrptr,    sizeof itrptr + sizeof itrace,
 488: #endif
 489: 
 490:     "_bfreelist",   (char *) &bfreelist,    sizeof bfreelist,
 491:     "_nfile",   (char *) &nfile,        sizeof nfile,
 492:     "_nmount",  (char *) &nmount,       sizeof nmount,
 493:     "_nproc",   (char *) &nproc,        sizeof nproc,
 494:     "_ntext",   (char *) &ntext,        sizeof ntext,
 495:     "_nclist",  (char *) &nclist,       sizeof nclist,
 496:     "_nbuf",    (char *) &nbuf,     sizeof nbuf,
 497:     "_ncallout",    (char *) &ncallout, sizeof ncallout,
 498:     "_u",       (char *) &u,        sizeof u,
 499:     "_bpaddr",  (char *) &bpaddr,       sizeof bpaddr,
 500:     "_bsize",   (char *) &bsize,        sizeof bsize,
 501:     "_ucb_cli", (char *) &ucbclist,     sizeof ucbclist,
 502:     "_clststrt",    (char *) &clststrt,     sizeof clststrt,
 503:     "_cfree",   (char *) &cfreebase,        sizeof cfreebase,
 504:     "_ninode",  (char *) &ninode,       sizeof ninode,
 505: 
 506:     /* Random Variables */
 507: #ifdef  notdef
 508:     "_dumplo",  (char *) &dumplo,   sizeof dumplo,
 509: #endif	notdef
 510:     "_rootdir", (char *) &rootdir,  sizeof rootdir,
 511:     "_cputype", (char *) &cputype,  sizeof cputype,
 512:     "_lbolt",   (char *) &lbolt,        sizeof lbolt,
 513:     "_time",    (char *) &stime,        sizeof stime,
 514:     "_boottim", (char *) &bootime,  sizeof bootime,
 515:     "_mpid",    (char *) &mpid,     sizeof mpid,
 516:     "_runrun",  (char *) &runrun,   sizeof runrun,
 517:     "_runout",  (char *) &runout,   sizeof runout,
 518:     "_runin",   (char *) &runin,    sizeof runin,
 519:     "_curpri",  (char *) &curpri,   sizeof curpri,
 520:     "_maxmem",  (char *) &maxmem,   sizeof maxmem,
 521:     "_physmem", (char *) &physmem,  sizeof physmem,
 522:     "_rootdev", (char *) &rootdev,  sizeof rootdev,
 523:     "_swapdev", (char *) &swapdev,  sizeof swapdev,
 524:     "_pipedev", (char *) &pipedev,  sizeof pipedev,
 525:     "_nswap",   (char *) &nswap,        sizeof nswap,
 526:     "_updlock", (char *) &updlock,  sizeof updlock,
 527:     "_rablock", (char *) &rablock,  sizeof rablock,
 528:     "_msgbuf",  (char *) &msgbuf,   sizeof msgbuf,
 529:     "_panicst", (char *) &panicstr, sizeof panicstr,
 530:     END
 531: };
 532: 
 533: struct  fetch fetch1tab[] = {
 534:     "__ovno",   (char *) &ovno,     sizeof ovno,
 535:     END
 536: };
 537: 
 538: /*
 539:  *	This table lists all addresses to be fetched.
 540:  */
 541: 
 542: struct fetch fetchatab[] = {
 543:     "ova",      (char *) &aova,         sizeof *ova,
 544:     "ovd",      (char *) &aovd,         sizeof *ovd,
 545:     END
 546: };
 547: 
 548: char    *corref = "/core";      /* Default dump file */
 549: char *symref = "/unix";
 550: char *MIS_ARG = "Missing arg";
 551: 
 552: unsigned find(); int stroct();
 553: char    *calloc();
 554: 
 555: /* Flag definitions */
 556: int bflg = 0;               /* brief flag -- u only */
 557: int dflg = 0;               /* Swapdev flag */
 558: int vflg = 0;               /* verbose flag -- dump each proc */
 559: int tflg = 0;               /* dump tty structs flag */
 560: int iflg = 0;               /* dump inode table flag */
 561: #ifdef  INTRPT
 562: int trflg = 0;              /* interrupt trace display flag */
 563: #endif	INTRPT
 564: 
 565: 
 566: /*
 567:  *			M A I N
 568:  *
 569:  *	Consume options and supervise the flow of control
 570:  *
 571:  */
 572: 
 573: main(argc,argv)
 574: int argc;
 575: char **argv;
 576: {
 577:     static unsigned *up;    /*!!! never initialized */
 578:     register int i;
 579: 
 580:     int trapstack;
 581:     int u_addr;             /* u block number */
 582:     int u_death;            /* death u */
 583:     unsigned sp;
 584:     unsigned r5;
 585:     unsigned xbuf[8];
 586: 
 587:     trapstack = 0;
 588:     u_addr = 0;
 589: 
 590:     /* parse off the arguments and do what we can with them */
 591:     for(i=1; i<argc; i++)
 592:         if( *argv[i] == '-' ) {
 593:         switch( argv[i][1] ) {
 594: 
 595:         case 'c':
 596:             /* Coredump input file name */
 597:             if ((i+1) >= argc) barf( MIS_ARG );
 598:             corref = argv[++i];
 599:             continue;
 600: 
 601:         case 's':
 602:             /* Symboltable input file name */
 603:             if ((i+1) >= argc) barf( MIS_ARG );
 604:             symref = argv[++i];
 605:             continue;
 606: 
 607:         case 'u':
 608:             /* trace a process other than current (takes U addr) */
 609:             if ((i+1) >= argc) barf( MIS_ARG );
 610:             u_addr = stroct( argv[++i] );
 611:             continue;
 612: 
 613:         case 'b':
 614:             /* Brief */
 615:             bflg++;
 616:             continue;
 617: 
 618:         case 'd':
 619:             /* Dump includes swap area */
 620:             dflg++;
 621:             continue;
 622: 
 623:         case 'v':   /* do everything */
 624:             /* Verbose */
 625:             vflg++;
 626:             continue;
 627: 
 628:         case 't':
 629:             /* TTY structures */
 630:             tflg++;
 631:             continue;
 632: 
 633:         case 'i':
 634:             /* Inode table */
 635:             iflg++;
 636:             continue;
 637: 
 638: #ifdef  INTRPT
 639:         case 'z':
 640:             /* Interrupt Trace */
 641:             trflg++;
 642:             continue;
 643: #endif	INTRPT
 644: 
 645:         default:
 646:             printf("Bad argument:  %s\n", argv[i]);
 647: 
 648:         case 'h':
 649:             /* Help message */
 650:             printf("Usage:  crash [-i] [-d] -[t] [-c dumpfile] [-s symtab file] [-u u-addr]\n\n");
 651:             exit(0);
 652:         }
 653: 
 654:         } else {
 655:         trapstack = stroct( argv[i] );
 656:         if( trapstack == 0 )
 657:             printf("Bad argument:  %s\n", argv[i]);
 658:         }
 659: 
 660:     kmem = open(corref,0);
 661:     if (kmem < 0) {
 662:         printf("Unable to open %s\n",corref);
 663:         exit(-1);
 664:     }
 665: 
 666:     /*
 667: 	 * Load the symbol table
 668: 	 */
 669:     getsym(symref);
 670: 
 671:     /*
 672: 	 * Load all of the shadow variables from the dump file,
 673: 	 * and print the header page.
 674: 	 */
 675:     fetch(fetchtab);
 676: 
 677:     if (tflg) {
 678:         clsize = nclist * sizeof(struct cblock);
 679:         cfree_ = (struct cblock *)calloc(nclist,sizeof(struct cblock));
 680:         if (cfree_ == (struct cblock *) NULL) {
 681:             printf("crash: out of memory getting cfree\n");
 682:             exit(1);
 683:         }
 684:         /* CLIST loaded first, improve accuracy on dump running sys */
 685:         if (!vf("_cfreeli", (char *) &cfreelist, sizeof cfreelist)) {
 686:             printf("could not find _cfreeli\n");
 687:             exit(1);
 688:         }
 689:     if  (ucbclist)
 690:         lseek(kmem, (off_t)ctob((long)clststrt), 0); /* clists click */
 691:     else
 692:         lseek(kmem, (off_t) cfreebase, 0);  /* clists in kernel  */
 693: 
 694:         read(kmem, (caddr_t) cfree_, clsize);
 695: 
 696:         vf("_nkl11", (char *) &nkl11, sizeof nkl11);
 697:         kl11 = (struct tty *) calloc(nkl11, sizeof(struct tty));
 698:         if (kl11 == (struct tty *) NULL) {
 699:             printf("crash: out of memory in kl11\n");
 700:             exit(1);
 701:         }
 702:         vf("_kl11", (char *) kl11, sizeof(struct tty)*nkl11);
 703:         if (vf("_ndh11", (char *) &ndh11, sizeof ndh11)) {
 704:             dh11 = (struct tty *) calloc(ndh11, sizeof(struct tty));
 705:             if (dh11 == (struct tty *) NULL) {
 706:                 printf("crash: out of memory in dh11\n");
 707:                 exit(1);
 708:             }
 709:             vf("_dh11", (char *) dh11, sizeof(struct tty)*ndh11);
 710:         }
 711:         if (vf("_ndz11", (char *) &ndz11, sizeof dz11)) {
 712:             dz11 = (struct tty *) calloc(ndz11, sizeof(struct tty));
 713:             if (dz11 == (struct tty *) NULL) {
 714:                 printf("crash: out of memory in dz11\n");
 715:                 exit(1);
 716:             }
 717:             vf("_dz11", (char *) dz11, sizeof(struct tty)*ndz11);
 718:         }
 719:     }
 720: 
 721:     /*
 722: 	 *	Setup for MENLO_KOV
 723: 	 */
 724:     if (overlay) {
 725:         fetch(fetch1tab);
 726:         fetcha(fetchatab);
 727:         vf("ova", (char *) ova, sizeof ova);
 728:         vf("ovd", (char *) ovd, sizeof ovd);
 729:         getpars();
 730:     }
 731: 
 732:     /* Display general information */
 733:     general();
 734: 
 735:     /*	dump the registers	*/
 736:     subhead = "Registers & Stack Dump";
 737:     saveps = find("saveps", 0);
 738:     lseek(kmem, (off_t) saveps, 0);
 739:     read(kmem, (caddr_t)&saveps, sizeof saveps);
 740:     newpage();
 741:     printf("\tThe registers\n");
 742:     lseek(kmem, (off_t)0300,0);
 743:     read(kmem,xbuf,sizeof xbuf);
 744:     printf("\nr0: "); octout(xbuf[0]); /* 2 */
 745:     putchar(' ');     if(!symbol(xbuf[0], DSYM, 0)) putchar('\t');
 746:     printf("\tr1: "); octout(xbuf[1]); /* 3 */
 747:     putchar(' ');     if(!symbol(xbuf[1], DSYM, 0)) putchar('\t');
 748:     printf("\tr2: "); octout(xbuf[2]); /* 4 */
 749:     putchar(' ');     if(!symbol(xbuf[2], DSYM, 0)) putchar('\t');
 750:     printf("\nr3: "); octout(xbuf[3]); /* 5 */
 751:     putchar(' ');     if(!symbol(xbuf[3], DSYM, 0)) putchar('\t');
 752:     printf("\tr4: "); octout(xbuf[4]); /* 6 */
 753:     putchar(' ');     if(!symbol(xbuf[4], DSYM, 0)) putchar('\t');
 754:     printf("\tr5: "); octout(xbuf[5]); /* 7 */
 755:     putchar(' ');     if(!symbol(xbuf[5], DSYM, 0)) putchar('\t');
 756:     printf("\nsp: "); octout(xbuf[6]); /* 8 */
 757:     putchar(' ');     if(!symbol(xbuf[6], DSYM, 0)) putchar('\t');
 758:     printf("\tksda: "); octout(xbuf[7]); /* 9 */
 759:     printf("\t\tps: "); octout(saveps); printps(saveps);
 760:     /* was: sp = xbuf[6] & 0177760; /*!!! why this mask?? */
 761:     sp = xbuf[6] & 0177776;
 762:     r5 = xbuf[5];
 763: 
 764:     /*
 765: 	 *	Take a stack dump
 766: 	 */
 767:     u_death = xbuf[7];
 768:     if( u_addr == 0 )
 769:         u_addr = u_death;
 770: 
 771:     /* lseek in u_addr core clicks (64 bytes) */
 772:     lseek(kmem, (off_t)(unsigned)u_addr<<6,0);
 773:     read (kmem, &u, USIZEB);
 774: 
 775:     if (u_addr != u_death) {
 776:         sp = u.u_rsave.val[R6];
 777:         r5 = u.u_rsave.val[R5];
 778:     }
 779: 
 780:     printf ("\n\n u at 0%o, r5 = 0%o, sp = 0%o\n\n", u_addr, r5, sp);
 781: 
 782:     /*	If an aps was specified, give ps, pc, sp at trap time */
 783:     if (trapstack == 0) {
 784:         trapstack = sp; /* temporary */
 785:     }
 786:     else {
 787:         printf("\n\n\timmediately prior to the trap:\n");
 788:         printf("\nsp: "); octout((unsigned)sp+4);
 789:         printf("\tps: "); octout(up[1]);
 790:         printf("\tpc: "); octout(up[0]);
 791:         putchar(' ');
 792:         symbol(up[0], ISYM, 0);
 793:     }
 794: 
 795:     stackdump( sp-2, sp-4 );    /* current r5 and some number less */
 796: 
 797:     /* Display Procsss information */
 798:     if (!bflg) dprocs();
 799: 
 800:     putchar('\n');      /* Flush buffer:  The End */
 801:     exit(0);
 802: }
 803: 
 804: 
 805: /*
 806:  *			S T A C K D U M P
 807:  *
 808:  * This routine interprets the kernel stack in the
 809:  * user structure (_u).
 810:  */
 811: stackdump( r5, sp )
 812: unsigned r5, sp;
 813: {
 814:     register unsigned *up;
 815:     register unsigned i;
 816: 
 817:     if ((sp < 0140000) || (sp > 0140000+USIZEB-18)) {
 818:         printf("\n\tsp(%0o) is unreasonable, 0140000 assumed\n", sp);
 819:         sp = 0140000;
 820:         /* since sp is bad, give him whole user area */
 821:     }
 822: 
 823:     /* now give a dump of the stack, relocating as we go */
 824:     printf("\n\n");
 825:     printf("STACK:  loc+00 loc+02 loc+04 loc+06   loc+10 loc+12 loc+14 loc+16");
 826: 
 827:     for( i = sp & ~017; i < 0140000+USIZEB; i += 16) {
 828: 
 829:         up = (unsigned *) &u;
 830:         up += ((int)i - 0140000)>>1;    /* damn pointer conversions */
 831:         printf("\n"); octout(i);
 832:         printf(": "); octout(up[0]);
 833:         printf(" "); octout(up[1]);
 834:         printf(" "); octout(up[2]);
 835:         printf(" "); octout(up[3]);
 836:         printf("   "); octout(up[4]);
 837:         printf(" "); octout(up[5]);
 838:         printf(" "); octout(up[6]);
 839:         printf(" "); octout(up[7]);
 840:     }
 841: 
 842:     /* go back to beginning of stack space and give trace */
 843:     printf("\n\n");
 844:     printf("TRACE:   old r2  old r3  old r4  ");
 845:     if (overlay)
 846:         printf("ovno    ");
 847:     printf("old r5  old pc");
 848:     i = sp;
 849:     while ((r5 > i) && (r5 < 0140000+USIZEB)) {
 850:         if (r5 == 0140000+USIZEB-18) break;
 851:         up = (unsigned *) &u;
 852:         up += ((int)r5 - 0140000)>>1;
 853:         printf("\n"); octout(r5);
 854:         printf(":  ");
 855:         if (overlay) {
 856:                   octout(up[-4]);
 857:         printf("  ");
 858:         }
 859:                   octout(up[-3]);
 860:         printf("  "); octout(up[-2]);
 861:         printf("  "); octout(up[-1]);
 862:         printf("  "); octout(up[0]);
 863:         printf("  "); octout(up[1]);
 864:         putchar(' ');
 865:         symbol(up[1], ISYM, (overlay ? up[-1] : 0));
 866:         i = r5 + 4;
 867:         r5 = up[0];
 868:     }
 869:     putchar('\n');
 870:     if (r5 != 0140000+USIZEB-18)
 871:         printf("\tThe dynamic chain is broken\n");
 872: }
 873: 
 874: 
 875: /*
 876:  *			G E N E R A L
 877:  *
 878:  *
 879:  * Display information of a general nature
 880:  */
 881: general() {
 882:     register int    i;  /* multi-function counter */
 883:     register int    j;
 884: 
 885:     /* Set up page heading */
 886:     subhead = "General Information";
 887:     newpage();
 888: 
 889:     /* Tell general stuff */
 890:     printf("UNIX Version 2.10bsd was running on a PDP-11/%d CPU\n",
 891:         cputype);
 892:     printf("when a crash occured at %s", ctime(&stime));
 893:     printf("system booted at %s", ctime(&bootime));
 894:     /* print panic message */
 895:     panicpr();
 896:     printf("\n\nThe `Random Variables' at time of crash:\n\n");
 897:     display(rv_tab, 0);
 898:     if (overlay)
 899:         display(ov_tab, 0);
 900:     /* print contents of msgbf */
 901:     msgbufpr();
 902:     /* Display Mount Table */
 903:     {
 904:         struct mount *mount;    /* NMOUNT */
 905:         register struct mount *mp;
 906: 
 907:         mount = (struct mount *) calloc(nmount, sizeof(struct mount));
 908:         if (mount != (struct mount *) NULL) {
 909:             subhead = "The Mount Structure";
 910:             newpage();
 911:             if (vf("_mount", (char *)mount,
 912:                 sizeof(struct mount)*nmount))
 913:                 for(mp = mount; mp < &mount[nmount]; mp++)
 914:                     if (mp->m_dev) {
 915:                         display(mnt_tab, mp);
 916:                         printdev(mp);
 917:                     }
 918:             free(mount);
 919:         }
 920:     }
 921: 
 922:     /* Display mbuf status info */
 923:     dispnet();
 924: 
 925:     /* Display the Callouts */
 926:     if( tflg )  {
 927:         struct callout *cp;
 928: 
 929:         subhead = "The Callout Structure";
 930:         newpage();
 931:         callout = (struct callout *) calloc(ncallout, sizeof(struct callout));
 932:         if (callout == (struct callout *) NULL) {
 933:             printf("crash: out of memory getting callout\n");
 934:             exit(1);
 935:         }
 936:         vf("_callout", (char *) callout, sizeof(struct callout)*ncallout);
 937:         for(cp=callout; cp<&callout[ncallout]; cp++)
 938:             if (cp->c_func)
 939:                 display( cal_buf, cp );
 940:         free(callout);
 941:     }
 942: 
 943: #ifdef  INTRPT
 944:     /* Display Interrupt Trace */
 945:     if( trflg )  {
 946:         itrstr = find( "_savstr", 1 );
 947:         itrend = find( "_savend", 1 );
 948:         subhead = "The Interrupt Trace (The SYS Group)";
 949:         newpage();
 950:         printf("\nEntry %d was the last trap processed\n",
 951:             (itrptr - itrstr)/(sizeof (struct itrace)) - 1
 952:         );
 953: 
 954:         printf("\nEntry\tInt PC\t<address>\tInt PS\tTrap r0\t<address>\tTrap PS\n");
 955:         for(i = 0; i < (itrend - itrstr)/(sizeof(struct itrace)); i++)
 956:         {
 957:             printf("\n%3d",i);
 958:             display( itr_buf, i*(sizeof (struct itrace)) );
 959:         }
 960:     }
 961: #endif
 962: 
 963:     /* If requested, dump tty structures and C-list */
 964:     if( tflg )  {
 965:         struct tty *tp;
 966:         struct cblock *bp;
 967: 
 968:         subhead = "The KL-11 TTY Structures";
 969:         newpage();
 970:         line = 8;
 971:         for(tp=kl11; tp<&kl11[nkl11]; tp++)  {
 972:             if( line > LINESPERPAGE ) {
 973:                 newpage();
 974:                 line = 8;
 975:             }
 976:             display(tty_buf, tp );
 977:             line += 13;
 978:             if( tp->t_rawq.c_cc > 0 ) {
 979:                 bp = (struct cblock *)(tp->t_rawq.c_cf-1);
 980:                 bp = (struct cblock *)((int)bp & ~CROUND);
 981:                 chase( "RAW", bp);
 982:             }
 983:             if( tp->t_outq.c_cc > 0 ) {
 984:                 bp = (struct cblock *)(tp->t_outq.c_cf-1);
 985:                 bp = (struct cblock *)((int)bp & ~CROUND);
 986:                 chase( "OUT", bp );
 987:             }
 988:             if( tp->t_canq.c_cc > 0 ) {
 989:                 bp = (struct cblock *)(tp->t_canq.c_cf-1);
 990:                 bp = (struct cblock *)((int)bp & ~CROUND);
 991:                 chase( "CAN", bp);
 992:             }
 993:         }
 994: 
 995:         if (ndh11 != 0) {
 996:             subhead = "The DH-11 TTY structures";
 997:             newpage();
 998:             line = 8;
 999:             for(tp=dh11; tp<&dh11[ndh11]; tp++)  {
1000:                 if( line > LINESPERPAGE ) {
1001:                     newpage();
1002:                     line = 8;
1003:                 }
1004:                 display(tty_buf, tp);
1005:                 line += 13;
1006:                 if( tp->t_rawq.c_cc > 0 ) {
1007:                     bp = (struct cblock *)(tp->t_rawq.c_cf-1);
1008:                     bp = (struct cblock *)((int)bp & ~CROUND);
1009:                     chase("RAW", bp);
1010:                 }
1011:                 if( tp->t_outq.c_cc > 0 ) {
1012:                     bp = (struct cblock *)(tp->t_outq.c_cf-1);
1013:                     bp = (struct cblock *)((int)bp & ~CROUND);
1014:                     chase( "OUT", bp);
1015:                 }
1016:                 if( tp->t_canq.c_cc > 0 ) {
1017:                     bp = (struct cblock *)(tp->t_canq.c_cf-1);
1018:                     bp = (struct cblock *)((int)bp & ~CROUND);
1019:                     chase( "CAN", bp);
1020:                 }
1021:             }
1022:         }
1023: 
1024:         if (ndz11 != 0) {
1025:             subhead = "The DZ-11 TTY Structures";
1026:             newpage();
1027:             line = 8;
1028:             for(tp=dz11; tp<&dz11[ndz11]; tp++)  {
1029:                 if( line > LINESPERPAGE ) {
1030:                     newpage();
1031:                     line = 8;
1032:                 }
1033:                 display(tty_buf, tp );
1034:                 line += 13;
1035:                 if( tp->t_rawq.c_cc > 0 ) {
1036:                     bp = (struct cblock *)(tp->t_rawq.c_cf-1);
1037:                     bp = (struct cblock *)((int)bp & ~CROUND);
1038:                     chase( "RAW", bp );
1039:                 }
1040:                 if( tp->t_outq.c_cc > 0 ) {
1041:                     bp = (struct cblock *)(tp->t_outq.c_cf-1);
1042:                     bp = (struct cblock *)((int)bp & ~CROUND);
1043:                     chase( "OUT", bp );
1044:                 }
1045:                 if( tp->t_canq.c_cc > 0 ) {
1046:                     bp = (struct cblock *)(tp->t_canq.c_cf-1);
1047:                     bp = (struct cblock *)((int)bp & ~CROUND);
1048:                     chase( "CAN", &tp->t_canq );
1049:                 }
1050:             }
1051:         }
1052: 
1053:         subhead = "The CBUF Freelist";
1054:         newpage();
1055:         line = 8;
1056:         if( cfreelist != (struct cblock *) NULL )
1057:             chase( "Freelist", cfreelist);
1058:         else
1059:             printf("The freelist was empty\n");
1060:     }
1061: 
1062:     /* display the C-list */
1063:     if( tflg )  {
1064:         struct cblock *cp;
1065: 
1066:         subhead = "The C-list";
1067:         newpage();
1068:         line = 8;
1069:         if (ucbclist)
1070:             j = (unsigned)0120000;
1071:         else
1072:             j = (unsigned)cfreebase;
1073: 
1074:         for(cp=cfree_; cp<&cfree_[nclist]; cp++)  {
1075:             putchar('\n');
1076:             octout( j );
1077:             display( cl_buf, cp);
1078:             j += sizeof(struct cblock);
1079:             line++;
1080:             if (line > LINESPERPAGE) {
1081:                 newpage();
1082:                 line = 8;
1083:             }
1084:         }
1085:     }
1086: 
1087:     /* Display the in-core inode table */
1088:     if( iflg )  {
1089:         struct buf *buf, *bp;   /* NBUF */
1090:         struct inode *inode, *ip;   /* NINODE */
1091: 
1092:         buf = (struct buf *) calloc(nbuf, sizeof(struct buf));
1093:         if (buf == (struct buf *) NULL) {
1094:             printf("crash: out of memory in buf\n");
1095:             exit(1);
1096:         }
1097:         subhead = "The BUF struct";
1098:         newpage();
1099:         line = 8;
1100:         j = find("_buf", 1 );
1101:         if (vf("_buf", (char *) buf, sizeof(struct buf)*nbuf)) {
1102:             for(bp = buf; bp < &buf[nbuf]; bp++)  {
1103:                 if( line > LINESPERPAGE ) {
1104:                     newpage();
1105:                     line = 8;
1106:                 }
1107:                 printf("\n\nBuf stored at 0%o\n", j);
1108:                 display(buf_tab, bp);
1109:                 line += 6;
1110:                 j += sizeof(struct buf);
1111:             }
1112:         }
1113:         free(buf);
1114: 
1115:         inode = (struct inode *) calloc(ninode, sizeof(struct inode));
1116:         if (inode == (struct inode *) NULL) {
1117:             printf("crash: out of memory in inode\n");
1118:             exit(1);
1119:         }
1120:         subhead = "The In-Core Inode Table";
1121:         newpage();
1122:         j = find( "_inode", 1 );
1123:         if (vf("_inode", (char *) inode, sizeof(struct inode)*ninode)) {
1124:             for(ip = inode; ip<&inode[ninode]; ip++ )  {
1125:                 if (ip->i_count == 0)
1126:                     continue;
1127:                 if( line > LINESPERPAGE )
1128:                     newpage();
1129:                 printf("\n\nInode stored at %o\n", j);
1130:                 display(inode_tab, ip);
1131:                 line += 6;
1132:                 j += sizeof inode[0];
1133:             }
1134:         }
1135:         free(inode);
1136:     }
1137: }
1138: 
1139: /*
1140:  *			C H A S E
1141:  *
1142:  * This routine is used to chase down a c-list chain,
1143:  * and display the data found there.
1144:  * Note the external variable, clststrt or cfreebase.
1145:  */
1146: chase( msg, headp )
1147: register struct cblock *headp;
1148: {
1149:     register unsigned int cp;
1150:     memaddr clstp, clstbase, clstend;
1151: 
1152:     if  (ucbclist)
1153:         clstbase = (memaddr)0120000;
1154:     else
1155:         clstbase = (memaddr)cfreebase;
1156: 
1157:     clstend = clstbase + clsize;
1158:     printf("\n----The %s Queue-----\n", msg);
1159:     line += 2;
1160: 
1161:     clstp = (unsigned) headp;
1162:     cp = (unsigned) cfree_ + clstp - clstbase;
1163:     while( clstp != 0 )  {
1164:         putchar('\n');
1165:         line++;
1166:         if (line > LINESPERPAGE) {
1167:             newpage();
1168:             printf("\n----The %s Queue-----\n", msg);
1169:             line = 8;
1170:         }
1171:         octout( clstp );
1172: 
1173:         if( clstp > clstend || clstp < clstbase)
1174:             barf(" cp exceeds limit");
1175:         display( cl_buf, cp );
1176: 
1177:         clstp = (memaddr) ((struct cblock *)cp)->c_next;
1178:         cp = (unsigned) cfree_ + clstp - clstbase;
1179:     }
1180: }
1181: 
1182: 
1183: 
1184: /*
1185:  *			D U S E R
1186:  *
1187:  *
1188:  *	Display the currently loaded User Structure
1189:  */
1190: duser() {
1191: 
1192:     printf("Name: %-15s\n", u.u_comm);
1193:     display( u_tab, 0 );
1194:     printf("\n\nSignal Disposition:");
1195:     col( 0, (unsigned *)u.u_signal, NSIG );
1196:     printf("\n\nOpen file pointers");
1197:     col( 0, (unsigned *)u.u_ofile, NOFILE );
1198: /****
1199: 	printf("\n\nuisa:");
1200: 	col( 0, (unsigned *)u.u_uisa, 16 );
1201: 	printf("\n\nuisd:");
1202: 	col( 0, (unsigned *)u.u_uisd, 16);
1203: ****/
1204: }
1205: 
1206: 
1207: /*
1208:  *			D P R O C S
1209:  *
1210:  *	Display information on each process
1211:  *
1212:  *    For every line entry in the process table,
1213:  * the ptable entry is displayed.  Then the
1214:  * per-process user structure is loaded into
1215:  * this program's incore copy of the user structure.
1216:  * Selected tidbits are displayed by duser().
1217:  *	Mike Muuss, 7/8/77.
1218:  */
1219: 
1220: dprocs() {
1221:     register struct proc *p;
1222:     register unsigned i;
1223:     register unsigned loc;
1224:     long baddr;         /* dump byte addr */
1225: 
1226: 
1227:     proc = (struct proc *) calloc(nproc, sizeof(struct proc));
1228:     if (proc == (struct proc *) NULL) {
1229:         printf("crash: out of memory getting proc\n");
1230:         exit(1);
1231:     }
1232:     vf("_proc", (char *) proc, sizeof(struct proc)*nproc);
1233:     loc = find( "_proc", 1 );   /* base dump addr */
1234:     subhead = "Information on Pid XXXXX";       /* page header */
1235: 
1236:     /* Consider each active entry */
1237:     for( i=0, p=proc; i<nproc; i++, p++, loc += sizeof(struct proc) ) {
1238:         if( p->p_stat == 0 ) continue;
1239: 
1240:         prints( &subhead[19], p->p_pid);
1241:         newpage();
1242: 
1243:         printf("Entry for PID %d at ", p->p_pid);
1244:         octout((unsigned) loc);
1245:         printf("\nStatus was: %s on ",
1246:             (p->p_stat > sizeof pmsg1 ?
1247:                 (char *)sprintf("%d", p->p_stat) :
1248:                  pmsg1[p->p_stat]));
1249:         symbol(p->p_wchan, DSYM, 0);
1250:         printf(" (0%o) wchan.\nFlags set were: ", p->p_wchan);
1251:         putbits( p_bits, p->p_flag&FLAG_MASK ); /* interpret flags */
1252:         putchar('\n');
1253:         display( proc_tab, p );
1254:         putchar('\n');
1255: 
1256:         /* Analyze the swapspace image */
1257:         if( p->p_flag & SLOAD ) {
1258:             baddr = p->p_addr * 64L;
1259:         } else {
1260:             if( !dflg ) {
1261:                 printf("\nImage not avail.\n");
1262:                 continue;
1263:             }
1264:             printf("\n Image retrieved from swapdev.\n");
1265:             baddr = ( p->p_addr ) * 512L;
1266:         }
1267: 
1268:         lseek( kmem, (off_t) baddr, 0 );
1269:         read( kmem, &u, USIZEB );
1270: 
1271:         /* Verify integrity of swap image, and if OK, print */
1272:         if( (unsigned)u.u_procp != loc )  {
1273:             printf("\n----> Image Defective <----\n");
1274:             printf("\nu.u_procp="); octout((unsigned)u.u_procp);
1275:             printf("\tbaddr="); loctout(baddr);
1276:             continue;
1277:         }
1278:         duser();
1279: 
1280:         /* eventually, I plan to print a core dump */
1281:         stackdump( (unsigned)u.u_rsave.val[R5], (unsigned)u.u_rsave.val[R6] );
1282:     }
1283:     free(proc);
1284: }
1285: 
1286: /*
1287:  * print panicstr
1288:  */
1289: panicpr()
1290: {
1291:     char pbuf[20];
1292:     register char ch;
1293:     register int i;
1294: 
1295:     if (panicstr != (char *)0) {
1296:         printf("\n\tpanicstr: \"");
1297:         lseek(kmem,(off_t)(unsigned)panicstr,0);
1298:         read(kmem,pbuf,sizeof pbuf);
1299:         for (i=0; i<sizeof pbuf; i++) {
1300:             if ((ch=pbuf[i]) == 0)
1301:                 break;
1302:             if (ch < 040 || ch > 0177) {
1303:                 switch(ch) {
1304:                 case '\n':
1305:                     printf("\\n");
1306:                     break;
1307:                 case '\r':
1308:                     printf("\\r");
1309:                     break;
1310:                 case '\t':
1311:                     printf("\\t");
1312:                     break;
1313:                 default:
1314:                     printf("\\%3o",ch);
1315:                 }
1316:             } else {
1317:                 putchar(ch);
1318:             }
1319:         }
1320:         putchar('"');
1321:     } else {
1322:         printf("\n\tpanicstr is null");
1323:     }
1324: }
1325: 
1326: /*
1327:  * Print contents of msgbuf
1328:  */
1329: msgbufpr()
1330: {
1331:     register int i;
1332:     register int j;
1333:     register char ch;
1334: 
1335:     printf("\n\nThe contents of msgbuf:");
1336:     for (i=0, j=0; i<MSG_BSIZE; i++) {
1337:         if ((j++)%20 == 0)
1338:             putchar('\n');
1339:         if ((ch=msgbuf.msg_bufc[i]) < 040 || ch > 0177) {
1340:             switch(ch) {
1341:             case '\n':
1342:                 printf("  \\n");
1343:                 break;
1344:             case '\r':
1345:                 printf("  \\r");
1346:                 break;
1347:             case '\t':
1348:                 printf("  \\t");
1349:                 break;
1350:             default:
1351:                 printf("\\%3o",ch);
1352:             }
1353:         } else {
1354:             printf("   %c",ch);
1355:         }
1356:     }
1357: }

Defined functions

chase defined in line 1146; used 10 times
dprocs defined in line 1220; used 1 times
duser defined in line 1190; used 1 times
general defined in line 881; used 1 times
main defined in line 573; never used
msgbufpr defined in line 1329; used 1 times
panicpr defined in line 1289; used 1 times
stackdump defined in line 811; used 2 times

Defined variables

MIS_ARG defined in line 550; used 3 times
aova defined in line 188; used 1 times
aovd defined in line 188; used 1 times
bflg defined in line 556; used 2 times
bfreelist defined in line 104; used 2 times
  • in line 490(2)
bootime defined in line 149; used 3 times
bpaddr defined in line 150; used 3 times
bsize defined in line 154; used 3 times
buf_tab defined in line 329; used 1 times
cal_buf defined in line 212; used 1 times
callout defined in line 106; used 6 times
cbad defined in line 180; never used
cfree_ defined in line 178; used 7 times
cfreebase defined in line 170; used 6 times
cfreelist defined in line 179; used 5 times
cl_buf defined in line 222; used 2 times
clsize defined in line 171; used 4 times
clststrt defined in line 169; used 4 times
corref defined in line 548; used 3 times
cputype defined in line 155; used 3 times
curpri defined in line 163; used 3 times
dflg defined in line 557; used 2 times
dh11 defined in line 126; used 5 times
dumplo defined in line 138; used 2 times
  • in line 508(2)
dz11 defined in line 128; used 6 times
fetch1tab defined in line 533; used 1 times
fetchatab defined in line 542; used 1 times
fetchtab defined in line 483; used 1 times
iflg defined in line 560; used 2 times
inode_tab defined in line 343; used 1 times
itr_buf defined in line 200; used 1 times
itrace defined in line 118; used 7 times
itrend defined in line 121; used 2 times
itrptr defined in line 117; used 3 times
itrstr defined in line 120; used 3 times
kl11 defined in line 130; used 5 times
kmem defined in line 184; used 15 times
lbolt defined in line 158; used 3 times
line defined in line 183; used 27 times
lks defined in line 166; used 1 times
maxmem defined in line 164; used 3 times
mnt_tab defined in line 192; used 1 times
mpid defined in line 159; used 3 times
msgbuf defined in line 135; used 3 times
nbuf defined in line 139; used 6 times
ncallout defined in line 140; used 5 times
nclist defined in line 147; used 5 times
ndh11 defined in line 125; used 6 times
ndz11 defined in line 127; used 5 times
nfile defined in line 141; used 3 times
ninode defined in line 142; used 6 times
nkl11 defined in line 129; used 5 times
nmount defined in line 146; used 5 times
nproc defined in line 143; used 6 times
nswap defined in line 145; used 3 times
ntext defined in line 144; used 3 times
ov_tab defined in line 288; used 1 times
ova defined in line 189; used 19 times
ovd defined in line 189; used 19 times
ovend defined in line 187; never used
overlay defined in line 186; used 8 times
ovno defined in line 187; used 3 times
p_bits defined in line 459; used 1 times
panicstr defined in line 136; used 4 times
physmem defined in line 165; used 3 times
pipedev defined in line 153; used 3 times
pmsg1 defined in line 447; used 2 times
proc defined in line 105; used 5 times
proc_tab defined in line 416; used 1 times
rablock defined in line 168; used 3 times
rootdev defined in line 151; used 3 times
rootdir defined in line 156; used 3 times
runin defined in line 160; used 3 times
runout defined in line 161; used 3 times
runq defined in line 157; never used
runrun defined in line 162; used 3 times
rv_tab defined in line 255; used 1 times
saveps defined in line 137; used 6 times
stime defined in line 148; used 3 times
subhead defined in line 182; used 14 times
swapdev defined in line 152; used 3 times
symref defined in line 549; used 2 times
tflg defined in line 559; used 5 times
trflg defined in line 562; used 2 times
tty_buf defined in line 231; used 3 times
u defined in line 91; used 45 times
u_tab defined in line 379; used 1 times
u_wasteXX defined in line 92; never used
ucbclist defined in line 172; used 5 times
updlock defined in line 167; used 3 times
vflg defined in line 558; used 1 times

Defined macros

FLAG_MASK defined in line 476; used 1 times
R1 defined in line 377; never used
R2 defined in line 372; never used
R3 defined in line 373; never used
R4 defined in line 374; never used
R5 defined in line 375; used 3 times
R6 defined in line 376; used 3 times
USIZEB defined in line 85; used 8 times
Last modified: 1997-11-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 40
Valid CSS Valid XHTML 1.0 Strict