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