1 /* $FreeBSD: releng/5.1/sys/powerpc/powerpc/db_trace.c 104435 2002-10-04 01:19:18Z grehan $ */
2 /* $NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */
3 /* $OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $ */
4
5 /*
6 * Mach Operating System
7 * Copyright (c) 1992 Carnegie Mellon University
8 * All Rights Reserved.
9 *
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/proc.h>
34 #include <sys/user.h>
35
36 #include <vm/vm.h>
37 #include <vm/pmap.h>
38 #include <vm/vm_extern.h>
39
40 #include <machine/db_machdep.h>
41 #include <machine/spr.h>
42 #include <machine/trap.h>
43
44 #include <ddb/ddb.h>
45 #include <ddb/db_access.h>
46 #include <ddb/db_sym.h>
47 #include <ddb/db_variables.h>
48
49 struct db_variable db_regs[] = {
50 { "r0", &ddb_regs.r[0], FCN_NULL },
51 { "r1", &ddb_regs.r[1], FCN_NULL },
52 { "r2", &ddb_regs.r[2], FCN_NULL },
53 { "r3", &ddb_regs.r[3], FCN_NULL },
54 { "r4", &ddb_regs.r[4], FCN_NULL },
55 { "r5", &ddb_regs.r[5], FCN_NULL },
56 { "r6", &ddb_regs.r[6], FCN_NULL },
57 { "r7", &ddb_regs.r[7], FCN_NULL },
58 { "r8", &ddb_regs.r[8], FCN_NULL },
59 { "r9", &ddb_regs.r[9], FCN_NULL },
60 { "r10", &ddb_regs.r[10], FCN_NULL },
61 { "r11", &ddb_regs.r[11], FCN_NULL },
62 { "r12", &ddb_regs.r[12], FCN_NULL },
63 { "r13", &ddb_regs.r[13], FCN_NULL },
64 { "r14", &ddb_regs.r[14], FCN_NULL },
65 { "r15", &ddb_regs.r[15], FCN_NULL },
66 { "r16", &ddb_regs.r[16], FCN_NULL },
67 { "r17", &ddb_regs.r[17], FCN_NULL },
68 { "r18", &ddb_regs.r[18], FCN_NULL },
69 { "r19", &ddb_regs.r[19], FCN_NULL },
70 { "r20", &ddb_regs.r[20], FCN_NULL },
71 { "r21", &ddb_regs.r[21], FCN_NULL },
72 { "r22", &ddb_regs.r[22], FCN_NULL },
73 { "r23", &ddb_regs.r[23], FCN_NULL },
74 { "r24", &ddb_regs.r[24], FCN_NULL },
75 { "r25", &ddb_regs.r[25], FCN_NULL },
76 { "r26", &ddb_regs.r[26], FCN_NULL },
77 { "r27", &ddb_regs.r[27], FCN_NULL },
78 { "r28", &ddb_regs.r[28], FCN_NULL },
79 { "r29", &ddb_regs.r[29], FCN_NULL },
80 { "r30", &ddb_regs.r[30], FCN_NULL },
81 { "r31", &ddb_regs.r[31], FCN_NULL },
82 { "iar", &ddb_regs.iar, FCN_NULL },
83 { "msr", &ddb_regs.msr, FCN_NULL },
84 { "lr", &ddb_regs.lr, FCN_NULL },
85 { "ctr", &ddb_regs.ctr, FCN_NULL },
86 { "cr", &ddb_regs.cr, FCN_NULL },
87 { "xer", &ddb_regs.xer, FCN_NULL },
88 #ifdef PPC_IBM4XX
89 { "dear", &ddb_regs.dear, FCN_NULL },
90 { "esr", &ddb_regs.esr, FCN_NULL },
91 { "pid", &ddb_regs.pid, FCN_NULL },
92 #endif
93 };
94 struct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]);
95
96 extern int trapexit[];
97 extern int end[];
98
99 /*
100 * Frame tracing.
101 */
102 static void
103 db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
104 char *modif, void (*pr)(const char *, ...))
105 {
106 db_addr_t frame, lr, caller, *args;
107 db_addr_t fakeframe[2];
108 db_expr_t diff;
109 c_db_sym_t sym;
110 const char *symname;
111 boolean_t kernel_only = TRUE;
112 boolean_t trace_thread = FALSE;
113 boolean_t full = FALSE;
114
115 {
116 register char *cp = modif;
117 register char c;
118
119 while ((c = *cp++) != 0) {
120 if (c == 't')
121 trace_thread = TRUE;
122 if (c == 'u')
123 kernel_only = FALSE;
124 if (c == 'f')
125 full = TRUE;
126 }
127 }
128
129 if (have_addr) {
130 #if 0
131 if (trace_thread) {
132 struct proc *p;
133 struct user *u;
134
135 (*pr)("trace: pid %d ", (int)addr);
136 p = pfind(addr);
137 if (p == NULL) {
138 (*pr)("not found\n");
139 return;
140 }
141 if (!(p->p_flag&P_INMEM)) {
142 (*pr)("swapped out\n");
143 return;
144 }
145 u = p->p_addr;
146 frame = (db_addr_t)u->u_pcb.pcb_sp;
147 (*pr)("at %p\n", frame);
148 } else
149 #endif
150 frame = (db_addr_t)addr;
151 } else {
152 frame = (db_addr_t)ddb_regs.r[1];
153 }
154 for (;;) {
155 if (frame < PAGE_SIZE)
156 break;
157 #ifdef PPC_MPC6XX
158 if (kernel_only &&
159 ((frame > (db_addr_t) end &&
160 frame < VM_MIN_KERNEL_ADDRESS) ||
161 frame >= VM_MAX_KERNEL_ADDRESS))
162 break;
163 #endif
164 frame = *(db_addr_t *)frame;
165 next_frame:
166 args = (db_addr_t *)(frame + 8);
167 if (frame < PAGE_SIZE)
168 break;
169 #ifdef PPC_MPC6XX
170 if (kernel_only &&
171 ((frame > (db_addr_t) end &&
172 frame < VM_MIN_KERNEL_ADDRESS) ||
173 frame >= VM_MAX_KERNEL_ADDRESS))
174 break;
175 #endif
176 if (count-- == 0)
177 break;
178
179 lr = *(db_addr_t *)(frame + 4) - 4;
180 if ((lr & 3) || (lr < 0x100)) {
181 (*pr)("saved LR(0x%x) is invalid.", lr);
182 break;
183 }
184 if ((caller = (db_addr_t)vtophys(lr)) == 0)
185 caller = lr;
186
187 if (frame != (db_addr_t) fakeframe) {
188 (*pr)("0x%08lx: ", frame);
189 } else {
190 (*pr)(" <?> : ");
191 }
192 if (caller + 4 == (db_addr_t) &trapexit) {
193 const char *trapstr;
194 struct trapframe *tf = (struct trapframe *) (frame+8);
195 (*pr)("%s ", tf->srr1 & PSL_PR ? "user" : "kernel");
196 switch (tf->exc) {
197 case EXC_DSI:
198 #ifdef PPC_MPC6XX
199 (*pr)("DSI %s trap @ %#x by ",
200 tf->dsisr & DSISR_STORE ? "write" : "read",
201 tf->dar);
202 #endif
203 #ifdef PPC_IBM4XX
204 (*pr)("DSI %s trap @ %#x by ",
205 tf->esr & ESR_DST ? "write" : "read",
206 tf->dear);
207 #endif
208 goto print_trap;
209 case EXC_ISI: trapstr = "ISI"; break;
210 case EXC_PGM: trapstr = "PGM"; break;
211 case EXC_SC: trapstr = "SC"; break;
212 case EXC_EXI: trapstr = "EXI"; break;
213 case EXC_MCHK: trapstr = "MCHK"; break;
214 case EXC_VEC: trapstr = "VEC"; break;
215 case EXC_FPU: trapstr = "FPU"; break;
216 case EXC_FPA: trapstr = "FPA"; break;
217 case EXC_DECR: trapstr = "DECR"; break;
218 case EXC_ALI: trapstr = "ALI"; break;
219 case EXC_BPT: trapstr = "BPT"; break;
220 case EXC_TRC: trapstr = "TRC"; break;
221 case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break;
222 case EXC_PERF: trapstr = "PERF"; break;
223 case EXC_SMI: trapstr = "SMI"; break;
224 case EXC_RST: trapstr = "RST"; break;
225 default: trapstr = NULL; break;
226 }
227 if (trapstr != NULL) {
228 (*pr)("%s trap by ", trapstr);
229 } else {
230 (*pr)("trap %#x by ", tf->exc);
231 }
232 print_trap:
233 lr = (db_addr_t) tf->srr0;
234 if ((caller = (db_addr_t)vtophys(lr)) == 0)
235 caller = lr;
236 diff = 0;
237 symname = NULL;
238 sym = db_search_symbol(caller, DB_STGY_ANY, &diff);
239 db_symbol_values(sym, &symname, 0);
240 if (symname == NULL || !strcmp(symname, "end")) {
241 (*pr)("%p: srr1=%#x\n", caller, tf->srr1);
242 } else {
243 (*pr)("%s+%x: srr1=%#x\n", symname, diff,
244 tf->srr1);
245 }
246 (*pr)("%-10s r1=%#x cr=%#x xer=%#x ctr=%#x",
247 "", tf->fixreg[1], tf->cr, tf->xer, tf->ctr);
248 #ifdef PPC_MPC6XX
249 if (tf->exc == EXC_DSI)
250 (*pr)(" dsisr=%#x", tf->dsisr);
251 #endif
252 #ifdef PPC_IBM4XX
253 if (tf->exc == EXC_DSI)
254 (*pr)(" dear=%#x", tf->dear);
255 (*pr)(" esr=%#x pid=%#x", tf->esr, tf->pid);
256 #endif
257 (*pr)("\n");
258 fakeframe[0] = (db_addr_t) tf->fixreg[1];
259 fakeframe[1] = (db_addr_t) tf->lr;
260 frame = (db_addr_t) fakeframe;
261 if (kernel_only && (tf->srr1 & PSL_PR))
262 break;
263 goto next_frame;
264 }
265
266 diff = 0;
267 symname = NULL;
268 sym = db_search_symbol(caller, DB_STGY_ANY, &diff);
269 db_symbol_values(sym, &symname, 0);
270 if (symname == NULL || !strcmp(symname, "end"))
271 (*pr)("at %p", caller);
272 else
273 (*pr)("at %s+%#x", symname, diff);
274 if (full)
275 /* Print all the args stored in that stackframe. */
276 (*pr)("(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)",
277 args[0], args[1], args[2], args[3],
278 args[4], args[5], args[6], args[7]);
279 (*pr)("\n");
280 }
281 }
282
283 void
284 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
285 char *modif)
286 {
287
288 db_stack_trace_print(addr, have_addr, count, modif, db_printf);
289 }
290
291 void
292 db_print_backtrace(void)
293 {
294 }
Cache object: bc310ff32c0ab7e1737eb106c492fefb
|