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