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