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