1*47819Sbostic /*-
2*47819Sbostic * Copyright (c) 1991 The Regents of the University of California.
3*47819Sbostic * All rights reserved.
4*47819Sbostic *
5*47819Sbostic * %sccs.include.proprietary.c%
6*47819Sbostic */
7*47819Sbostic
836560Sbostic #ifndef lint
9*47819Sbostic static char sccsid[] = "@(#)kstack.c 5.4 (Berkeley) 04/04/91";
10*47819Sbostic #endif /* not lint */
1136560Sbostic
1236560Sbostic /*
1336560Sbostic * adb - routines to probe the kernel stack when debugging post-mortem
1436560Sbostic * crash dumps.
1536560Sbostic */
1636560Sbostic
1736560Sbostic #include "defs.h"
1836560Sbostic #include <ctype.h>
1936560Sbostic #include <machine/pte.h>
2036560Sbostic #include <machine/frame.h>
2145982Sbostic #include <tahoe/tahoe/rpb.h>
2236560Sbostic
2336560Sbostic struct pte *sbr;
2436560Sbostic int slr;
2536560Sbostic struct pcb pcb;
2636560Sbostic
2736560Sbostic static caddr_t rpb, erpb;
2836560Sbostic static caddr_t intstack, eintstack;
2936560Sbostic static caddr_t ustack, eustack;
3036560Sbostic
3136560Sbostic char *malloc();
3236560Sbostic
3336560Sbostic /*
3436560Sbostic * Convert a kernel virtual address to an (off_t) physical offset.
3536560Sbostic */
3636560Sbostic #define kvtooff(a) ((off_t)(a) & ~KERNBASE)
3736560Sbostic
3836560Sbostic /*
3936560Sbostic * Check if an address is in one of the kernel's stacks:
4036560Sbostic * interrupt stack, rpb stack (during restart sequence),
4136560Sbostic * or u. stack.
4236560Sbostic */
4336560Sbostic #define within(a, b, e) \
4436560Sbostic ((addr_t)(a) >= (addr_t)(b) && (addr_t)(a) < (addr_t)(e))
4536560Sbostic #define kstackaddr(a) \
4636560Sbostic (within(a, intstack, eintstack) || \
4736560Sbostic within(a, rpb + sizeof(struct rpb), erpb) || \
4836560Sbostic within(a, ustack, eustack))
4936560Sbostic
5036560Sbostic /*
5136560Sbostic * Determine whether we are looking at a kernel core dump, and if so,
5236560Sbostic * set sbr and slr and the current pcb.
5336560Sbostic */
getkcore()5436560Sbostic getkcore() {
5536560Sbostic struct nlist *sm, *ss, *mp;
5636560Sbostic
5736560Sbostic if ((sm = lookup("_Sysmap")) == NULL ||
5836560Sbostic (ss = lookup("_Syssize")) == NULL ||
5936560Sbostic (mp = lookup("_masterpaddr")) == NULL)
6036560Sbostic return (0); /* a.out is not a vmunix */
6136560Sbostic datmap.m1.b = 0;
6236560Sbostic datmap.m1.e = -1L;
6336560Sbostic /* must set sbr, slr before setpcb() */
6436560Sbostic sbr = (struct pte *)sm->n_value;
6536560Sbostic slr = ss->n_value;
6636560Sbostic adbprintf("sbr %X slr %X\n", sbr, slr);
6736560Sbostic setpcb((addr_t)mp->n_value);
6836560Sbostic getpcb();
6936560Sbostic findstackframe();
7036560Sbostic return (1);
7136560Sbostic }
7236560Sbostic
7336560Sbostic /*
7436560Sbostic * A version of lookup that never returns failure, and which returns
7536560Sbostic * the n_value field of the symbol found.
7636560Sbostic */
7736560Sbostic static caddr_t
xlookup(sym)7836560Sbostic xlookup(sym)
7936560Sbostic char *sym;
8036560Sbostic {
8136560Sbostic struct nlist *sp;
8236560Sbostic
8336560Sbostic if ((sp = lookup(sym)) == NULL) {
8436560Sbostic adbprintf("symbol %s not found ... bad kernel core?\n", sym);
8536560Sbostic exit(1);
8636560Sbostic }
8736560Sbostic return ((caddr_t)sp->n_value);
8836560Sbostic }
8936560Sbostic
9036560Sbostic /*
9136560Sbostic * Find the current stack frame when debugging the kernel.
9236560Sbostic * If we're looking at a crash dump and this was not a ``clean''
9336560Sbostic * crash, then we must search the interrupt stack carefully
9436560Sbostic * looking for a valid frame.
9536560Sbostic */
findstackframe()9636560Sbostic findstackframe()
9736560Sbostic {
9836560Sbostic register char *cp;
9936560Sbostic register int n;
10036560Sbostic caddr_t addr;
10136560Sbostic struct frame fr;
10236560Sbostic char buf[256];
10336560Sbostic
10436560Sbostic if (readcore(kvtooff(xlookup("_panicstr")), (caddr_t)&addr,
10536560Sbostic sizeof(addr)) != sizeof(addr) || addr == 0)
10636560Sbostic return;
10736560Sbostic n = readcore(kvtooff(addr), buf, sizeof(buf));
10836560Sbostic for (cp = buf; --n > 0 && *cp != 0; cp++)
10936560Sbostic if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
11036560Sbostic *cp = '?';
11136560Sbostic *cp = '\0';
11236560Sbostic adbprintf("panic: %s\n", buf);
11336560Sbostic
11436560Sbostic /*
11536560Sbostic * After a panic, look at the top of the rpb stack to find a stack
11636560Sbostic * frame. If this was a clean crash, i.e. one which left the
11736560Sbostic * interrupt and kernel stacks in a reasonable state, then we should
11836560Sbostic * find a pointer to the proper stack frame here (at location
11936560Sbostic * intstack-8). If we don't find a reasonable frame here, then we
12036560Sbostic * must search down through the interrupt stack.
12136560Sbostic */
12236560Sbostic intstack = xlookup("_intstack");
12336560Sbostic eintstack = xlookup("_Xdoadump"); /* XXX */
12436560Sbostic rpb = xlookup("_rsstk"); /* XXX */
12536560Sbostic erpb = rpb + NBPG - 2 * sizeof(long);
12636560Sbostic ustack = xlookup("_u");
12736560Sbostic eustack = ustack + ctob(UPAGES);
12836560Sbostic ustack += (int)((struct user *)0)->u_stack;
12936560Sbostic (void) readcore(kvtooff(intstack - 8), (caddr_t)&addr, sizeof(addr));
13036560Sbostic if (!getframe(addr, &fr) && !checkintstack(&addr, &fr)) {
13136560Sbostic /* search kernel stack? */
13236560Sbostic prints("can't locate stack frame\n");
13336560Sbostic return;
13436560Sbostic }
13536560Sbostic /* probably shouldn't clobber pcb, but for now this is easy */
13636560Sbostic pcb.pcb_fp = (int)addr;
13736560Sbostic pcb.pcb_pc = fr.fr_savpc;
13836560Sbostic }
13936560Sbostic
14036560Sbostic /*
14136560Sbostic * Search interrupt stack for a valid frame. Return 1 if found,
14236560Sbostic * also setting *addr to the kernel address of the frame, and *frame
14336560Sbostic * to the frame at that address.
14436560Sbostic */
checkintstack(addr,frame)14536560Sbostic checkintstack(addr, frame)
14636560Sbostic caddr_t *addr;
14736560Sbostic struct frame *frame;
14836560Sbostic {
14936560Sbostic register int ssize;
15036560Sbostic register char *stack;
15136560Sbostic
15236560Sbostic ssize = eintstack - intstack;
15336560Sbostic if ((stack = malloc((u_int)ssize)) == NULL)
15436560Sbostic return (0);
15536560Sbostic if (readcore(kvtooff(intstack), stack, ssize) != ssize) {
15636560Sbostic free(stack);
15736560Sbostic return (0);
15836560Sbostic }
15936560Sbostic for (ssize -= sizeof(*frame); ssize >= 0; ssize -= 4) {
16036560Sbostic if (goodframe((struct frame *)&stack[ssize])) {
16136560Sbostic *addr = &intstack[ssize] + FRAMEOFF;
16236560Sbostic *frame = *(struct frame *)&stack[ssize];
16336560Sbostic free(stack);
16436560Sbostic return (1);
16536560Sbostic }
16636560Sbostic }
16736560Sbostic free(stack);
16836560Sbostic return (0);
16936560Sbostic }
17036560Sbostic
17136560Sbostic /*
17236560Sbostic * Get a stack frame and verify that it looks like
17336560Sbostic * something which might be on a kernel stack. Return 1 if OK.
17436560Sbostic */
getframe(addr,fp)17536560Sbostic getframe(addr, fp)
17636560Sbostic caddr_t addr;
17736560Sbostic struct frame *fp;
17836560Sbostic {
17936560Sbostic off_t off;
18036560Sbostic char *err = NULL;
18136560Sbostic
18236560Sbostic if (!kstackaddr(addr))
18336560Sbostic return (0);
18436560Sbostic off = vtophys((addr_t)(addr - FRAMEOFF), &err);
18536560Sbostic if (err || readcore(off, (caddr_t)fp, sizeof(*fp)) != sizeof(*fp))
18636560Sbostic return (0);
18736560Sbostic return (goodframe(fp));
18836560Sbostic }
18936560Sbostic
19036560Sbostic /*
19136560Sbostic * Check a call frame to see if it's ok as a kernel stack frame.
19236560Sbostic * It should have its parent frame in the kernel stack, and should
19336560Sbostic * return to kernel code.
19436560Sbostic */
goodframe(fr)19536560Sbostic goodframe(fr)
19636560Sbostic register struct frame *fr;
19736560Sbostic {
19836560Sbostic
19936560Sbostic return (kstackaddr(fr->fr_savfp) &&
20036560Sbostic within(fr->fr_savpc, txtmap.m1.b, txtmap.m1.e));
20136560Sbostic }
202