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