xref: /netbsd/sys/arch/sparc/sparc/db_trace.c (revision bf9ec67e)
1 /*	$NetBSD: db_trace.c,v 1.16 2000/05/26 03:34:29 jhawk Exp $ */
2 
3 /*
4  * Mach Operating System
5  * Copyright (c) 1991,1990 Carnegie Mellon University
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie the
26  * rights to redistribute these changes.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/proc.h>
31 #include <sys/user.h>
32 #include <machine/db_machdep.h>
33 
34 #include <ddb/db_access.h>
35 #include <ddb/db_sym.h>
36 #include <ddb/db_interface.h>
37 #include <ddb/db_output.h>
38 
39 #define INKERNEL(va)	(((vaddr_t)(va)) >= USRSTACK)
40 
41 void
42 db_stack_trace_print(addr, have_addr, count, modif, pr)
43 	db_expr_t       addr;
44 	int             have_addr;
45 	db_expr_t       count;
46 	char            *modif;
47 	void		(*pr) __P((const char *, ...));
48 {
49 	struct frame	*frame;
50 	boolean_t	kernel_only = TRUE;
51 	boolean_t	trace_thread = FALSE;
52 	char		c, *cp = modif;
53 
54 	while ((c = *cp++) != 0) {
55 		if (c == 't')
56 			trace_thread = TRUE;
57 		if (c == 'u')
58 			kernel_only = FALSE;
59 	}
60 
61 	if (!have_addr)
62 		frame = (struct frame *)DDB_TF->tf_out[6];
63 	else {
64 		if (trace_thread) {
65 			struct proc *p;
66 			struct user *u;
67 			(*pr)("trace: pid %d ", (int)addr);
68 			p = pfind(addr);
69 			if (p == NULL) {
70 				(*pr)("not found\n");
71 				return;
72 			}
73 			if ((p->p_flag & P_INMEM) == 0) {
74 				(*pr)("swapped out\n");
75 				return;
76 			}
77 			u = p->p_addr;
78 			frame = (struct frame *)u->u_pcb.pcb_sp;
79 			(*pr)("at %p\n", frame);
80 		} else {
81 			frame = (struct frame *)addr;
82 		}
83 	}
84 
85 	while (count--) {
86 		int		i;
87 		db_expr_t	offset;
88 		char		*name;
89 		db_addr_t	pc;
90 
91 		/*
92 		 * Switch to frame that contains arguments
93 		 */
94 
95 		pc = frame->fr_pc;
96 		frame = frame->fr_fp;
97 
98 		if (!INKERNEL(pc) || !INKERNEL(frame)) {
99 			if (!kernel_only) {
100 				count++;
101 				while (count--) {
102 					(*pr)("0x%lx()\n", pc);
103 					pc = fuword(&frame->fr_pc);
104 					frame = (void *)fuword(&frame->fr_fp);
105 					if (pc == 0 || frame == NULL) {
106 						return;
107 					}
108 				}
109 			}
110 			return;
111 		}
112 
113 		db_find_sym_and_offset(pc, &name, &offset);
114 		if (name == NULL)
115 			name = "?";
116 
117 		(*pr)("%s(", name);
118 
119 		/*
120 		 * Print %i0..%i5, hope these still reflect the
121 		 * actual arguments somewhat...
122 		 */
123 		for (i=0; i < 5; i++)
124 			(*pr)("0x%x, ", frame->fr_arg[i]);
125 		(*pr)("0x%x) at ", frame->fr_arg[i]);
126 		db_printsym(pc, DB_STGY_PROC, pr);
127 		(*pr)("\n");
128 	}
129 }
130