xref: /netbsd-src/sys/arch/hppa/hppa/db_trace.c (revision bd44ed7096bdfbfe80ca09c7f229b57c68c25aa3)
1 /*	$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 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-2003 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  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 
38 #include <machine/db_machdep.h>
39 
40 #include <ddb/db_access.h>
41 #include <ddb/db_sym.h>
42 #include <ddb/db_interface.h>
43 #include <ddb/db_proc.h>
44 
45 void
db_stack_trace_print(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif,void (* pr)(const char *,...))46 db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
47     const char *modif, void (*pr)(const char *, ...))
48 {
49 	register_t *fp, pc, rp;
50 #if 0
51 	bool kernel_only = true;
52 #endif
53 	bool trace_thread = false;
54 	bool lwpaddr = false;
55 	db_sym_t sym;
56 	db_expr_t off;
57 	const char *name;
58 	const char *cp = modif;
59 	char c;
60 
61 	if (count < 0)
62 		count = 65536;
63 
64 	while ((c = *cp++) != 0) {
65 		if (c == 'a') {
66 			lwpaddr = true;
67 			trace_thread = true;
68 		}
69 		if (c == 't')
70 			trace_thread = true;
71 #if 0
72 		if (c == 'u')
73 			kernel_only = false;
74 #endif
75 	}
76 
77 	if (!have_addr) {
78 		fp = (register_t *)ddb_regs.tf_r3;
79 		pc = ddb_regs.tf_iioq_head;
80 		rp = ddb_regs.tf_rp;
81 	} else {
82 		if (trace_thread) {
83 			proc_t p;
84 			lwp_t l;
85 			pid_t pid;
86 
87 			if (lwpaddr) {
88 				db_read_bytes(addr, sizeof(l), (char *)&l);
89 				db_read_bytes((db_addr_t)l.l_proc, sizeof(p),
90 				    (char *)&p);
91 				(*pr)("trace: pid %d ", p.p_pid);
92 			} else {
93 				proc_t *pp;
94 
95 				pid = (pid_t)addr;
96 				(*pr)("trace: pid %d ", pid);
97 				pp = db_proc_find(pid);
98 				if (pp == NULL) {
99 					(*pr)("not found\n");
100 					return;
101 				}
102 				db_read_bytes((db_addr_t)pp, sizeof(p),
103 				    (char *)&p);
104 				addr = (db_addr_t)p.p_lwps.lh_first;
105 				db_read_bytes(addr, sizeof(l), (char *)&l);
106 			}
107 			(*pr)("lid %d ", l.l_lid);
108 #ifdef _KERNEL
109 			if (l.l_proc == curproc && (lwp_t *)addr == curlwp) {
110 				fp = (int *)ddb_regs.tf_r3;
111 				pc = ddb_regs.tf_iioq_head;
112 				rp = ddb_regs.tf_rp;
113 			} else
114 #endif
115 			{
116 				struct pcb *pcb = lwp_getpcb(&l);
117 				register_t sp;
118 				/* cpu_switchto fp, and return point */
119 				db_read_bytes((db_addr_t)&pcb->pcb_ksp,
120 				    sizeof(sp), (char *)&sp);
121 				fp = (register_t *)(sp -
122 				    (HPPA_FRAME_SIZE + 16*4));
123 				pc = 0;
124 
125 				db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
126 				    (char *)&rp);
127 			}
128 			(*pr)("at %p\n", fp);
129 		} else {
130 			pc = 0;
131 			fp = (register_t *)addr;
132 			db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
133 			    (char *)&rp);
134 		}
135 	}
136 
137 	while (fp && count--) {
138 		register_t *newfp;
139 #ifdef DDB_DEBUG
140 		pr(">> %08x %08x %08x\t", fp, pc, rp);
141 #endif
142 
143 		if (USERMODE(pc))
144 			return;
145 
146 		if (pc) {
147 			sym = db_search_symbol(pc, DB_STGY_ANY, &off);
148 			db_symbol_values (sym, &name, NULL);
149 
150 			pr("%s() at ", name);
151 			db_printsym(pc, DB_STGY_PROC, pr);
152 			pr("\n");
153 		}
154 
155 		db_read_bytes((db_addr_t)&fp[0], sizeof(newfp), (char *)&newfp);
156 
157 		/*
158 		 * if a terminal frame then report the trapframe and continue
159 		 * after it (if not the last one).
160 		 */
161 		if (!newfp) {
162 			register_t scargs[5];
163 			struct trapframe tf, *ktf;
164 			int scoff;
165 
166 			/* Stack space for syscall args */
167 			scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE +
168 			    HPPA_FRAME_MAXARGS);
169 			ktf = (struct trapframe *)((char *)fp - scoff -
170 			    sizeof(tf));
171 
172 			db_read_bytes((db_addr_t)((char *)fp - scoff),
173 			     sizeof(scargs), (char *)&scargs);
174 			db_read_bytes((db_addr_t)ktf, sizeof(tf), (char *)&tf);
175 
176 			if (tf.tf_flags & TFF_SYS)
177 				pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n",
178 				    tf.tf_t1, scargs[1], scargs[2],
179 				    scargs[3], scargs[4], ktf);
180 			else
181 				pr("-- trap #%d (%p) %s\n", tf.tf_flags & 0x3f,
182 				    ktf, (tf.tf_flags & T_USER)? " from user" :
183 				    "");
184 
185 			if (!(tf.tf_flags & TFF_LAST)) {
186 				fp = (register_t *)tf.tf_r3;
187 				pc = tf.tf_iioq_head;
188 				rp = tf.tf_rp;
189 			} else {
190 				pc = 0;
191 				fp = 0;
192 			}
193 		} else {
194 			/* next frame */
195 			fp = newfp;
196 			pc = rp;
197 			db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
198 			    (char *)&rp);
199 		}
200 	}
201 
202 	if (count && pc) {
203 		db_printsym(pc, DB_STGY_XTRN, pr);
204 		pr(":\n");
205 	}
206 }
207