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