|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)kstack.c 5.1 (Berkeley) 1/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.