Annotation of sys/arch/alpha/alpha/db_trace.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_trace.c,v 1.14 2003/10/18 20:14:40 jmc Exp $ */
2:
3: /*
4: * Copyright (c) 1997 Niklas Hallqvist. All rights reserved.
5: * Copyright (c) 1997 Theo de Raadt. 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: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
29: #include <sys/param.h>
30: #include <sys/systm.h>
31:
32: #include <uvm/uvm_extern.h>
33:
34: #include <machine/db_machdep.h>
35: #include <machine/frame.h>
36:
37: #include <ddb/db_access.h>
38: #include <ddb/db_command.h>
39: #include <ddb/db_output.h>
40: #include <ddb/db_sym.h>
41: #include <ddb/db_variables.h>
42: #include <ddb/db_extern.h>
43: #include <ddb/db_interface.h>
44:
45: extern int etext;
46:
47: struct opcode opcode[] = {
48: { OPC_PAL, "call_pal", 0 }, /* 00 */
49: { OPC_RES, "opc01", 0 }, /* 01 */
50: { OPC_RES, "opc02", 0 }, /* 02 */
51: { OPC_RES, "opc03", 0 }, /* 03 */
52: { OPC_RES, "opc04", 0 }, /* 04 */
53: { OPC_RES, "opc05", 0 }, /* 05 */
54: { OPC_RES, "opc06", 0 }, /* 06 */
55: { OPC_RES, "opc07", 0 }, /* 07 */
56: { OPC_MEM, "lda", 1 }, /* 08 */
57: { OPC_MEM, "ldah", 1 }, /* 09 */
58: { OPC_RES, "opc0a", 0 }, /* 0A */
59: { OPC_MEM, "ldq_u", 1 }, /* 0B */
60: { OPC_RES, "opc0c", 0 }, /* 0C */
61: { OPC_RES, "opc0d", 0 }, /* 0D */
62: { OPC_RES, "opc0e", 0 }, /* 0E */
63: { OPC_MEM, "stq_u", 1 }, /* 0F */
64: { OPC_OP, "inta", 0 }, /* 10 */
65: { OPC_OP, "intl", 0 }, /* 11 */
66: { OPC_OP, "ints", 0 }, /* 12 */
67: { OPC_OP, "intm", 0 }, /* 13 */
68: { OPC_RES, "opc14", 0 }, /* 14 */
69: { OPC_OP, "fltv", 1 }, /* 15 */
70: { OPC_OP, "flti", 1 }, /* 16 */
71: { OPC_OP, "fltl", 1 }, /* 17 */
72: { OPC_MEM, "misc", 0 }, /* 18 */
73: { OPC_PAL, "pal19", 0 }, /* 19 */
74: { OPC_MEM, "jsr", 0 }, /* 1A */
75: { OPC_PAL, "pal1b", 0 }, /* 1B */
76: { OPC_RES, "opc1c", 0 }, /* 1C */
77: { OPC_PAL, "pal1d", 0 }, /* 1D */
78: { OPC_PAL, "pal1e", 0 }, /* 1E */
79: { OPC_PAL, "pal1f", 0 }, /* 1F */
80: { OPC_MEM, "ldf", 1 }, /* 20 */
81: { OPC_MEM, "ldg", 1 }, /* 21 */
82: { OPC_MEM, "lds", 1 }, /* 22 */
83: { OPC_MEM, "ldt", 1 }, /* 23 */
84: { OPC_MEM, "stf", 1 }, /* 24 */
85: { OPC_MEM, "stg", 1 }, /* 25 */
86: { OPC_MEM, "sts", 1 }, /* 26 */
87: { OPC_MEM, "stt", 1 }, /* 27 */
88: { OPC_MEM, "ldl", 1 }, /* 28 */
89: { OPC_MEM, "ldq", 1 }, /* 29 */
90: { OPC_MEM, "ldl_l", 1 }, /* 2A */
91: { OPC_MEM, "ldq_l", 1 }, /* 2B */
92: { OPC_MEM, "stl", 1 }, /* 2C */
93: { OPC_MEM, "stq", 1 }, /* 2D */
94: { OPC_MEM, "stl_c", 1 }, /* 2E */
95: { OPC_MEM, "stq_c", 1 }, /* 2F */
96: { OPC_BR, "br", 1 }, /* 30 */
97: { OPC_BR, "fbeq", 1 }, /* 31 */
98: { OPC_BR, "fblt", 1 }, /* 32 */
99: { OPC_BR, "fble", 1 }, /* 33 */
100: { OPC_BR, "bsr", 1 }, /* 34 */
101: { OPC_BR, "fbne", 1 }, /* 35 */
102: { OPC_BR, "fbge", 1 }, /* 36 */
103: { OPC_BR, "fbgt", 1 }, /* 37 */
104: { OPC_BR, "blbc", 1 }, /* 38 */
105: { OPC_BR, "beq", 1 }, /* 39 */
106: { OPC_BR, "blt", 1 }, /* 3A */
107: { OPC_BR, "ble", 1 }, /* 3B */
108: { OPC_BR, "blbs", 1 }, /* 3C */
109: { OPC_BR, "bne", 1 }, /* 3D */
110: { OPC_BR, "bge", 1 }, /* 3E */
111: { OPC_BR, "bgt", 1 }, /* 3F */
112: };
113:
114: static __inline int sext(u_int);
115: static __inline int rega(u_int);
116: static __inline int regb(u_int);
117: static __inline int regc(u_int);
118: static __inline int disp(u_int);
119:
120: static __inline int
121: sext(x)
122: u_int x;
123: {
124: return ((x & 0x8000) ? -(-x & 0xffff) : (x & 0xffff));
125: }
126:
127: static __inline int
128: rega(x)
129: u_int x;
130: {
131: return ((x >> 21) & 0x1f);
132: }
133:
134: static __inline int
135: regb(x)
136: u_int x;
137: {
138: return ((x >> 16) & 0x1f);
139: }
140:
141: static __inline int
142: regc(x)
143: u_int x;
144: {
145: return (x & 0x1f);
146: }
147:
148: static __inline int
149: disp(x)
150: u_int x;
151: {
152: return (sext(x & 0xffff));
153: }
154:
155: /*
156: * XXX There are a couple of problems with this code:
157: *
158: * The argument list printout code is likely to get confused.
159: *
160: * It relies on the conventions of gcc code generation.
161: *
162: * It uses heuristics to calculate the framesize, and might get it wrong.
163: *
164: * It doesn't yet use the framepointer if available.
165: *
166: * The address argument can only be used for pointing at trapframes
167: * since a frame pointer of its own serves no good on the alpha,
168: * you need a pc value too.
169: *
170: * The heuristics used for tracing through a trap relies on having
171: * symbols available.
172: */
173: void
174: db_stack_trace_print(addr, have_addr, count, modif, pr)
175: db_expr_t addr;
176: int have_addr;
177: db_expr_t count;
178: char *modif;
179: int (*pr)(const char *, ...);
180: {
181: u_long *frame;
182: int i, framesize;
183: db_addr_t pc, ra;
184: u_int inst;
185: char *name;
186: db_expr_t offset;
187: db_regs_t *regs;
188: u_long *slot[32];
189:
190: bzero(slot, sizeof(slot));
191: if (count == -1)
192: count = 65535;
193:
194: if (have_addr) {
195: (*pr)("alpha trace requires a trap frame... giving up.\n");
196: return;
197: }
198: regs = DDB_REGS;
199: trapframe:
200: /* remember where various registers are stored */
201: for (i = 0; i < 31; i++)
202: slot[i] = ®s->tf_regs[0] +
203: ((u_long *)db_regs[i].valuep - &ddb_regs.tf_regs[0]);
204: frame = (u_long *)regs->tf_regs[FRAME_SP];
205: pc = (db_addr_t)regs->tf_regs[FRAME_PC];
206: ra = (db_addr_t)regs->tf_regs[FRAME_RA];
207:
208: while (count-- && pc >= (db_addr_t)KERNBASE && pc < (db_addr_t)&etext) {
209: db_find_sym_and_offset(pc, &name, &offset);
210: if (!name) {
211: name = "?";
212: /* Limit the search for procedure start */
213: offset = 65536;
214: }
215: (*pr)("%s(", name);
216:
217: framesize = 0;
218: for (i = sizeof (int); i <= offset; i += sizeof (int)) {
219: inst = *(u_int *)(pc - i);
220:
221: /*
222: * If by chance we don't have any symbols we have to
223: * get out somehow anyway. Check for the preceding
224: * procedure return in that case.
225: */
226: if (name[0] == '?' && inst_return(inst))
227: break;
228:
229: /*
230: * Disassemble to get the needed info for the frame.
231: */
232: if ((inst & 0xffff0000) == 0x23de0000)
233: /* lda sp,n(sp) */
234: framesize -= disp(inst) / sizeof (u_long);
235: else if ((inst & 0xfc1f0000) == 0xb41e0000)
236: /* stq X,n(sp) */
237: slot[rega(inst)] =
238: frame + disp(inst) / sizeof (u_long);
239: else if ((inst & 0xfc000fe0) == 0x44000400 &&
240: rega(inst) == regb(inst)) {
241: /* bis X,X,Y (aka mov X,Y) */
242: /* zero is hardwired */
243: if (rega(inst) != 31)
244: slot[rega(inst)] = slot[regc(inst)];
245: slot[regc(inst)] = 0;
246: /*
247: * XXX In here we might special case a frame
248: * pointer setup, i.e. mov sp, fp.
249: */
250: } else if (inst_load(inst))
251: /* clobbers a register */
252: slot[rega(inst)] = 0;
253: else if (opcode[inst >> 26].opc_fmt == OPC_OP)
254: /* clobbers a register */
255: slot[regc(inst)] = 0;
256: /*
257: * XXX Recognize more reg clobbering instructions and
258: * set slot[reg] = 0 then too.
259: */
260: }
261:
262: /*
263: * Try to print the 6 quads that might hold the args.
264: * We print 6 of them even if there are fewer, cause we don't
265: * know the number. Maybe we could skip the last ones
266: * that never got used. If we cannot know the value, print
267: * a question mark.
268: */
269: for (i = 0; i < 6; i++) {
270: if (i > 0)
271: (*pr)(", ");
272: if (slot[16 + i])
273: (*pr)("%lx", *slot[16 + i]);
274: else
275: (*pr)("?");
276: }
277:
278: #if 0
279: /*
280: * XXX This will go eventually when I trust the argument
281: * printout heuristics.
282: *
283: * Print the stack frame contents.
284: */
285: (*pr)(") [%p: ", frame);
286: if (framesize > 1) {
287: for (i = 0; i < framesize - 1; i++)
288: (*pr)("%lx, ", frame[i]);
289: (*pr)("%lx", frame[i]);
290: }
291: (*pr)("] at ");
292: #else
293: (*pr)(") at ");
294: #endif
295: db_printsym(pc, DB_STGY_PROC, pr);
296: (*pr)("\n");
297:
298: /*
299: * If we are looking at a Xent* routine we are in a trap
300: * context.
301: */
302: if (strncmp(name, "Xent", sizeof("Xent") - 1) == 0) {
303: regs = (db_regs_t *)frame;
304: goto trapframe;
305: }
306:
307: /* Look for the return address if recorded. */
308: if (slot[26])
309: ra = *(db_addr_t *)slot[26];
310: else
311: break;
312:
313: /* Advance to the next frame. */
314: frame += framesize;
315: pc = ra;
316: }
317: }
CVSweb