xref: /netbsd/sys/arch/sparc64/sparc64/db_trace.c (revision bf9ec67e)
1 /*	$NetBSD: db_trace.c,v 1.25 2002/05/16 20:27:09 eeh Exp $ */
2 
3 /*
4  * Copyright (c) 1996-2002 Eduardo Horvath.  All rights reserved.
5  * Mach Operating System
6  * Copyright (c) 1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie the
27  * rights to redistribute these changes.
28  */
29 
30 #include <sys/param.h>
31 #include <sys/proc.h>
32 #include <sys/systm.h>
33 #include <sys/user.h>
34 #include <machine/db_machdep.h>
35 #include <machine/ctlreg.h>
36 
37 #include <ddb/db_access.h>
38 #include <ddb/db_sym.h>
39 #include <ddb/db_interface.h>
40 #include <ddb/db_output.h>
41 
42 void db_dump_fpstate __P((db_expr_t, int, db_expr_t, char *));
43 void db_dump_window __P((db_expr_t, int, db_expr_t, char *));
44 void db_dump_stack __P((db_expr_t, int, db_expr_t, char *));
45 void db_dump_trap __P((db_expr_t, int, db_expr_t, char *));
46 void db_dump_ts __P((db_expr_t, int, db_expr_t, char *));
47 void db_print_window __P((u_int64_t));
48 
49 #if 0
50 #define INKERNEL(va)	(((vaddr_t)(va)) >= USRSTACK) /* Not really true, y'know */
51 #else
52 #define INKERNEL(va)	1	/* Everything's in the kernel now. 8^) */
53 #endif
54 
55 #define	KLOAD(x)	probeget((paddr_t)(u_long)&(x), ASI_PRIMARY, sizeof(x))
56 #define ULOAD(x)	probeget((paddr_t)(u_long)&(x), ASI_AIUS, sizeof(x))
57 
58 void
59 db_stack_trace_print(addr, have_addr, count, modif, pr)
60 	db_expr_t       addr;
61 	int             have_addr;
62 	db_expr_t       count;
63 	char            *modif;
64  	void		(*pr) __P((const char *, ...));
65 {
66 	vaddr_t		frame;
67 	boolean_t	kernel_only = TRUE;
68 	boolean_t	trace_thread = FALSE;
69 	char		c, *cp = modif;
70 
71 	while ((c = *cp++) != 0) {
72 		if (c == 't')
73 			trace_thread = TRUE;
74 		if (c == 'u')
75 			kernel_only = FALSE;
76 	}
77 
78 	if (!have_addr)
79 		frame = (vaddr_t)DDB_TF->tf_out[6];
80 	else {
81 		if (trace_thread) {
82 			struct proc *p;
83 			struct user *u;
84 			(*pr)("trace: pid %d ", (int)addr);
85 			p = pfind(addr);
86 			if (p == NULL) {
87 				(*pr)("not found\n");
88 				return;
89 			}
90 			if ((p->p_flag & P_INMEM) == 0) {
91 				(*pr)("swapped out\n");
92 				return;
93 			}
94 			u = p->p_addr;
95 			frame = (vaddr_t)u->u_pcb.pcb_sp;
96 			(*pr)("at %p\n", frame);
97 		} else {
98 			frame = (vaddr_t)addr;
99 		}
100 	}
101 
102 	while (count--) {
103 		int		i;
104 		db_expr_t	offset;
105 		char		*name;
106 		db_addr_t	pc;
107 		struct frame64	*f64;
108 		struct frame32  *f32;
109 
110 		/*
111 		 * Switch to frame that contains arguments
112 		 */
113 		if (frame & 1) {
114 			f64 = (struct frame64 *)(frame + BIAS);
115 			pc = (db_addr_t)KLOAD(f64->fr_pc);
116 
117 			frame = KLOAD(f64->fr_fp);
118 		} else {
119 			f32 = (struct frame32 *)(frame);
120 			pc = (db_addr_t)KLOAD(f32->fr_pc);
121 
122 			frame = (long)KLOAD(f32->fr_fp);
123 		}
124 
125 		if (kernel_only) {
126 			if (pc < KERNBASE || pc >= KERNEND)
127 				break;
128 			if (frame < KERNBASE || frame >= EINTSTACK)
129 				break;
130 		} else {
131 			if (frame == 0 || frame == (vaddr_t)-1)
132 				break;
133 		}
134 #if 0
135 		if (!INKERNEL(frame))
136 			break;
137 #endif
138 
139 		db_find_sym_and_offset(pc, &name, &offset);
140 		if (name == NULL)
141 			name = "?";
142 
143 		(*pr)("%s(", name);
144 
145 		/*
146 		 * Print %i0..%i5; hope these still reflect the
147 		 * actual arguments somewhat...
148 		 */
149 		if (frame & 1) {
150 			f64 = (struct frame64 *)(frame + BIAS);
151 			for (i = 0; i < 5; i++)
152 				(*pr)("%lx, ", (long)KLOAD(f64->fr_arg[i]));
153 			(*pr)("%lx) at ", (long)KLOAD(f64->fr_arg[i]));
154 		} else {
155 			f32 = (struct frame32 *)(frame);
156 			for (i = 0; i < 5; i++)
157 				(*pr)("%x, ", (u_int)KLOAD(f32->fr_arg[i]));
158 			(*pr)("%x) at ", (u_int)KLOAD(f32->fr_arg[i]));
159 		}
160 		db_printsym(pc, DB_STGY_PROC, pr);
161 		(*pr)("\n");
162 	}
163 }
164 
165 
166 void
167 db_dump_window(addr, have_addr, count, modif)
168 	db_expr_t addr;
169 	int have_addr;
170 	db_expr_t count;
171 	char *modif;
172 {
173 	int i;
174 	u_int64_t frame = DDB_TF->tf_out[6];
175 
176 	/* Addr is really window number */
177 	if (!have_addr)
178 		addr = 0;
179 
180 	/* Traverse window stack */
181 	for (i=0; i<addr && frame; i++) {
182 		if (frame & 1)
183 			frame = (u_int64_t)((struct frame64 *)(u_long)(frame + BIAS))->fr_fp;
184 		else frame = (u_int64_t)((struct frame32 *)(u_long)frame)->fr_fp;
185 	}
186 
187 	db_printf("Window %lx ", addr);
188 	db_print_window(frame);
189 }
190 
191 void
192 db_print_window(frame)
193 u_int64_t frame;
194 {
195 	if (frame & 1) {
196 		struct frame64* f = (struct frame64*)(u_long)(frame + BIAS);
197 
198 		db_printf("frame64 %p locals, ins:\n", f);
199 		if (INKERNEL(f)) {
200 			db_printf("%llx %llx %llx %llx ",
201 				  (unsigned long long)f->fr_local[0],
202 				  (unsigned long long)f->fr_local[1],
203 				  (unsigned long long)f->fr_local[2],
204 				  (unsigned long long)f->fr_local[3]);
205 			db_printf("%llx %llx %llx %llx\n",
206 				  (unsigned long long)f->fr_local[4],
207 				  (unsigned long long)f->fr_local[5],
208 				  (unsigned long long)f->fr_local[6],
209 				  (unsigned long long)f->fr_local[7]);
210 			db_printf("%llx %llx %llx %llx ",
211 				  (unsigned long long)f->fr_arg[0],
212 				  (unsigned long long)f->fr_arg[1],
213 				  (unsigned long long)f->fr_arg[2],
214 				  (unsigned long long)f->fr_arg[3]);
215 			db_printf("%llx %llx %llx=sp %llx=pc:",
216 				  (unsigned long long)f->fr_arg[4],
217 				  (unsigned long long)f->fr_arg[5],
218 				  (unsigned long long)f->fr_fp,
219 				  (unsigned long long)f->fr_pc);
220 			/* Sometimes this don't work.  Dunno why. */
221 			db_printsym(f->fr_pc, DB_STGY_PROC, db_printf);
222 			db_printf("\n");
223 		} else {
224 			struct frame64 fr;
225 
226 			if (copyin(f, &fr, sizeof(fr))) return;
227 			f = &fr;
228 			db_printf("%llx %llx %llx %llx ",
229 				  (unsigned long long)f->fr_local[0], (unsigned long long)f->fr_local[1], (unsigned long long)f->fr_local[2], (unsigned long long)f->fr_local[3]);
230 			db_printf("%llx %llx %llx %llx\n",
231 				  (unsigned long long)f->fr_local[4], (unsigned long long)f->fr_local[5], (unsigned long long)f->fr_local[6], (unsigned long long)f->fr_local[7]);
232 			db_printf("%llx %llx %llx %llx ",
233 				  (unsigned long long)f->fr_arg[0],
234 				  (unsigned long long)f->fr_arg[1],
235 				  (unsigned long long)f->fr_arg[2],
236 				  (unsigned long long)f->fr_arg[3]);
237 			db_printf("%llx %llx %llx=sp %llx=pc",
238 				  (unsigned long long)f->fr_arg[4],
239 				  (unsigned long long)f->fr_arg[5],
240 				  (unsigned long long)f->fr_fp,
241 				  (unsigned long long)f->fr_pc);
242 			db_printf("\n");
243 		}
244 	} else {
245 		struct frame32* f = (struct frame32*)(u_long)frame;
246 
247 		db_printf("frame %p locals, ins:\n", f);
248 		if (INKERNEL(f)) {
249 			db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n",
250 				  f->fr_local[0], f->fr_local[1], f->fr_local[2], f->fr_local[3],
251 				  f->fr_local[4], f->fr_local[5], f->fr_local[6], f->fr_local[7]);
252 			db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc:",
253 				  f->fr_arg[0], f->fr_arg[1], f->fr_arg[2], f->fr_arg[3],
254 				  f->fr_arg[4], f->fr_arg[5], f->fr_fp, f->fr_pc);
255 			db_printsym(f->fr_pc, DB_STGY_PROC, db_printf);
256 			db_printf("\n");
257 		} else {
258 			struct frame32 fr;
259 
260 			if (copyin(f, &fr, sizeof(fr))) return;
261 			f = &fr;
262 			db_printf("%8x %8x %8x %8x %8x %8x %8x %8x\n",
263 				  f->fr_local[0], f->fr_local[1],
264 				  f->fr_local[2], f->fr_local[3],
265 				  f->fr_local[4], f->fr_local[5],
266 				  f->fr_local[6], f->fr_local[7]);
267 			db_printf("%8x %8x %8x %8x %8x %8x %8x=sp %8x=pc\n",
268 				  f->fr_arg[0], f->fr_arg[1],
269 				  f->fr_arg[2], f->fr_arg[3],
270 				  f->fr_arg[4], f->fr_arg[5],
271 				  f->fr_fp, f->fr_pc);
272 		}
273 	}
274 }
275 
276 void
277 db_dump_stack(addr, have_addr, count, modif)
278 	db_expr_t addr;
279 	int have_addr;
280 	db_expr_t count;
281 	char *modif;
282 {
283 	int		i;
284 	u_int64_t	frame, oldframe;
285 	boolean_t	kernel_only = TRUE;
286 	char		c, *cp = modif;
287 
288 	while ((c = *cp++) != 0)
289 		if (c == 'u')
290 			kernel_only = FALSE;
291 
292 	if (count == -1)
293 		count = 65535;
294 
295 	if (!have_addr)
296 		frame = DDB_TF->tf_out[6];
297 	else
298 		frame = addr;
299 
300 	/* Traverse window stack */
301 	oldframe = 0;
302 	for (i=0; i<count && frame; i++) {
303 		if (oldframe == frame) {
304 			db_printf("WARNING: stack loop at %llx\n",
305 			    (unsigned long long) frame);
306 			break;
307 		}
308 		oldframe = frame;
309 		if (frame & 1) {
310 			frame += BIAS;
311 			if (!INKERNEL(((struct frame64 *)(u_long)(frame)))
312 			    && kernel_only) break;
313 			db_printf("Window %x ", i);
314 			db_print_window(frame - BIAS);
315 			if (!INKERNEL(((struct frame64 *)(u_long)(frame))))
316 				copyin(((caddr_t)&((struct frame64 *)(u_long)frame)->fr_fp), &frame, sizeof(frame));
317 			else
318 				frame = ((struct frame64 *)(u_long)frame)->fr_fp;
319 		} else {
320 			u_int32_t tmp;
321 			if (!INKERNEL(((struct frame32 *)(u_long)frame))
322 			    && kernel_only) break;
323 			db_printf("Window %x ", i);
324 			db_print_window(frame);
325 			if (!INKERNEL(((struct frame32 *)(u_long)frame))) {
326 				copyin(&((struct frame32 *)(u_long)frame)->fr_fp, &tmp, sizeof(tmp));
327 				frame = (u_int64_t)tmp;
328 			} else
329 				frame = (u_int64_t)((struct frame32 *)(u_long)frame)->fr_fp;
330 		}
331 	}
332 
333 }
334 
335 
336 void
337 db_dump_trap(addr, have_addr, count, modif)
338 	db_expr_t addr;
339 	int have_addr;
340 	db_expr_t count;
341 	char *modif;
342 {
343 	struct trapframe64 *tf;
344 
345 	/* Use our last trapframe? */
346 	tf = &ddb_regs.ddb_tf;
347 	{
348 		/* Or the user trapframe? */
349 		register char c, *cp = modif;
350 		while ((c = *cp++) != 0)
351 			if (c == 'u')
352 				tf = curproc->p_md.md_tf;
353 	}
354 	/* Or an arbitrary trapframe */
355 	if (have_addr)
356 		tf = (struct trapframe64 *)addr;
357 
358 	db_printf("Trapframe %p:\ttstate: %llx\tpc: %llx\tnpc: %llx\n",
359 		  tf, (unsigned long long)tf->tf_tstate,
360 		  (unsigned long long)tf->tf_pc,
361 		  (unsigned long long)tf->tf_npc);
362 	db_printf("y: %x\tpil: %d\toldpil: %d\tfault: %llx\ttt: %x\tGlobals:\n",
363 		  (int)tf->tf_y, (int)tf->tf_pil, (int)tf->tf_oldpil,
364 		  (unsigned long long)tf->tf_fault, (int)tf->tf_tt);
365 	db_printf("%016llx %016llx %016llx %016llx\n",
366 		  (unsigned long long)tf->tf_global[0],
367 		  (unsigned long long)tf->tf_global[1],
368 		  (unsigned long long)tf->tf_global[2],
369 		  (unsigned long long)tf->tf_global[3]);
370 	db_printf("%016llx %016llx %016llx %016llx\nouts:\n",
371 		  (unsigned long long)tf->tf_global[4],
372 		  (unsigned long long)tf->tf_global[5],
373 		  (unsigned long long)tf->tf_global[6],
374 		  (unsigned long long)tf->tf_global[7]);
375 	db_printf("%016llx %016llx %016llx %016llx\n",
376 		  (unsigned long long)tf->tf_out[0],
377 		  (unsigned long long)tf->tf_out[1],
378 		  (unsigned long long)tf->tf_out[2],
379 		  (unsigned long long)tf->tf_out[3]);
380 	db_printf("%016llx %016llx %016llx %016llx\n",
381 		  (unsigned long long)tf->tf_out[4],
382 		  (unsigned long long)tf->tf_out[5],
383 		  (unsigned long long)tf->tf_out[6],
384 		  (unsigned long long)tf->tf_out[7]);
385 #ifdef DEBUG
386 	db_printf("locals:\n%016llx %016llx %016llx %016llx\n",
387 		  (unsigned long long)tf->tf_local[0],
388 		  (unsigned long long)tf->tf_local[1],
389 		  (unsigned long long)tf->tf_local[2],
390 		  (unsigned long long)tf->tf_local[3]);
391 	db_printf("%016llx %016llx %016llx %016llx\nins:\n",
392 		  (unsigned long long)tf->tf_local[4],
393 		  (unsigned long long)tf->tf_local[5],
394 		  (unsigned long long)tf->tf_local[6],
395 		  (unsigned long long)tf->tf_local[7]);
396 	db_printf("%016llx %016llx %016llx %016llx\n",
397 		  (unsigned long long)tf->tf_in[0],
398 		  (unsigned long long)tf->tf_in[1],
399 		  (unsigned long long)tf->tf_in[2],
400 		  (unsigned long long)tf->tf_in[3]);
401 	db_printf("%016llx %016llx %016llx %016llx\n",
402 		  (unsigned long long)tf->tf_in[4],
403 		  (unsigned long long)tf->tf_in[5],
404 		  (unsigned long long)tf->tf_in[6],
405 		  (unsigned long long)tf->tf_in[7]);
406 #endif
407 #if 0
408 	if (tf == curproc->p_md.md_tf) {
409 		struct rwindow32 *kstack = (struct rwindow32 *)(((caddr_t)tf)+CCFSZ);
410 		db_printf("ins (from stack):\n%016llx %016llx %016llx %016llx\n",
411 			  (int64_t)kstack->rw_local[0], (int64_t)kstack->rw_local[1],
412 			  (int64_t)kstack->rw_local[2], (int64_t)kstack->rw_local[3]);
413 		db_printf("%016llx %016llx %016llx %016llx\n",
414 			  (int64_t)kstack->rw_local[4], (int64_t)kstack->rw_local[5],
415 			  (int64_t)kstack->rw_local[6], (int64_t)kstack->rw_local[7]);
416 	}
417 #endif
418 }
419 
420 void
421 db_dump_fpstate(addr, have_addr, count, modif)
422 	db_expr_t addr;
423 	int have_addr;
424 	db_expr_t count;
425 	char *modif;
426 {
427 	struct fpstate64 *fpstate;
428 
429 	/* Use our last trapframe? */
430 	fpstate = &ddb_regs.ddb_fpstate;
431 	/* Or an arbitrary trapframe */
432 	if (have_addr)
433 		fpstate = (struct fpstate64 *)addr;
434 
435 	db_printf("fpstate %p: fsr = %llx gsr = %lx\nfpregs:\n",
436 		fpstate, (unsigned long long)fpstate->fs_fsr,
437 		(unsigned long)fpstate->fs_gsr);
438 	db_printf(" 0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
439 		(unsigned int)fpstate->fs_regs[0],
440 		(unsigned int)fpstate->fs_regs[1],
441 		(unsigned int)fpstate->fs_regs[2],
442 		(unsigned int)fpstate->fs_regs[3],
443 		(unsigned int)fpstate->fs_regs[4],
444 		(unsigned int)fpstate->fs_regs[5],
445 		(unsigned int)fpstate->fs_regs[6],
446 		(unsigned int)fpstate->fs_regs[7]);
447 	db_printf(" 8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
448 		(unsigned int)fpstate->fs_regs[8],
449 		(unsigned int)fpstate->fs_regs[9],
450 		(unsigned int)fpstate->fs_regs[10],
451 		(unsigned int)fpstate->fs_regs[11],
452 		(unsigned int)fpstate->fs_regs[12],
453 		(unsigned int)fpstate->fs_regs[13],
454 		(unsigned int)fpstate->fs_regs[14],
455 		(unsigned int)fpstate->fs_regs[15]);
456 	db_printf("16: %08x %08x %08x %08x %08x %08x %08x %08x\n",
457 		(unsigned int)fpstate->fs_regs[16],
458 		(unsigned int)fpstate->fs_regs[17],
459 		(unsigned int)fpstate->fs_regs[18],
460 		(unsigned int)fpstate->fs_regs[19],
461 		(unsigned int)fpstate->fs_regs[20],
462 		(unsigned int)fpstate->fs_regs[21],
463 		(unsigned int)fpstate->fs_regs[22],
464 		(unsigned int)fpstate->fs_regs[23]);
465 	db_printf("24: %08x %08x %08x %08x %08x %08x %08x %08x\n",
466 		(unsigned int)fpstate->fs_regs[24],
467 		(unsigned int)fpstate->fs_regs[25],
468 		(unsigned int)fpstate->fs_regs[26],
469 		(unsigned int)fpstate->fs_regs[27],
470 		(unsigned int)fpstate->fs_regs[28],
471 		(unsigned int)fpstate->fs_regs[29],
472 		(unsigned int)fpstate->fs_regs[30],
473 		(unsigned int)fpstate->fs_regs[31]);
474 	db_printf("32: %08x%08x %08x%08x %08x%08x %08x%08x\n",
475 		(unsigned int)fpstate->fs_regs[32],
476 		(unsigned int)fpstate->fs_regs[33],
477 		(unsigned int)fpstate->fs_regs[34],
478 		(unsigned int)fpstate->fs_regs[35],
479 		(unsigned int)fpstate->fs_regs[36],
480 		(unsigned int)fpstate->fs_regs[37],
481 		(unsigned int)fpstate->fs_regs[38],
482 		(unsigned int)fpstate->fs_regs[39]);
483 	db_printf("40: %08x%08x %08x%08x %08x%08x %08x%08x\n",
484 		(unsigned int)fpstate->fs_regs[40],
485 		(unsigned int)fpstate->fs_regs[41],
486 		(unsigned int)fpstate->fs_regs[42],
487 		(unsigned int)fpstate->fs_regs[43],
488 		(unsigned int)fpstate->fs_regs[44],
489 		(unsigned int)fpstate->fs_regs[45],
490 		(unsigned int)fpstate->fs_regs[46],
491 		(unsigned int)fpstate->fs_regs[47]);
492 	db_printf("48: %08x%08x %08x%08x %08x%08x %08x%08x\n",
493 		(unsigned int)fpstate->fs_regs[48],
494 		(unsigned int)fpstate->fs_regs[49],
495 		(unsigned int)fpstate->fs_regs[50],
496 		(unsigned int)fpstate->fs_regs[51],
497 		(unsigned int)fpstate->fs_regs[52],
498 		(unsigned int)fpstate->fs_regs[53],
499 		(unsigned int)fpstate->fs_regs[54],
500 		(unsigned int)fpstate->fs_regs[55]);
501 	db_printf("56: %08x%08x %08x%08x %08x%08x %08x%08x\n",
502 		(unsigned int)fpstate->fs_regs[56],
503 		(unsigned int)fpstate->fs_regs[57],
504 		(unsigned int)fpstate->fs_regs[58],
505 		(unsigned int)fpstate->fs_regs[59],
506 		(unsigned int)fpstate->fs_regs[60],
507 		(unsigned int)fpstate->fs_regs[61],
508 		(unsigned int)fpstate->fs_regs[62],
509 		(unsigned int)fpstate->fs_regs[63]);
510 }
511 
512 void
513 db_dump_ts(addr, have_addr, count, modif)
514 	db_expr_t addr;
515 	int have_addr;
516 	db_expr_t count;
517 	char *modif;
518 {
519 	struct trapstate	*ts;
520 	int			i, tl;
521 
522 	/* Use our last trapframe? */
523 	ts = &ddb_regs.ddb_ts[0];
524 	tl = ddb_regs.ddb_tl;
525 	for (i=0; i<tl; i++) {
526 		printf("%d tt=%lx tstate=%lx tpc=%p tnpc=%p\n",
527 		       i+1, (long)ts[i].tt, (u_long)ts[i].tstate,
528 		       (void*)(u_long)ts[i].tpc, (void*)(u_long)ts[i].tnpc);
529 	}
530 
531 }
532 
533 
534