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