1*36565Sbostic #ifndef lint 2*36565Sbostic static char sccsid[] = "@(#)kstack.c 5.1 (Berkeley) 01/16/89"; 3*36565Sbostic #endif 4*36565Sbostic 5*36565Sbostic /* 6*36565Sbostic * adb - routines to probe the kernel stack when debugging post-mortem 7*36565Sbostic * crash dumps. 8*36565Sbostic */ 9*36565Sbostic 10*36565Sbostic #include "defs.h" 11*36565Sbostic #include <ctype.h> 12*36565Sbostic #include <machine/pte.h> 13*36565Sbostic #include <machine/frame.h> 14*36565Sbostic #include <machine/rpb.h> 15*36565Sbostic 16*36565Sbostic struct pte *sbr; 17*36565Sbostic int slr; 18*36565Sbostic struct pcb pcb; 19*36565Sbostic 20*36565Sbostic static caddr_t rpb; 21*36565Sbostic static caddr_t scb; 22*36565Sbostic static caddr_t intstack, eintstack; 23*36565Sbostic static caddr_t ustack, eustack; 24*36565Sbostic 25*36565Sbostic char *malloc(); 26*36565Sbostic 27*36565Sbostic /* 28*36565Sbostic * Convert a kernel virtual address to an (off_t) physical offset. 29*36565Sbostic */ 30*36565Sbostic #define kvtooff(a) ((off_t)(a) & ~KERNBASE) 31*36565Sbostic 32*36565Sbostic /* 33*36565Sbostic * Check if an address is in one of the kernel's stacks: 34*36565Sbostic * interrupt stack, rpb stack (during restart sequence), 35*36565Sbostic * or u. stack. 36*36565Sbostic */ 37*36565Sbostic #define within(a, b, e) \ 38*36565Sbostic ((addr_t)(a) >= (addr_t)(b) && (addr_t)(a) < (addr_t)(e)) 39*36565Sbostic #define kstackaddr(a) \ 40*36565Sbostic (within(a, intstack, eintstack) || \ 41*36565Sbostic within(a, rpb + sizeof(struct rpb), scb) || \ 42*36565Sbostic within(a, ustack, eustack)) 43*36565Sbostic 44*36565Sbostic /* 45*36565Sbostic * Determine whether we are looking at a kernel core dump, and if so, 46*36565Sbostic * set sbr and slr and the current pcb. 47*36565Sbostic */ 48*36565Sbostic getkcore() { 49*36565Sbostic struct nlist *sm, *ss, *mp; 50*36565Sbostic 51*36565Sbostic if ((sm = lookup("_Sysmap")) == NULL || 52*36565Sbostic (ss = lookup("_Syssize")) == NULL || 53*36565Sbostic (mp = lookup("_masterpaddr")) == NULL) 54*36565Sbostic return (0); /* a.out is not a vmunix */ 55*36565Sbostic datmap.m1.b = 0; 56*36565Sbostic datmap.m1.e = -1L; 57*36565Sbostic /* must set sbr, slr before setpcb() */ 58*36565Sbostic sbr = (struct pte *)sm->n_value; 59*36565Sbostic slr = ss->n_value; 60*36565Sbostic adbprintf("sbr %X slr %X\n", sbr, slr); 61*36565Sbostic setpcb((addr_t)mp->n_value); 62*36565Sbostic getpcb(); 63*36565Sbostic findstackframe(); 64*36565Sbostic return (1); 65*36565Sbostic } 66*36565Sbostic 67*36565Sbostic /* 68*36565Sbostic * A version of lookup that never returns failure, and which returns 69*36565Sbostic * the n_value field of the symbol found. 70*36565Sbostic */ 71*36565Sbostic static caddr_t 72*36565Sbostic xlookup(sym) 73*36565Sbostic char *sym; 74*36565Sbostic { 75*36565Sbostic struct nlist *sp; 76*36565Sbostic 77*36565Sbostic if ((sp = lookup(sym)) == NULL) { 78*36565Sbostic adbprintf("symbol %s not found ... bad kernel core?\n", sym); 79*36565Sbostic exit(1); 80*36565Sbostic } 81*36565Sbostic return ((caddr_t)sp->n_value); 82*36565Sbostic } 83*36565Sbostic 84*36565Sbostic /* 85*36565Sbostic * Find the current stack frame when debugging the kernel. 86*36565Sbostic * If we're looking at a crash dump and this was not a ``clean'' 87*36565Sbostic * crash, then we must search the interrupt stack carefully 88*36565Sbostic * looking for a valid frame. 89*36565Sbostic */ 90*36565Sbostic findstackframe() 91*36565Sbostic { 92*36565Sbostic register char *cp; 93*36565Sbostic register int n; 94*36565Sbostic caddr_t addr; 95*36565Sbostic struct frame fr; 96*36565Sbostic char buf[256]; 97*36565Sbostic 98*36565Sbostic if (readcore(kvtooff(xlookup("_panicstr")), (caddr_t)&addr, 99*36565Sbostic sizeof(addr)) != sizeof(addr) || addr == 0) 100*36565Sbostic return; 101*36565Sbostic n = readcore(kvtooff(addr), buf, sizeof(buf)); 102*36565Sbostic for (cp = buf; --n > 0 && *cp != 0; cp++) 103*36565Sbostic if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp))) 104*36565Sbostic *cp = '?'; 105*36565Sbostic *cp = '\0'; 106*36565Sbostic adbprintf("panic: %s\n", buf); 107*36565Sbostic 108*36565Sbostic /* 109*36565Sbostic * After a panic, look at the top of the rpb stack to find a stack 110*36565Sbostic * frame. If this was a clean crash, i.e. one which left the 111*36565Sbostic * interrupt and kernel stacks in a reasonable state, then we should 112*36565Sbostic * find a pointer to the proper stack frame here (at location scb-4). 113*36565Sbostic * If we don't find a reasonable frame here, then we must search down 114*36565Sbostic * through the interrupt stack. 115*36565Sbostic */ 116*36565Sbostic intstack = xlookup("_intstack"); 117*36565Sbostic eintstack = xlookup("_doadump"); /* XXX */ 118*36565Sbostic rpb = xlookup("_rpb"); 119*36565Sbostic scb = xlookup("_scb"); 120*36565Sbostic ustack = xlookup("_u"); 121*36565Sbostic eustack = ustack + ctob(UPAGES); 122*36565Sbostic ustack += (int)((struct user *)0)->u_stack; 123*36565Sbostic (void) readcore(kvtooff(scb - 4), (caddr_t)&addr, sizeof(addr)); 124*36565Sbostic if (!getframe(addr, &fr) && !checkintstack(&addr, &fr)) { 125*36565Sbostic /* search kernel stack? */ 126*36565Sbostic prints("can't locate stack frame\n"); 127*36565Sbostic return; 128*36565Sbostic } 129*36565Sbostic /* probably shouldn't clobber pcb, but for now this is easy */ 130*36565Sbostic pcb.pcb_fp = (int)addr; 131*36565Sbostic pcb.pcb_pc = fr.fr_savpc; 132*36565Sbostic pcb.pcb_ap = (int)addr + sizeof(fr) + fr.fr_spa; 133*36565Sbostic for (n = fr.fr_mask; n != 0; n >>= 1) 134*36565Sbostic if (n & 1) 135*36565Sbostic pcb.pcb_ap += 4; 136*36565Sbostic } 137*36565Sbostic 138*36565Sbostic /* 139*36565Sbostic * Search interrupt stack for a valid frame. Return 1 if found, 140*36565Sbostic * also setting *addr to the kernel address of the frame, and *frame 141*36565Sbostic * to the frame at that address. 142*36565Sbostic */ 143*36565Sbostic checkintstack(addr, frame) 144*36565Sbostic caddr_t *addr; 145*36565Sbostic struct frame *frame; 146*36565Sbostic { 147*36565Sbostic register int ssize; 148*36565Sbostic register char *stack; 149*36565Sbostic 150*36565Sbostic ssize = eintstack - intstack; 151*36565Sbostic if ((stack = malloc((u_int)ssize)) == NULL) 152*36565Sbostic return (0); 153*36565Sbostic if (readcore(kvtooff(intstack), stack, ssize) != ssize) { 154*36565Sbostic free(stack); 155*36565Sbostic return (0); 156*36565Sbostic } 157*36565Sbostic for (ssize -= sizeof(*frame); ssize >= 0; ssize -= 4) { 158*36565Sbostic if (goodframe((struct frame *)&stack[ssize])) { 159*36565Sbostic *addr = &intstack[ssize]; 160*36565Sbostic *frame = *(struct frame *)&stack[ssize]; 161*36565Sbostic free(stack); 162*36565Sbostic return (1); 163*36565Sbostic } 164*36565Sbostic } 165*36565Sbostic free(stack); 166*36565Sbostic return (0); 167*36565Sbostic } 168*36565Sbostic 169*36565Sbostic /* 170*36565Sbostic * Get a stack frame and verify that it looks like 171*36565Sbostic * something which might be on a kernel stack. Return 1 if OK. 172*36565Sbostic */ 173*36565Sbostic getframe(addr, fp) 174*36565Sbostic caddr_t addr; 175*36565Sbostic struct frame *fp; 176*36565Sbostic { 177*36565Sbostic off_t off; 178*36565Sbostic char *err = NULL; 179*36565Sbostic 180*36565Sbostic if (!kstackaddr(addr)) 181*36565Sbostic return (0); 182*36565Sbostic off = vtophys((addr_t)addr, &err); 183*36565Sbostic if (err || readcore(off, (caddr_t)fp, sizeof(*fp)) != sizeof(*fp)) 184*36565Sbostic return (0); 185*36565Sbostic return (goodframe(fp)); 186*36565Sbostic } 187*36565Sbostic 188*36565Sbostic /* 189*36565Sbostic * Check a call frame to see if it's ok as a kernel stack frame. 190*36565Sbostic * It should be a calls, should have its parent within the kernel stack, 191*36565Sbostic * and should return to kernel code. 192*36565Sbostic */ 193*36565Sbostic goodframe(fr) 194*36565Sbostic register struct frame *fr; 195*36565Sbostic { 196*36565Sbostic 197*36565Sbostic return (fr->fr_handler == 0 && fr->fr_s && 198*36565Sbostic kstackaddr(fr->fr_savap) && kstackaddr(fr->fr_savfp) && 199*36565Sbostic within(fr->fr_savpc, txtmap.m1.b, txtmap.m1.e)); 200*36565Sbostic } 201