xref: /netbsd-src/sys/arch/hppa/hppa/db_interface.c (revision ce2c90c7c172d95d2402a5b3d96d8f8e6d138a21)
1 /*	$NetBSD: db_interface.c,v 1.9 2006/08/26 06:27:40 skrll Exp $	*/
2 
3 /*	$OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $	*/
4 
5 /*
6  * Copyright (c) 1999-2000 Michael Shalayeff
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Michael Shalayeff.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.9 2006/08/26 06:27:40 skrll Exp $");
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 
41 #include <machine/db_machdep.h>
42 #include <machine/frame.h>
43 #include <machine/cpufunc.h>
44 
45 #include <ddb/db_access.h>
46 #include <ddb/db_command.h>
47 #include <ddb/db_output.h>
48 #include <ddb/db_run.h>
49 #include <ddb/db_sym.h>
50 #include <ddb/db_variables.h>
51 #include <ddb/db_extern.h>
52 #include <ddb/db_interface.h>
53 #include <ddb/ddbvar.h>
54 
55 #include <dev/cons.h>
56 
57 void kdbprinttrap(int, int);
58 
59 extern label_t *db_recover;
60 extern int db_active;
61 extern char *trap_type[];
62 extern int trap_types;
63 
64 db_regs_t	ddb_regs;
65 const struct db_variable db_regs[] = {
66 	{ "flags", (long *)&ddb_regs.tf_flags,  FCN_NULL },
67 	{ "r1",    (long *)&ddb_regs.tf_r1,  FCN_NULL },
68 	{ "rp",    (long *)&ddb_regs.tf_rp,  FCN_NULL },
69 	{ "r3",    (long *)&ddb_regs.tf_r3,  FCN_NULL },
70 	{ "r4",    (long *)&ddb_regs.tf_r4,  FCN_NULL },
71 	{ "r5",    (long *)&ddb_regs.tf_r5,  FCN_NULL },
72 	{ "r6",    (long *)&ddb_regs.tf_r6,  FCN_NULL },
73 	{ "r7",    (long *)&ddb_regs.tf_r7,  FCN_NULL },
74 	{ "r8",    (long *)&ddb_regs.tf_r8,  FCN_NULL },
75 	{ "r9",    (long *)&ddb_regs.tf_r9,  FCN_NULL },
76 	{ "r10",   (long *)&ddb_regs.tf_r10, FCN_NULL },
77 	{ "r11",   (long *)&ddb_regs.tf_r11, FCN_NULL },
78 	{ "r12",   (long *)&ddb_regs.tf_r12, FCN_NULL },
79 	{ "r13",   (long *)&ddb_regs.tf_r13, FCN_NULL },
80 	{ "r14",   (long *)&ddb_regs.tf_r14, FCN_NULL },
81 	{ "r15",   (long *)&ddb_regs.tf_r15, FCN_NULL },
82 	{ "r16",   (long *)&ddb_regs.tf_r16, FCN_NULL },
83 	{ "r17",   (long *)&ddb_regs.tf_r17, FCN_NULL },
84 	{ "r18",   (long *)&ddb_regs.tf_r18, FCN_NULL },
85 	{ "t4",    (long *)&ddb_regs.tf_t4,  FCN_NULL },
86 	{ "t3",    (long *)&ddb_regs.tf_t3,  FCN_NULL },
87 	{ "t2",    (long *)&ddb_regs.tf_t2,  FCN_NULL },
88 	{ "t1",    (long *)&ddb_regs.tf_t1,  FCN_NULL },
89 	{ "arg3",  (long *)&ddb_regs.tf_arg3,  FCN_NULL },
90 	{ "arg2",  (long *)&ddb_regs.tf_arg2,  FCN_NULL },
91 	{ "arg1",  (long *)&ddb_regs.tf_arg1,  FCN_NULL },
92 	{ "arg0",  (long *)&ddb_regs.tf_arg0,  FCN_NULL },
93 	{ "dp",    (long *)&ddb_regs.tf_dp,    FCN_NULL },
94 	{ "ret0",  (long *)&ddb_regs.tf_ret0,  FCN_NULL },
95 	{ "ret1",  (long *)&ddb_regs.tf_ret1,  FCN_NULL },
96 	{ "sp",    (long *)&ddb_regs.tf_sp,    FCN_NULL },
97 	{ "r31",   (long *)&ddb_regs.tf_r31,   FCN_NULL },
98 	{ "sar",   (long *)&ddb_regs.tf_sar,   FCN_NULL },
99 
100 	{ "eirr",  (long *)&ddb_regs.tf_eirr,  FCN_NULL },
101 	{ "eiem",  (long *)&ddb_regs.tf_eiem,  FCN_NULL },
102 	{ "iir",   (long *)&ddb_regs.tf_iir,   FCN_NULL },
103 	{ "isr",   (long *)&ddb_regs.tf_isr,   FCN_NULL },
104 	{ "ior",   (long *)&ddb_regs.tf_ior,   FCN_NULL },
105 	{ "ipsw",  (long *)&ddb_regs.tf_ipsw,  FCN_NULL },
106 	{ "iisqh", (long *)&ddb_regs.tf_iisq_head,  FCN_NULL },
107 	{ "iioqh", (long *)&ddb_regs.tf_iioq_head,  FCN_NULL },
108 	{ "iisqt", (long *)&ddb_regs.tf_iisq_tail,  FCN_NULL },
109 	{ "iioqt", (long *)&ddb_regs.tf_iioq_tail,  FCN_NULL },
110 
111 	{ "sr0",   (long *)&ddb_regs.tf_sr0,   FCN_NULL },
112 	{ "sr1",   (long *)&ddb_regs.tf_sr1,   FCN_NULL },
113 	{ "sr2",   (long *)&ddb_regs.tf_sr2,   FCN_NULL },
114 	{ "sr3",   (long *)&ddb_regs.tf_sr3,   FCN_NULL },
115 	{ "sr4",   (long *)&ddb_regs.tf_sr4,   FCN_NULL },
116 	{ "sr5",   (long *)&ddb_regs.tf_sr5,   FCN_NULL },
117 	{ "sr6",   (long *)&ddb_regs.tf_sr6,   FCN_NULL },
118 	{ "sr7",   (long *)&ddb_regs.tf_sr7,   FCN_NULL },
119 
120 	{ "pidr1", (long *)&ddb_regs.tf_pidr1, FCN_NULL },
121 	{ "pidr2", (long *)&ddb_regs.tf_pidr2, FCN_NULL },
122 #ifdef pbably_not_worth_it
123 	{ "pidr3", (long *)&ddb_regs.tf_pidr3, FCN_NULL },
124 	{ "pidr4", (long *)&ddb_regs.tf_pidr4, FCN_NULL },
125 #endif
126 
127 	{ "hptm",  (long *)&ddb_regs.tf_hptm,  FCN_NULL },
128 	{ "vtop",  (long *)&ddb_regs.tf_vtop,  FCN_NULL },
129 	{ "cr28",  (long *)&ddb_regs.tf_cr28,  FCN_NULL },
130 	{ "cr30",  (long *)&ddb_regs.tf_cr30,  FCN_NULL },
131 };
132 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
133 int db_active = 0;
134 
135 void
136 Debugger(void)
137 {
138 	__asm volatile ("break	%0, %1"
139 			  :: "i" (HPPA_BREAK_KERNEL), "i" (HPPA_BREAK_KGDB));
140 }
141 
142 /*
143  * Print trap reason.
144  */
145 void
146 kdbprinttrap(int type, int code)
147 {
148 	db_printf("kernel: ");
149 	if (type >= trap_types || type < 0)
150 		db_printf("type %d", type);
151 	else
152 		db_printf("%s", trap_type[type]);
153 	db_printf(" trap, code=%x\n", code);
154 }
155 
156 /*
157  *  kdb_trap - field a BPT trap
158  */
159 int
160 kdb_trap(int type, int code, db_regs_t *regs)
161 {
162 	int s;
163 
164 	switch (type) {
165 	case T_RECOVERY:
166 	case T_IBREAK:
167 	case T_DBREAK:
168 	case -1:
169 		break;
170 	default:
171 		if (!db_onpanic && db_recover == 0)
172 			return 0;
173 
174 		kdbprinttrap(type, code);
175 		if (db_recover != 0) {
176 			db_error("Caught exception in DDB; continuing...\n");
177 			/* NOT REACHED */
178 		}
179 	}
180 
181 	/* XXX Should switch to kdb`s own stack here. */
182 
183 	ddb_regs = *regs;
184 
185 	s = splhigh();
186 	db_active++;
187 	cnpollc(TRUE);
188 	db_trap(type, code);
189 	cnpollc(FALSE);
190 	db_active--;
191 	splx(s);
192 
193 	*regs = ddb_regs;
194 	return (1);
195 }
196 
197 /*
198  *  Validate an address for use as a breakpoint.
199  *  Any address is allowed for now.
200  */
201 int
202 db_valid_breakpoint(db_addr_t addr)
203 {
204 	return (1);
205 }
206 
207 void
208 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
209     const char *modif, void (*pr)(const char *, ...))
210 {
211 	register_t *fp, pc, rp, nargs, *argp;
212 	db_sym_t sym;
213 	db_expr_t off;
214 	const char *name;
215 	char **argnp, *argnames[HPPA_FRAME_NARGS];
216 
217 	if (count < 0)
218 		count = 65536;
219 
220 	if (!have_addr) {
221 		fp = (register_t *)ddb_regs.tf_r3;
222 		pc = ddb_regs.tf_iioq_head;
223 		rp = ddb_regs.tf_rp;
224 	} else {
225 		fp = (register_t *)addr;
226 		pc = 0;
227 		rp = ((register_t *)fp)[-5];
228 	}
229 
230 #ifdef DDB_DEBUG
231 	pr(">> %x, %x, %x\t", fp, pc, rp);
232 #endif
233 	while (fp && count--) {
234 
235 		if (USERMODE(pc))
236 			return;
237 
238 		sym = db_search_symbol(pc, DB_STGY_ANY, &off);
239 		db_symbol_values (sym, &name, NULL);
240 
241 		pr("%s(", name);
242 
243 		/* args */
244 		nargs = HPPA_FRAME_NARGS;
245 		argnp = NULL;
246 		if (db_sym_numargs(sym, &nargs, argnames))
247 			argnp = argnames;
248 		else
249 			nargs = 4;
250 		/*
251 		 * XXX first four args are passed on registers, and may not
252 		 * be stored on stack, dunno how to recover their values yet
253 		 */
254 		for (argp = &fp[-9]; nargs--; argp--) {
255 			if (argnp)
256 				pr("%s=", *argnp++);
257 			pr("%lx%s", db_get_value((int)argp, 4, FALSE),
258 				  nargs? ",":"");
259 		}
260 		pr(") at ");
261 		db_printsym(pc, DB_STGY_PROC, pr);
262 		pr("\n");
263 
264 		/* TODO: print locals */
265 
266 		/* next frame */
267 		pc = rp;
268 		rp = fp[-5];
269 
270 		/* if a terminal frame and not a start of a page
271 		 * then skip the trapframe and the terminal frame */
272 		if (!fp[0]) {
273 			struct trapframe *tf;
274 
275 			tf = (struct trapframe *)((char *)fp - sizeof(*tf));
276 
277 			if (tf->tf_flags & TFF_SYS)
278 				pr("-- syscall #%d(%x, %x, %x, %x, ...)\n",
279 				    tf->tf_t1, tf->tf_arg0, tf->tf_arg1,
280 				    tf->tf_arg2, tf->tf_arg3);
281 			else
282 				pr("-- trap #%d%s\n", tf->tf_flags & 0x3f,
283 				    (tf->tf_flags & T_USER)? " from user" : "");
284 
285 			if (!(tf->tf_flags & TFF_LAST)) {
286 				fp = (register_t *)tf->tf_r3;
287 				pc = tf->tf_iioq_head;
288 				rp = tf->tf_rp;
289 			} else
290 				fp = 0;
291 		} else
292 			fp = (register_t *)fp[0];
293 #ifdef DDB_DEBUG
294 		pr(">> %x, %x, %x\t", fp, pc, rp);
295 #endif
296 	}
297 
298 	if (count && pc) {
299 		db_printsym(pc, DB_STGY_XTRN, pr);
300 		pr(":\n");
301 	}
302 }
303