Annotation of sys/arch/sh/sh/db_trace.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_trace.c,v 1.4 2007/03/17 20:23:05 miod Exp $ */
2: /* $NetBSD: db_trace.c,v 1.19 2006/01/21 22:10:59 uwe Exp $ */
3:
4: /*-
5: * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
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 BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
30: #include <sys/param.h>
31: #include <sys/systm.h>
32:
33: #include <machine/db_machdep.h>
34:
35: #include <ddb/db_access.h>
36: #include <ddb/db_interface.h>
37: #include <ddb/db_output.h>
38: #include <ddb/db_sym.h>
39: #include <ddb/db_variables.h>
40:
41: #ifdef TRACE_DEBUG
42: # define DPRINTF printf
43: #else
44: # define DPRINTF while (/* CONSTCOND */ 0) printf
45: #endif
46:
47: extern char start[], etext[];
48: void db_nextframe(db_addr_t, db_addr_t *, db_addr_t *);
49:
50: struct db_variable db_regs[] = {
51: { "r0", (long *)&ddb_regs.tf_r0, FCN_NULL },
52: { "r1", (long *)&ddb_regs.tf_r1, FCN_NULL },
53: { "r2", (long *)&ddb_regs.tf_r2, FCN_NULL },
54: { "r3", (long *)&ddb_regs.tf_r3, FCN_NULL },
55: { "r4", (long *)&ddb_regs.tf_r4, FCN_NULL },
56: { "r5", (long *)&ddb_regs.tf_r5, FCN_NULL },
57: { "r6", (long *)&ddb_regs.tf_r6, FCN_NULL },
58: { "r7", (long *)&ddb_regs.tf_r7, FCN_NULL },
59: { "r8", (long *)&ddb_regs.tf_r8, FCN_NULL },
60: { "r9", (long *)&ddb_regs.tf_r9, FCN_NULL },
61: { "r10", (long *)&ddb_regs.tf_r10, FCN_NULL },
62: { "r11", (long *)&ddb_regs.tf_r11, FCN_NULL },
63: { "r12", (long *)&ddb_regs.tf_r12, FCN_NULL },
64: { "r13", (long *)&ddb_regs.tf_r13, FCN_NULL },
65: { "r14", (long *)&ddb_regs.tf_r14, FCN_NULL },
66: { "r15", (long *)&ddb_regs.tf_r15, FCN_NULL },
67: { "pr", (long *)&ddb_regs.tf_pr, FCN_NULL },
68: { "spc", (long *)&ddb_regs.tf_spc, FCN_NULL },
69: { "ssr", (long *)&ddb_regs.tf_ssr, FCN_NULL },
70: { "mach", (long *)&ddb_regs.tf_mach, FCN_NULL },
71: { "macl", (long *)&ddb_regs.tf_macl, FCN_NULL },
72: };
73:
74: struct db_variable *db_eregs =
75: db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
76:
77: void
78: db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count,
79: char *modif, int (*print)(const char *, ...))
80: {
81: db_addr_t callpc, frame, lastframe;
82: uint32_t vbr;
83:
84: __asm volatile("stc vbr, %0" : "=r"(vbr));
85:
86: frame = ddb_regs.tf_r14;
87: callpc = ddb_regs.tf_spc;
88:
89: if (count == 0 || count == -1)
90: count = INT_MAX;
91:
92: lastframe = 0;
93: while (count > 0 && frame != 0) {
94: /* Are we crossing a trap frame? */
95: if ((callpc & ~PAGE_MASK) == vbr) {
96: struct trapframe *tf = (void *)frame;
97:
98: frame = tf->tf_r14;
99: callpc = tf->tf_spc;
100:
101: (*print)("(EXPEVT %03x; SSR=%08x) at ",
102: tf->tf_expevt, tf->tf_ssr);
103: db_printsym(callpc, DB_STGY_PROC, print);
104: (*print)("\n");
105:
106: /* XXX: don't venture into the userland yet */
107: if ((tf->tf_ssr & PSL_MD) == 0)
108: break;
109: } else {
110: char *name;
111: db_expr_t offset;
112: db_sym_t sym;
113:
114:
115: DPRINTF(" (1)newpc 0x%lx, newfp 0x%lx\n",
116: callpc, frame);
117:
118: sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
119: db_symbol_values(sym, &name, NULL);
120:
121: (*print)("%s() at ", name ? name : "");
122: db_printsym(callpc, DB_STGY_PROC, print);
123: (*print)("\n");
124:
125: if (lastframe == 0 && offset == 0) {
126: callpc = ddb_regs.tf_pr;
127: continue;
128: }
129:
130: db_nextframe(callpc - offset, &frame, &callpc);
131: DPRINTF(" (2)newpc 0x%lx, newfp 0x%lx\n",
132: callpc, frame);
133:
134: if (callpc == 0 && lastframe == 0)
135: callpc = (db_addr_t)ddb_regs.tf_pr;
136: DPRINTF(" (3)newpc 0x%lx, newfp 0x%lx\n",
137: callpc, frame);
138: }
139:
140: count--;
141: lastframe = frame;
142: }
143: }
144:
145: void
146: db_nextframe(
147: db_addr_t pc, /* in: entry address of current function */
148: db_addr_t *fp, /* in: current fp, out: parent fp */
149: db_addr_t *pr) /* out: parent pr */
150: {
151: int *frame = (void *)*fp;
152: int i, inst;
153: int depth, prdepth, fpdepth;
154:
155: depth = 0;
156: prdepth = fpdepth = -1;
157:
158: if (pc < (db_addr_t)start || pc > (db_addr_t)etext)
159: goto out;
160:
161: for (i = 0; i < 30; i++) {
162: inst = db_get_value(pc, 2, FALSE);
163: pc += 2;
164:
165: if (inst == 0x6ef3) /* mov r15,r14 -- end of prologue */
166: break;
167:
168: if (inst == 0x4f22) { /* sts.l pr,@-r15 */
169: prdepth = depth;
170: depth++;
171: continue;
172: }
173: if (inst == 0x2fe6) { /* mov.l r14,@-r15 */
174: fpdepth = depth;
175: depth++;
176: continue;
177: }
178: if ((inst & 0xff0f) == 0x2f06) { /* mov.l r?,@-r15 */
179: depth++;
180: continue;
181: }
182: if ((inst & 0xff00) == 0x7f00) { /* add #n,r15 */
183: int8_t n = inst & 0xff;
184:
185: if (n >= 0) {
186: printf("add #n,r15 (n > 0)\n");
187: break;
188: }
189:
190: depth += -n/4;
191: continue;
192: }
193: if ((inst & 0xf000) == 0x9000) {
194: if (db_get_value(pc, 2, FALSE) == 0x3f38) {
195: /* "mov #n,r3; sub r3,r15" */
196: unsigned int disp = (int)(inst & 0xff);
197: int r3;
198:
199: r3 = db_get_value(pc + 4 - 2 + (disp << 1),
200: 2, FALSE);
201: if ((r3 & 0x00008000) == 0)
202: r3 &= 0x0000ffff;
203: else
204: r3 |= 0xffff0000;
205: depth += (r3 / 4);
206:
207: pc += 2;
208: continue;
209: }
210: }
211:
212: #ifdef TRACE_DEBUG
213: printf("unknown instruction in prologue\n");
214: db_disasm(pc - 2, 0);
215: #endif
216: }
217:
218: out:
219: #ifdef TRACE_DEBUG
220: printf("depth=%x fpdepth=0x%x prdepth=0x%x\n", depth, fpdepth, prdepth);
221: #endif
222: if (fpdepth != -1)
223: *fp = frame[depth - fpdepth - 1];
224: else
225: *fp = 0;
226:
227: if (prdepth != -1)
228: *pr = frame[depth - prdepth - 1];
229: else
230: *pr = 0;
231: }
CVSweb