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