/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ static char Sccsid[] = "@(#)cda.c 3.1 7/21/87"; /* * ULTRIX-11 crash dump analysis program (cda). * Fred Canter 10/10/83 * Bill Burns 6/84 * added: * core and swap map prinout (-r (resource map)) * buffer queue option (-q) * added mscp disk info dump (-u) * added getu option * * Chung-Wu Lee 2/11/85 * added: * added tmscp magtape info dump (-k) * * Fred Canter -- 8/17/85 * * Make CDA understand the ublock doubled in size. * Fix up CDA's concept of the stack frame, which * was really bent by the 431 and 451 kernels. * Expand CPU error register bits with ascii text. * * Usage: cda -he?????? [namelist] [corefile] * * namelist File name containing the namelist, * default is `/unix'. * * corefile Filename of the core dump file, * default is `/usr/crash/core'. * If the corefile is given then namelist * must also be given. * * -h Print the help message. * * -e Locate, format, and print any unlogged errors * (from the kernel error log buffer in memory). * Also print last error logged by each block I/O device. * * -t Format and print the panic trap stack frame. * * -m Print the memory usage map (memstat) * * -b Print I/O buffer pool usage (bufstat) * * -r Print the resourse maps (core and swap) * * -q Print the block I/O buffer queues * * -u Print the MSCP disk data structures * * -k Print the TMSCP magtape data structures * * -g[#] Use getu to print user blocks * * -ps Get process status from core dump (ps -alx) * * -pp pstat -p * -ppa pstat -pa * -pi pstat -i * -pf pstat -f * -px pstat -x * -pu# pstat -u addr * -pt pstat -t * -ppaifxtu# all of the above */ #include <sys/param.h> /* Don't matter which one */ #include <sys/tmscp.h> /* must preceed errlog.h (EL_MAXSZ) */ #include <sys/errlog.h> #include <sys/hp_info.h> #include <stdio.h> #include <a.out.h> #include <sys/map.h> #include "cda.h" #include <time.h> #define MBSMAX 1024 /* MAX size of saved error message buffer */ struct nlist nl[] = { { "_el_buf" }, /* 0 */ { "_elbsiz" }, /* 1 */ { "_el_bpi" }, /* 2 */ { "_el_bpo" }, /* 3 */ { "_cputype" }, /* 4 */ { "__ovno" }, /* 5 */ { "svi0" }, /* no longer used */ /* 6 */ { "_rn_ssr3" }, /* 7 */ { "_cpereg" }, /* 8 */ { "_mmr3" }, /* 9 */ { "ssr" }, /* 10 */ { "ova" }, /* 11 */ { "_msgbuf" }, /* 12 */ { "_msgbufs" }, /* 13 */ { "_mapsize" }, /* 14 */ { "_coremap" }, /* 15 */ { "_swapmap" }, /* 16 */ { "_msgbufp" }, /* 17 */ { "_nuda" }, /* 18 */ { "_uda_sof" }, /* 19 */ { "_uda" }, /* 20 */ { "_nra" }, /* 21 */ { "_ra_drv" }, /* 22 */ { "_ra_ctid" }, /* 23 */ { "_time" }, /* 24 */ { "_cfree" }, /* 25 */ { "_sepid" }, /* 26 */ { "_ubmaps" }, /* 27 */ { "_ntk" }, /* 28 */ { "_tk_soft" }, /* 29 */ { "_tk" }, /* 30 */ { "_tk_drv" }, /* 31 */ { "_tk_ctid" }, /* 32 */ { "_ra_rs" }, /* 33 */ { "_ra_rp" }, /* 34 */ { "_ra_cp" }, /* 35 */ { "_tk_csr" }, /* 36 */ { "_nhp" }, /* 37 */ { "_nts" }, /* 38 */ { "_ub_map" }, /* 39 */ { "" }, /* */ }; extern int nuda; extern int ntk; int nts; char nhp[MAXRH]; int nrh; struct exec exe; /* place for exec struct from a.out */ struct nlist dnl[] = { { "_hk_ebuf" }, { "_hp_ebuf" }, { "_ht_ebuf" }, { "_ra_ebuf" }, { "_rk_ebuf" }, { "_rl_ebuf" }, { "_rp_ebuf" }, { "_hx_ebuf" }, { "_tm_ebuf" }, { "_ts_ebuf" }, { "_tk_ebuf" }, { "" }, }; /* * flags word is used to indicate what * functions have already been called. * * bit meaning * * 0 cdhead called * 1 rainfo called * 2 bioinfo called */ int flags; #define CD_SAVE 040 /* crash info saved at 040 on panic trap */ /* if 040 < 0140000 or > 0144000, no info saved */ /* 040 = aps (virtual address of PS on stack) */ /* 042 = ka6 (physical address of U block) */ /* 044 = current kernel stack pointer */ /* 046 = first kernel I space PAR */ int ssr[4]; /* saved M/M status registers */ /* ssr0, ssr1, ssr2, ssr3 */ int cputype; int rn_ssr3; /* bits 0->5, saved M/M SSR3 (NOT USED) */ /* bits 6->15, kernel version number (see machdep.c) */ int cpereg; /* -1 if no CPU error register, otherwise contents */ int mmr3; /* 0 if no M/M status reg 3, otherwise its address */ int ksp; /* current kernel stack pointer */ int kisa0; /* first kernel I space PAR */ int ovno; /* -1 if NOT overlay kernal */ int sepid; /* type of processor */ int magic; /* type of kernel 0 == 430; 1 == 431/451 */ unsigned ova[8]; /* text overlay address table */ unsigned ka6; /* physical address of base of current U block */ unsigned aps; /* virtual address of top of stack frame. */ int svi0; /* address of svi0 */ int elbsiz; /* size of error log buffer */ char *el_bpi; /* buffer input pointer */ char *el_bpo; /* buffer output pointer */ char *ebuf; /* local copy of error log buffer */ char obuf[513] = E_EOB; /* end of block followed by zeroes */ int msgbufs; /* size of kernel saved error messages buffer */ int msgbufp; /* pointer in msgbuf area */ int mapsize; /* size of core and swap maps */ int ubmaps; /* if unibus map present or not */ struct map coremap[300]; /* room for core map */ struct map swapmap[300]; /* room for swap map */ #define UBMAPSZ 12 /* no. of map entries, constant 12 in ubmap.c */ struct map ub_map[UBMAPSZ]; /* room for unibus map */ time_t time; /* system time - used by red zone printout */ /* * Buffer to hold one block I/O device error. * Assumes that TMSCP (tk50/tu81) is the largest error! * EL_MAXSZ defined in /usr/include/sys/errlog.h */ union { struct { struct elrhdr d_hdr; /* error record header */ struct el_bdh d_bdh; /* block device header */ int d_reg[sizeof(struct tmslg)/2]; /* device info */ } d_ebuf; char d_max[EL_MAXSZ]; } d_un; char msgbuf[MBSMAX+1]; /* console message buffer */ char *corfil = "/usr/crash/core"; char *nlfil = "/unix"; char tmpfil[40]; char syscmd[100]; char *help[] = { "\n(cda) - ULTRIX-11 crash dump analysis program", "\nUsage:\tcda -key [namelist] [corefile]", "\n\tnamelist\tFile containing namelist, default is /unix.", "\n\tcorefile\tCrash dump file, default is /usr/crash/core.", "\t\t\tIf given then namelist must also be given.", "\n\t-key\t\tThe operation(s) to be performed:", "\t\t\tMultiple keys may be given.", "\n\t\th\tPrint the help message.", "\n\t\te\tLocate, format, & print any unlogged errors.", "\n\t\tm\tPrint the memory usage map.", "\n\t\tb\tPrint the I/O buffer pool usage.", "\n\t\tt\tFormat & print the panic trap error stack frame.", "\n\t\tr\tPrint the resource maps (core and swap).", "\n\t\tq\tPrint the block I/O buffer queues.", "\n\t\tu[#]\tPrint MSCP disk information (# = controller).", "\n\t\tk\tPrint TMSCP magtape information.", "\n\t\tg\tPrint user blocks.", "\n\t\tps\tGet process status from crash dump (ps -alx).", "\n\t\tpp\tDump the process table, only active slots.", "\n\t\tppa\tDump process table, all slots.", "\n\t\tpi\tDump the incore inode table.", "\n\t\tpf\tDump the incore open file table.", "\n\t\tpx\tDump the incore text table.", "\n\t\tpt\tPrint the status of all terminal lines.", "\n\t\tpu#\tDump the U block for the process at address #.", "\nExample:\tcda -et /unix.crash /usr/crash/core.crash", "\n\t\tPrint unlogged errors and panic trap stack frame.", "\n\n", 0 }; char *trapmsg[] = { "4 - Bus error", "10 - Reserved instruction", "14 - Break point trace", "20 - Input/Output trap", "24 - Power fail", "30 - Emulator trap", "34 - Trap instruction (system call from kernel mode)", "240 - Programmed interrupt request", "244 - Floating point exception", "250 - Memory management violation", }; int mem; main(argc, argv) char *argv[]; int argc; { register char *p, *n; register int i; int f; int ctlr; if((argc > 4) || (argc == 1)) { phelp(); exit(0); } if(argv[1] [0] != '-') { printf("\ncda: missing key\n"); phelp(); exit(1); } if(argv[1] [1] == 'h') { phelp(); exit(0); } if(argc == 4) corfil = argv[3]; if(argc >= 3) nlfil = argv[2]; /* find out magic number */ f = open(nlfil, 0); if(f < 0) return(-1); read(f, (char *)&exe, sizeof exe); if((exe.a_magic == 0431) || (exe.a_magic == 0451)) magic = 1; close(f); nlist(nlfil, nl); if(nl[0].n_type == 0) { printf("\ncda: Can't access namelist in %s\n", nlfil); exit(1); } if((mem = open(corfil, 0)) < 0) { printf("\ncda: Can't open corefile %s\n", corfil); exit(1); } nlist(nlfil, dnl); lseek(mem, (long)nl[4].n_value, 0); read(mem, (char *)&cputype, sizeof(cputype)); lseek(mem, (long)nl[5].n_value, 0); read(mem, (char *)&ovno, sizeof(ovno)); if(ovno >= 0) { /* overlay kernel, get overlay addresss table */ lseek(mem, (long)nl[11].n_value, 0); read(mem, (char *)&ova[0], sizeof(ova)); } if(nl[37].n_value) { lseek(mem, (long)nl[37].n_value, 0); read(mem, (char *)&nhp, sizeof(nhp)); for(nrh=0; nhp[nrh]; nrh++); } if(nl[38].n_value) { lseek(mem, (long)nl[38].n_value, 0); read(mem, (char *)&nts, sizeof(nts)); } if(nl[28].n_value) { lseek(mem, (long)nl[28].n_value, 0); read(mem, (char *)&ntk, sizeof(ntk)); } if(nl[18].n_value) { lseek(mem, (long)nl[18].n_value, 0); read(mem, (char *)&nuda, sizeof(nuda)); } lseek(mem, (long)nl[26].n_value, 0); read(mem, (char *)&sepid, sizeof(sepid)); lseek(mem, (long)nl[7].n_value, 0); read(mem, (char *)&rn_ssr3, sizeof(rn_ssr3)); lseek(mem, (long)nl[8].n_value, 0); read(mem, (char *)&cpereg, sizeof(cpereg)); lseek(mem, (long)nl[9].n_value, 0); read(mem, (char *)&mmr3, sizeof(mmr3)); lseek(mem, (long)nl[10].n_value, 0); read(mem, (char *)&ssr[0], sizeof(ssr)); lseek(mem, (long)nl[14].n_value, 0); read(mem, (char *)&mapsize, sizeof(mapsize)); lseek(mem, (long)nl[15].n_value, 0); read(mem, (char *)&coremap, mapsize); lseek(mem, (long)nl[16].n_value, 0); read(mem, (char *)&swapmap, mapsize); lseek(mem, (long)nl[17].n_value, 0); read(mem, (char *)&msgbufp, sizeof(msgbufp)); lseek(mem, (long)nl[27].n_value, 0); read(mem, (char *)&ubmaps, sizeof(ubmaps)); if(ubmaps) { lseek(mem, (long)nl[39].n_value, 0); read(mem, (char *)&ub_map, UBMAPSZ); } lseek(mem, (long)CD_SAVE, 0); read(mem, (char *)&aps, sizeof(aps)); read(mem, (char *)&ka6, sizeof(ka6)); read(mem, (char *)&ksp, sizeof(ksp)); read(mem, (char *)&kisa0, sizeof(kisa0)); p = &msgbuf[0]; for(i=0; i<(MBSMAX+1); i++) *p++ = 0; lseek(mem, (long)nl[13].n_value, 0); read(mem, (char *)&msgbufs, sizeof(msgbufs)); if(msgbufs > MBSMAX) i = MBSMAX; else i = msgbufs; lseek(mem, (long)nl[12].n_value, 0); read(mem, (char *)&msgbuf, i); p = argv[1]; for( ;;) { switch(*p++) { case 0: exit(0); case '-': break; case 'm': /* memory usage map (memstat) */ if(!(flags & CDHEAD)) cdhead(); printf("\n****** Map of memory usage ******\n"); fflush(stdout); sprintf(&syscmd, "memstat -fn %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 'r': /* core and swap map */ if(!(flags & CDHEAD)) cdhead(); printf("\n****** Resource map contents ******\n\n"); fflush(stdout); rcmd(); fflush(stdout); break; case 'u': /* mscp disk info */ if(!(flags & CDHEAD)) cdhead(); ctlr = 0; if((*p >= '0') && (*p <= '9')) { ctlr = atoi(p++); ctlr++; } printf("\n****** Mscp disk information ******"); fflush(stdout); ucmd(ctlr); fflush(stdout); break; case 'k': /* tmscp magtape info */ if(!(flags & CDHEAD)) cdhead(); ctlr = 0; if((*p >= '0') && (*p <= '9')) { ctlr = atoi(p++); ctlr++; } printf("\n****** Tmscp magtape information ******"); fflush(stdout); kcmd(ctlr); fflush(stdout); break; case 'q': /* buffer queues */ if(!(flags & CDHEAD)) cdhead(); qcmd(); fflush(stdout); break; case 'g': /* getu */ if(!(flags & CDHEAD)) cdhead(); if((*p >= '0') && (*p <= '7')) { n = &tmpfil; while(*p >= '0' && *p <= '7') *n++ = *p++; *n++ = '\0'; sprintf(&syscmd, "/usr/crash/getu -%s %s %s", tmpfil, nlfil, corfil); } else sprintf(&syscmd, "/usr/crash/getu %s %s", nlfil, corfil); printf("\n****** Ublock information ******\n\n"); fflush(stdout); system(&syscmd); fflush(stdout); break; case 'b': /* I/O buffer pool usage (bufstat) */ if(!(flags & CDHEAD)) cdhead(); printf("\n****** I/O buffer pool usage ******\n"); fflush(stdout); sprintf(&syscmd, "bufstat -fn %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 'e': /* unlogged errors */ if(!(flags & CDHEAD)) cdhead(); printf("\n****** Analysis of unlogged errors ******\n"); fflush(stdout); ecmd(); fflush(stdout); break; case 't': /* panic trap stack frame */ if(!(flags & CDHEAD)) cdhead(); if(rzchk() == 0) { printf("\n****** Dump of panic trap error stack frame ******\n"); tcmd(); } fflush(stdout); break; case 'p': /* ps -alx or pstat */ if(!(flags & CDHEAD)) cdhead(); if(*p == 's') { p++; printf("\n****** Status of active processes ******\n"); printf("\nCAUTION !, if the process is swapped (F = 0) or being swapped (F = 11)"); printf("\n , then TTY, TIME and CMD could be erroneous !\n"); fflush(stdout); sprintf(&syscmd, "ps -alx %s %s",nlfil, corfil); system(&syscmd); } loop: if(*p == 0) break; switch(*p++) { case 'p': if(*p == 'a') { printf("\n****** Dump of all process table slots ******\n"); p++; fflush(stdout); sprintf(&syscmd, "pstat -pa %s %s", corfil, nlfil); system(&syscmd); } else { printf("\n****** Dump of only active process table slots ******\n"); fflush(stdout); sprintf(&syscmd, "pstat -p %s %s", corfil, nlfil); system(&syscmd); } fflush(stdout); break; case 'i': printf("\n****** Dump of the incore inode table ******\n"); fflush(stdout); sprintf(&syscmd, "pstat -i %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 'f': printf("\n****** Dump of the incore open file table ******\n"); fflush(stdout); sprintf(&syscmd, "pstat -f %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 'x': printf("\n****** Dump of the incore text table ******\n"); fflush(stdout); sprintf(&syscmd, "pstat -x %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 't': printf("\n****** Status of all terminal lines ******\n"); fflush(stdout); sprintf(&syscmd, "pstat -t %s %s", corfil, nlfil); system(&syscmd); fflush(stdout); break; case 'u': n = &tmpfil; while(*p >= '0' && *p <= '7') *n++ = *p++; *n++ = '\0'; printf("\n****** Dump of U block for process at address %s ******\n", tmpfil); fflush(stdout); sprintf(&syscmd, "pstat -u %s %s %s ", tmpfil, corfil, nlfil); system(&syscmd); fflush(stdout); break; default: printf("\ncda: bad -p option\n"); break; } goto loop; break; default: printf("\ncda: Unknown key\n"); exit(1); } } } phelp() { register int i; for(i=0; help[i]; i++) printf("\n%s", help[i]); } ecmd() { register char *ip, *op; register char siz; char *lim; int fd; int found; int i, j, k; lseek(mem, (long)nl[1].n_value, 0); read(mem, (char *)&elbsiz, sizeof(elbsiz)); lseek(mem, (long)nl[2].n_value, 0); read(mem, (char *)&el_bpi, sizeof(el_bpi)); lseek(mem, (long)nl[3].n_value, 0); read(mem, (char *)&el_bpo, sizeof(el_bpo)); printf("\nError log buffer at\t%06.o", nl[0].n_value); printf("\nBuffer size in words =\t%06.d",elbsiz); printf("\nBuffer input pointer =\t%06.o", el_bpi); printf("\nBuffer output pointer =\t%06.o\n",el_bpo); ebuf = calloc((elbsiz+1), sizeof(int)); if(ebuf == NULL) { printf("\ncda: Can't get more memory for buffer\n"); exit(1); } lseek(mem, (long)nl[0].n_value, 0); read(mem, (char *)ebuf, (elbsiz*2)); sprintf(&tmpfil, "/tmp/cda_el.%d", getpid()); if((fd = creat(&tmpfil, 0644)) < 0) { printf("\ncda: Can't create %s\n", &tmpfil); exit(1); } if(el_bpi == el_bpo) { printf("\n****** No unlogged errors in kernel buffer ******\n"); close(fd); goto e_last; } ip = ebuf + (el_bpi - nl[0].n_value); op = ebuf + (el_bpo - nl[0].n_value); lim = ebuf + (elbsiz*2); e_loop: if(ip == op) goto e_done; if(op >= lim) { op = ebuf; goto e_loop; } if(*op == 0) { op = ebuf; goto e_loop; } if(*op < 0 || *op > E_BD) { /* bad record type */ printf("\ncda: bad error log record - type\n"); goto badrec; } siz = *(op + 1); if((siz <= 0) || (siz & 1) || (siz > EL_MAXSZ)) { /* bad size */ printf("\ncda: bad error log record - size\n"); badrec: printf("\n error report terminated\n"); goto e_done; } if(write(fd, (char *)op, siz) != siz) { wrterr: printf("\ncda: write error\n"); exit(1); } if(write(fd, (char *)obuf, (512 - siz)) != (512 - siz)) goto wrterr; op += siz; goto e_loop; e_done: if(write(fd, (char *)&obuf+1, 512) != 512) goto wrterr; close(fd); fflush(stdout); sprintf(&syscmd, "elp %s", &tmpfil); system(&syscmd); /* * Print the last error on each block I/O device. * The error is located in the device's error buffer. * This is done because, * when a `panic' occurs, errors that have been * passed from the kernel error log buffer to * the error log copy process (elc) can be lost if the * panic crashes unix before elc can write the error to * the disk error log file. */ e_last: siz = 0; for(i=0; (dnl[i].n_name[0] != 0); i++) siz += dnl[i].n_value; if(siz == 0) { printf("\n****** Can't locate device error buffers ******\n"); goto e_xit; } if((fd = open(&tmpfil, 2)) < 0) { printf("\ncda: Can't open %s\n", &tmpfil); exit(1); } found = 0; for(i=0; (dnl[i].n_name[0] != 0); i++) { if(dnl[i].n_value == 0) continue; /* device not configured */ j = 1; if(nrh && (strncmp(dnl[i].n_name, "_hp_ebuf", 8) == 0)) j = nrh; if(nuda && (strncmp(dnl[i].n_name, "_ra_ebuf", 8) == 0)) j = nuda; if(nts && (strncmp(dnl[i].n_name, "_ts_ebuf", 8) == 0)) j = nts; if(ntk && (strncmp(dnl[i].n_name, "_tk_ebuf", 8) == 0)) j = ntk; lseek(mem, (long)dnl[i].n_value, 0); /* find dev error buf */ for(k=0; k<j; k++) { read(mem, (char *)&d_un.d_ebuf, EL_MAXSZ); /* get contents */ if(d_un.d_ebuf.d_hdr.e_time == 0) continue; /* no error in buffer */ found++; d_un.d_ebuf.d_hdr.e_type = E_BD; siz = sizeof(struct elrhdr) + sizeof(struct el_bdh) + (d_un.d_ebuf.d_bdh.bd_nreg * 2); d_un.d_ebuf.d_hdr.e_size = siz; /* actual record size */ if(write(fd, (char *)&d_un.d_ebuf, siz) != siz) goto wrterr; if(write(fd, (char *)&obuf, (512 - siz)) != (512 - siz)) goto wrterr; } } if(write(fd, (char*)&obuf+1, 512) != 512) goto wrterr; close(fd); printf("\n****** Last error on each Block I/O device ******\n"); if(found == 0) { printf("\n\n****** No errors found ******\n"); goto e_xit; } sprintf(&syscmd, "elp %s", &tmpfil); fflush(stdout); system(&syscmd); e_xit: unlink(&tmpfil); } /* * Fred Canter -- 8/17/85 * * Stack frame for all type kernels currently used * by ULTRIX-11 (430, 431, 450, 451), 411 is dead. * * Offset sf[#] Contents * ------------ -------- * 13 PS * 12 PC * 11 R0 * 10 NPS * 9 OV (at error time) * 8 R1 * 7 SP (previous space) * 6 DEV * 5 TPC * 4 R5 * 3 OV (current) * 2 R4 * 1 R3 * 0 R2 */ int sf[14]; /* copy of panic trap error stack frame, reverse order */ int pco[] = {-6, -4, -2, 0, 2, 4}; int pcdata[6]; tcmd() { register int i; long sfa; int sfs; char ov; int dev; unsigned vpc; long ppc; if((aps < 0140000) || (aps > 0144000)) { printf("\nNO panic trap error status saved !"); printf("\nAre you sure the error was a panic trap ?\n"); return; } sfa = ka6; sfa = sfa << 6; sfa += (aps - 0140000); if(ovno < 0) { /* sep I&D kernel - w/o overlays */ ov = 1; /* was 0 */ /*sfa -= 026; */ sfs = 26; /* was 24 */ } else { ov = 1; /*sfa -= 030; */ sfs = 28; } sfa -= 032; lseek(mem, (long)sfa, 0); read(mem, (char *)&sf[0], sfs); printf("\nGeneral Registers at error time:"); printf("\n\tR0\t%06.o", ov ? sf[11] : sf[9]); printf("\n\tR1\t%06.o", ov ? sf[8] : sf[7]); printf("\n\tR2\t%06.o", sf[0]); printf("\n\tR3\t%06.o", sf[1]); printf("\n\tR4\t%06.o", sf[2]); printf("\n\tR5\t%06.o", ov ? sf[4] : sf[3]); printf("\n\tSP\t%06.o", ov ? sf[7] : sf[6]); printf("\t(from previous space)"); printf("\n\tSP\t%06.o\t(after panic trap)", ksp); printf("\n\nMemory Management Status Registers:"); printf("\n\tMMR0\t%06.o", ssr[0]); if(sepid) /* only separate I & D CPUs have MMR1 */ printf("\n\tMMR1\t%06.o", ssr[1]); printf("\n\tMMR2\t%06.o", ssr[2]); if(mmr3 == 0172516) printf("\n\tMMR3\t%06.o", ssr[3]); if(cpereg != -1) { printf("\n\nCPU Error Register = %06.o", cpereg); if(cpereg&0200) printf("\n\tIllegal halt"); if(cpereg&0100) printf("\n\tAddress error"); if(cpereg&040) printf("\n\tNon-existent memory"); if(cpereg&020) printf("\n\tI/O bus time-out"); if(cpereg&010) printf("\n\tYellow zone stack limit"); if(cpereg&04) printf("\n\tRed zone stack limit"); } printf("\n\nka6 = %o aps = %o", ka6, aps); vpc = ov ? sf[12] : sf[10]; printf("\nUpdated program counter\t= %06.o", vpc); printf("\nProcessor status word\t= %06.o", ov ? sf[13] : sf[11]); if(ovno != -1) { printf("\nCurrent kernel overlay\t= %d", sf[3]); printf("\nOverlay at error time\t= %d", sf[9]); } dev = ov ? sf[6] : sf[5]; if(dev & 020) goto nopc; /* can't do user pc */ /* * sepid kernel now also overlaid using last i page * -- Bill Burns 8/15/84 */ if(magic) { /* 431/451 kernel */ if(vpc < 0160000) ppc = kisa0 + (((vpc >> 13) & 07) * 0200); else ppc = ova[sf[9]]; } else if(vpc < 040000) { /* 430 kernel */ ppc = vpc; /* in root text segment */ goto tcmd1; } else ppc = ova[sf[9]]; /* was sf[3] */ /****************************** old stuff for non overlaid sepid * if(ovno < 0) * ppc = kisa0 + (((vpc >> 13) & 07) * 0200); * else if(vpc < 040000) { * ppc = vpc; * goto tcmd1; * } else * ppc = ova[sf[9]]; *********************************************************************/ ppc = ppc << 6; ppc += (vpc & 017777); tcmd1: lseek(mem, (long)ppc+pco[0], 0); read(mem, (char *)&pcdata[0], sizeof(pcdata)); printf("\n\nPC\tPhysical"); printf("\noffset\taddress Contents"); for(i=0; i<6; i++) { printf("\n"); if(pco[i] > 0) printf("+"); printf("%d",pco[i]); printf("\t%06.O",(ppc+pco[i])); printf(" %06.o", pcdata[i]); } nopc: printf("\n\nCPU was in "); if(dev & 020) printf("USER"); else printf("KERNEL"); printf(" mode at the time of the trap"); printf("\nThe error type was ("); if((dev & 017) > 9) printf("UNKNOWN)\n"); else printf("trap thru location %s)", trapmsg[dev&017]); if(((dev & 017) == 2) && (vpc == 2)) { /* jump -> 0 */ printf("\n(trap type = 2, pc = 2 - most likely"); printf(" a jump to location zero !)"); } if(((dev & 017) == 0) && (!magic) && (vpc == 5)) { /* vector -> 0 */ printf("\n(trap type = 0, pc = 5 - most likely"); printf(" a vector through location zero !)"); } printf("\n"); } /* * Prints crash dump heading message */ cdhead() { register char rn, rnd; register int i; char rnv; int diff; flags |= CDHEAD; rn = ((rn_ssr3 >> 12) & 017) + '0'; rnd = ((rn_ssr3 >> 8) & 017) + '0'; if(rn_ssr3 & 0100) rnv = 'X'; else if(rn_ssr3 & 0200) rnv = 'Y'; else rnv = 'V'; printf("\n\nCrash Dump Analysis of ULTRIX-11 "); printf("%c%c.%c Kernel\n", rnv, rn, rnd); if(magic == 1) printf("Split I/D space overlay version"); else printf("Non-split I/D space overlay version"); printf(" on 11/%d CPU\n", cputype); if(msgbufs > MBSMAX) i = MBSMAX; else i = msgbufs; printf("\n****** Last %d characters of console messages ******", i); if(msgbufs > MBSMAX) { printf("\n(kernel message buffer size exceeds %d bytes, ", MBSMAX); printf("last %d bytes lost !)\n", (msgbufs - MBSMAX)); } else printf("\n"); /* print out mesg buf in order - Bill 6/84 */ diff = (msgbufp - nl[12].n_value); printf("\n%s", (msgbuf + diff)); *(msgbuf + diff) = '\0'; printf("%s\n", msgbuf); } /* * Check for red zone stack violation. * Saved stack pointer equal to zero indicates red zone. * Print CPU error register if it exists. */ rzchk() { int pc, ps; if(ksp) return(0); lseek(mem, 0L, 0); read(mem, (char *)&pc, sizeof(int)); read(mem, (char *)&ps, sizeof (int)); lseek(mem, (long)nl[24].n_value, 0); read(mem, (char *)&time, sizeof(time)); printf("\n\n****** RED ZONE STACK VIOLATION ******\n"); printf("\nUpdated Program Counter\t= %06.o", pc); printf("\nProcessor Status Word\t= %06.o", ps); if(cpereg >= 0) printf("\nCPU Error Register\t= %06.o", cpereg); printf("\nError date and time\t= %s", ctime(&time)); printf("\n\n"); return(1); } /* * print core and swap maps */ rcmd() { int i, j, k, x, y, xall, yall; struct map *cmp, *smp, *ump; j = k = x = y = xall = yall = 0; for(i = 0; i < mapsize; i++) { /* size the maps */ if(x) { if(coremap[i].m_size || coremap[i].m_addr) xall++; } else if(coremap[i].m_size) { j++; } else { x++; } if(y) { if(swapmap[i].m_size || swapmap[i].m_addr) yall++; } else if(swapmap[i].m_size) { k++; } else { y++; } } printf("Mapsize = %d\n\n", mapsize); printf("%16s%15s%16s%15s\n\n", "Core Map", "", "Swap Map", ""); printf("%10s%11s%10s%10s%11s\n", "Size", "Address", "", "Size", "Address"); if(xall || yall) for(i = 0; i < mapsize; i++) { cmp = &coremap[i]; smp = &swapmap[i]; printf("%10u%5s%06o", cmp->m_size, "", cmp->m_addr); printf("%10s", ""); printf("%10u%5s%06o\n", smp->m_size, "", smp->m_addr); } else for(i = 0; i < mapsize ; i++, j--, k--) { cmp = &coremap[i]; smp = &swapmap[i]; if(j >= 0) printf("%10u%5s%06o", cmp->m_size, "", cmp->m_addr); else if (j == -1) printf("%3d %17s", (mapsize - i), "more zero entries"); else printf("%21s", ""); printf("%10s", ""); if(k >= 0) printf("%10u%5s%06o\n", smp->m_size, "", smp->m_addr); else if (k == -1) printf("%3d %17s\n", (mapsize - i), "more zero entries"); else printf("%21s\n", ""); if((j < -1) && (k < -1)) break; } if(!ubmaps) return; j = x = xall = 0; for(i = 0; i < UBMAPSZ; i++) { /* size the maps */ if(x) { if(ub_map[i].m_size || ub_map[i].m_addr) xall++; } else if(ub_map[i].m_size) { j++; } else { x++; } } printf("%16s\n\n", "Unibus Map"); printf("%10s%11s\n", "Size", "Address"); if(xall ) for(i = 0; i < UBMAPSZ; i++) { ump = &ub_map[i]; printf("%10u%5s%06o\n", ump->m_size, "", ump->m_addr); } else for(i = 0; i < UBMAPSZ ; i++, j--) { ump = &ub_map[i]; if(j >= 0) printf("%10u%5s%06o\n", ump->m_size, "", ump->m_addr); else if (j == -1) printf("%3d %17s\n", (UBMAPSZ - i), "more zero entries"); if((j < -1) && (k < -1)) break; } }