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