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