2 * Copyright (c) 2004-2005, Juniper Networks, Inc.
5 * JNPR: db_trace.c,v 1.8 2007/08/09 11:23:32 katta
11 #include <sys/param.h>
12 #include <sys/systm.h>
15 #include <sys/stack.h>
16 #include <sys/sysent.h>
18 #include <machine/db_machdep.h>
19 #include <machine/md_var.h>
20 #include <machine/mips_opcode.h>
21 #include <machine/pcb.h>
22 #include <machine/trap.h>
25 #include <ddb/db_sym.h>
27 extern char _locore[];
28 extern char _locoreEnd[];
32 * A function using a stack frame has the following instruction as the first
33 * one: [d]addiu sp,sp,-<frame_size>
35 * We make use of this to detect starting address of a function. This works
36 * better than using 'j ra' instruction to signify end of the previous
37 * function (for e.g. functions like boot() or panic() do not actually
38 * emit a 'j ra' instruction).
40 * XXX the abi does not require that the addiu instruction be the first one.
42 #define MIPS_START_OF_FUNCTION(ins) ((((ins) & 0xffff8000) == 0x27bd8000) \
43 || (((ins) & 0xffff8000) == 0x67bd8000))
46 * MIPS ABI 3.0 requires that all functions return using the 'j ra' instruction
48 * XXX gcc doesn't do this for functions with __noreturn__ attribute.
50 #define MIPS_END_OF_FUNCTION(ins) ((ins) == 0x03e00008)
52 #if defined(__mips_n64)
53 # define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
54 ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
56 # define MIPS_IS_VALID_KERNELADDR(reg) ((((reg) & 3) == 0) && \
57 ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
61 * Functions ``special'' enough to print by name
64 #define Name(_fn) { (void*)_fn, # _fn }
66 #define Name(_fn) { _fn, "_fn"}
74 Name(MipsKernGenException),
75 Name(MipsUserGenException),
85 * Map a function address to a string name, if known; or a hex string.
88 fn_name(uintptr_t addr)
99 sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
100 db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
101 if (symname && diff == 0)
104 for (i = 0; names[i].name; i++)
105 if (names[i].addr == (void *)addr)
106 return (names[i].name);
107 sprintf(buf, "%jx", (uintmax_t)addr);
112 stacktrace_subr(register_t pc, register_t sp, register_t ra,
113 int (*printfn) (const char *,...))
117 * Arrays for a0..a3 registers and flags if content
118 * of these registers is valid, e.g. obtained from the stack
123 unsigned instr, mask;
124 unsigned int frames = 0;
125 int more, stksize, j;
127 /* Jump here when done with a frame, to start a new one */
131 * Invalidate arguments values
137 /* Jump here after a nonstandard (interrupt handler) frame */
140 if (frames++ > 100) {
141 (*printfn) ("\nstackframe count exceeded\n");
142 /* return breaks stackframe-size heuristics with gcc -O2 */
143 goto finish; /* XXX */
145 /* check for bad SP: could foul up next frame */
146 /*XXX MIPS64 bad: this hard-coded SP is lame */
147 if (!MIPS_IS_VALID_KERNELADDR(sp)) {
148 (*printfn) ("SP 0x%jx: not in kernel\n", sp);
153 #define Between(x, y, z) \
154 ( ((x) <= (y)) && ((y) < (z)) )
155 #define pcBetween(a,b) \
156 Between((uintptr_t)a, pc, (uintptr_t)b)
159 * Check for current PC in exception handler code that don't have a
160 * preceding "j ra" at the tail of the preceding function. Depends
161 * on relative ordering of functions in exception.S, swtch.S.
163 if (pcBetween(MipsKernGenException, MipsUserGenException))
164 subr = (uintptr_t)MipsKernGenException;
165 else if (pcBetween(MipsUserGenException, MipsKernIntr))
166 subr = (uintptr_t)MipsUserGenException;
167 else if (pcBetween(MipsKernIntr, MipsUserIntr))
168 subr = (uintptr_t)MipsKernIntr;
169 else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
170 subr = (uintptr_t)MipsUserIntr;
171 else if (pcBetween(MipsTLBInvalidException, MipsTLBMissException))
172 subr = (uintptr_t)MipsTLBInvalidException;
173 else if (pcBetween(fork_trampoline, savectx))
174 subr = (uintptr_t)fork_trampoline;
175 else if (pcBetween(savectx, cpu_throw))
176 subr = (uintptr_t)savectx;
177 else if (pcBetween(cpu_throw, cpu_switch))
178 subr = (uintptr_t)cpu_throw;
179 else if (pcBetween(cpu_switch, MipsSwitchFPState))
180 subr = (uintptr_t)cpu_switch;
181 else if (pcBetween(_locore, _locoreEnd)) {
182 subr = (uintptr_t)_locore;
186 /* check for bad PC */
187 /*XXX MIPS64 bad: These hard coded constants are lame */
188 if (!MIPS_IS_VALID_KERNELADDR(pc)) {
189 (*printfn) ("PC 0x%jx: not in kernel\n", pc);
194 * Find the beginning of the current subroutine by scanning
195 * backwards from the current PC for the end of the previous
199 va = pc - sizeof(int);
201 instr = kdbpeek((int *)va);
203 if (MIPS_START_OF_FUNCTION(instr))
206 if (MIPS_END_OF_FUNCTION(instr)) {
207 /* skip over branch-delay slot instruction */
208 va += 2 * sizeof(int);
215 /* skip over nulls which might separate .o files */
216 while ((instr = kdbpeek((int *)va)) == 0)
220 /* scan forwards to find stack size and any saved registers */
224 for (va = subr; more; va += sizeof(int),
225 more = (more == 3) ? 3 : more - 1) {
226 /* stop if hit our current position */
229 instr = kdbpeek((int *)va);
231 switch (i.JType.op) {
233 switch (i.RType.func) {
236 more = 2; /* stop after next instruction */
241 more = 1; /* stop now */
252 more = 2; /* stop after next instruction */
259 switch (i.RType.rs) {
262 more = 2; /* stop after next instruction */
267 /* look for saved registers on the stack */
268 if (i.IType.rs != 29)
270 /* only restore the first one */
271 if (mask & (1 << i.IType.rt))
273 mask |= (1 << i.IType.rt);
274 switch (i.IType.rt) {
276 args[0] = kdbpeek((int *)(sp + (short)i.IType.imm));
281 args[1] = kdbpeek((int *)(sp + (short)i.IType.imm));
286 args[2] = kdbpeek((int *)(sp + (short)i.IType.imm));
291 args[3] = kdbpeek((int *)(sp + (short)i.IType.imm));
296 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
301 /* look for saved registers on the stack */
302 if (i.IType.rs != 29)
304 /* only restore the first one */
305 if (mask & (1 << i.IType.rt))
307 mask |= (1 << i.IType.rt);
308 switch (i.IType.rt) {
310 args[0] = kdbpeekd((int *)(sp + (short)i.IType.imm));
315 args[1] = kdbpeekd((int *)(sp + (short)i.IType.imm));
320 args[2] = kdbpeekd((int *)(sp + (short)i.IType.imm));
325 args[3] = kdbpeekd((int *)(sp + (short)i.IType.imm));
330 ra = kdbpeekd((int *)(sp + (short)i.IType.imm));
338 /* look for stack pointer adjustment */
339 if (i.IType.rs != 29 || i.IType.rt != 29)
341 stksize = -((short)i.IType.imm);
346 (*printfn) ("%s+%x (", fn_name(subr), pc - subr);
347 for (j = 0; j < 4; j ++) {
351 (*printfn)("%x", args[j]);
356 (*printfn) (") ra %jx sp %jx sz %d\n", ra, sp, stksize);
359 if (pc == ra && stksize == 0)
360 (*printfn) ("stacktrace: loop!\n");
370 (*printfn) ("pid %d\n", curproc->p_pid);
372 (*printfn) ("curproc NULL\n");
378 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
386 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
394 db_md_list_watchpoints()
401 db_trace_thread (curthread, -1);
406 db_trace_thread(struct thread *thr, int count)
408 register_t pc, ra, sp;
411 if (thr == curthread) {
412 sp = (register_t)(intptr_t)__builtin_frame_address(0);
413 ra = (register_t)(intptr_t)__builtin_return_address(0);
419 "move %0, $31\n" /* get ra */
420 "move $31, %1\n" /* restore ra */
425 ctx = kdb_thr_ctx(thr);
426 sp = (register_t)ctx->pcb_context[PCB_REG_SP];
427 pc = (register_t)ctx->pcb_context[PCB_REG_PC];
428 ra = (register_t)ctx->pcb_context[PCB_REG_RA];
431 stacktrace_subr(pc, sp, ra,
432 (int (*) (const char *, ...))db_printf);
438 db_show_mdpcpu(struct pcpu *pc)
441 db_printf("ipis = 0x%x\n", pc->pc_pending_ipis);
442 db_printf("next ASID = %d\n", pc->pc_next_asid);
443 db_printf("GENID = %d\n", pc->pc_asid_generation);