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