]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/mips/mips/db_trace.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / mips / mips / db_trace.c
1 /*-
2  * Copyright (c) 2004-2005, Juniper Networks, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      JNPR: db_trace.c,v 1.8 2007/08/09 11:23:32 katta
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kdb.h>
35 #include <sys/proc.h>
36 #include <sys/stack.h>
37 #include <sys/sysent.h>
38
39 #include <machine/db_machdep.h>
40 #include <machine/md_var.h>
41 #include <machine/mips_opcode.h>
42 #include <machine/pcb.h>
43 #include <machine/trap.h>
44
45 #include <ddb/ddb.h>
46 #include <ddb/db_sym.h>
47
48 extern char _locore[];
49 extern char _locoreEnd[];
50 extern char edata[];
51
52 /*
53  * A function using a stack frame has the following instruction as the first
54  * one: [d]addiu sp,sp,-<frame_size>
55  *
56  * We make use of this to detect starting address of a function. This works
57  * better than using 'j ra' instruction to signify end of the previous
58  * function (for e.g. functions like boot() or panic() do not actually
59  * emit a 'j ra' instruction).
60  *
61  * XXX the abi does not require that the addiu instruction be the first one.
62  */
63 #define MIPS_START_OF_FUNCTION(ins)     ((((ins) & 0xffff8000) == 0x27bd8000) \
64         || (((ins) & 0xffff8000) == 0x67bd8000))
65
66 /*
67  * MIPS ABI 3.0 requires that all functions return using the 'j ra' instruction
68  *
69  * XXX gcc doesn't do this for functions with __noreturn__ attribute.
70  */
71 #define MIPS_END_OF_FUNCTION(ins)       ((ins) == 0x03e00008)
72
73 #if defined(__mips_n64)
74 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
75                                         ((vm_offset_t)(reg) >= MIPS_XKPHYS_START))
76 #else
77 #       define  MIPS_IS_VALID_KERNELADDR(reg)   ((((reg) & 3) == 0) && \
78                                         ((vm_offset_t)(reg) >= MIPS_KSEG0_START))
79 #endif
80
81 /*
82  * Functions ``special'' enough to print by name
83  */
84 #ifdef __STDC__
85 #define Name(_fn)  { (void*)_fn, # _fn }
86 #else
87 #define Name(_fn) { _fn, "_fn"}
88 #endif
89 static struct {
90         void *addr;
91         char *name;
92 }      names[] = {
93
94         Name(trap),
95         Name(MipsKernGenException),
96         Name(MipsUserGenException),
97         Name(MipsKernIntr),
98         Name(MipsUserIntr),
99         Name(cpu_switch),
100         {
101                 0, 0
102         }
103 };
104
105 /*
106  * Map a function address to a string name, if known; or a hex string.
107  */
108 static char *
109 fn_name(uintptr_t addr)
110 {
111         static char buf[17];
112         int i = 0;
113
114         db_expr_t diff;
115         c_db_sym_t sym;
116         char *symname;
117
118         diff = 0;
119         symname = NULL;
120         sym = db_search_symbol((db_addr_t)addr, DB_STGY_ANY, &diff);
121         db_symbol_values(sym, (const char **)&symname, (db_expr_t *)0);
122         if (symname && diff == 0)
123                 return (symname);
124
125         for (i = 0; names[i].name; i++)
126                 if (names[i].addr == (void *)addr)
127                         return (names[i].name);
128         sprintf(buf, "%jx", (uintmax_t)addr);
129         return (buf);
130 }
131
132 void
133 stacktrace_subr(register_t pc, register_t sp, register_t ra,
134         int (*printfn) (const char *,...))
135 {
136         InstFmt i;
137         /*
138          * Arrays for a0..a3 registers and flags if content
139          * of these registers is valid, e.g. obtained from the stack
140          */
141         int valid_args[4];
142         uintptr_t args[4];
143         uintptr_t va, subr;
144         unsigned instr, mask;
145         unsigned int frames = 0;
146         int more, stksize, j;
147
148 /* Jump here when done with a frame, to start a new one */
149 loop:
150
151         /*
152          * Invalidate arguments values
153          */
154         valid_args[0] = 0;
155         valid_args[1] = 0;
156         valid_args[2] = 0;
157         valid_args[3] = 0;
158 /* Jump here after a nonstandard (interrupt handler) frame */
159         stksize = 0;
160         subr = 0;
161         if (frames++ > 100) {
162                 (*printfn) ("\nstackframe count exceeded\n");
163                 /* return breaks stackframe-size heuristics with gcc -O2 */
164                 goto finish;    /* XXX */
165         }
166         /* check for bad SP: could foul up next frame */
167         /*XXX MIPS64 bad: this hard-coded SP is lame */
168         if (!MIPS_IS_VALID_KERNELADDR(sp)) {
169                 (*printfn) ("SP 0x%jx: not in kernel\n", sp);
170                 ra = 0;
171                 subr = 0;
172                 goto done;
173         }
174 #define Between(x, y, z) \
175                 ( ((x) <= (y)) && ((y) < (z)) )
176 #define pcBetween(a,b) \
177                 Between((uintptr_t)a, pc, (uintptr_t)b)
178
179         /*
180          * Check for current PC in  exception handler code that don't have a
181          * preceding "j ra" at the tail of the preceding function. Depends
182          * on relative ordering of functions in exception.S, swtch.S.
183          */
184         if (pcBetween(MipsKernGenException, MipsUserGenException))
185                 subr = (uintptr_t)MipsKernGenException;
186         else if (pcBetween(MipsUserGenException, MipsKernIntr))
187                 subr = (uintptr_t)MipsUserGenException;
188         else if (pcBetween(MipsKernIntr, MipsUserIntr))
189                 subr = (uintptr_t)MipsKernIntr;
190         else if (pcBetween(MipsUserIntr, MipsTLBInvalidException))
191                 subr = (uintptr_t)MipsUserIntr;
192         else if (pcBetween(MipsTLBInvalidException, MipsTLBMissException))
193                 subr = (uintptr_t)MipsTLBInvalidException;
194         else if (pcBetween(fork_trampoline, savectx))
195                 subr = (uintptr_t)fork_trampoline;
196         else if (pcBetween(savectx, cpu_throw))
197                 subr = (uintptr_t)savectx;
198         else if (pcBetween(cpu_throw, cpu_switch))
199                 subr = (uintptr_t)cpu_throw;
200         else if (pcBetween(cpu_switch, MipsSwitchFPState))
201                 subr = (uintptr_t)cpu_switch;
202         else if (pcBetween(_locore, _locoreEnd)) {
203                 subr = (uintptr_t)_locore;
204                 ra = 0;
205                 goto done;
206         }
207         /* check for bad PC */
208         /*XXX MIPS64 bad: These hard coded constants are lame */
209         if (!MIPS_IS_VALID_KERNELADDR(pc)) {
210                 (*printfn) ("PC 0x%jx: not in kernel\n", pc);
211                 ra = 0;
212                 goto done;
213         }
214         /*
215          * Find the beginning of the current subroutine by scanning
216          * backwards from the current PC for the end of the previous
217          * subroutine.
218          */
219         if (!subr) {
220                 va = pc - sizeof(int);
221                 while (1) {
222                         instr = kdbpeek((int *)va);
223
224                         if (MIPS_START_OF_FUNCTION(instr))
225                                 break;
226
227                         if (MIPS_END_OF_FUNCTION(instr)) {
228                                 /* skip over branch-delay slot instruction */
229                                 va += 2 * sizeof(int);
230                                 break;
231                         }
232
233                         va -= sizeof(int);
234                 }
235
236                 /* skip over nulls which might separate .o files */
237                 while ((instr = kdbpeek((int *)va)) == 0)
238                         va += sizeof(int);
239                 subr = va;
240         }
241         /* scan forwards to find stack size and any saved registers */
242         stksize = 0;
243         more = 3;
244         mask = 0;
245         for (va = subr; more; va += sizeof(int),
246             more = (more == 3) ? 3 : more - 1) {
247                 /* stop if hit our current position */
248                 if (va >= pc)
249                         break;
250                 instr = kdbpeek((int *)va);
251                 i.word = instr;
252                 switch (i.JType.op) {
253                 case OP_SPECIAL:
254                         switch (i.RType.func) {
255                         case OP_JR:
256                         case OP_JALR:
257                                 more = 2;       /* stop after next instruction */
258                                 break;
259
260                         case OP_SYSCALL:
261                         case OP_BREAK:
262                                 more = 1;       /* stop now */
263                         };
264                         break;
265
266                 case OP_BCOND:
267                 case OP_J:
268                 case OP_JAL:
269                 case OP_BEQ:
270                 case OP_BNE:
271                 case OP_BLEZ:
272                 case OP_BGTZ:
273                         more = 2;       /* stop after next instruction */
274                         break;
275
276                 case OP_COP0:
277                 case OP_COP1:
278                 case OP_COP2:
279                 case OP_COP3:
280                         switch (i.RType.rs) {
281                         case OP_BCx:
282                         case OP_BCy:
283                                 more = 2;       /* stop after next instruction */
284                         };
285                         break;
286
287                 case OP_SW:
288                         /* look for saved registers on the stack */
289                         if (i.IType.rs != 29)
290                                 break;
291                         /* only restore the first one */
292                         if (mask & (1 << i.IType.rt))
293                                 break;
294                         mask |= (1 << i.IType.rt);
295                         switch (i.IType.rt) {
296                         case 4:/* a0 */
297                                 args[0] = kdbpeek((int *)(sp + (short)i.IType.imm));
298                                 valid_args[0] = 1;
299                                 break;
300
301                         case 5:/* a1 */
302                                 args[1] = kdbpeek((int *)(sp + (short)i.IType.imm));
303                                 valid_args[1] = 1;
304                                 break;
305
306                         case 6:/* a2 */
307                                 args[2] = kdbpeek((int *)(sp + (short)i.IType.imm));
308                                 valid_args[2] = 1;
309                                 break;
310
311                         case 7:/* a3 */
312                                 args[3] = kdbpeek((int *)(sp + (short)i.IType.imm));
313                                 valid_args[3] = 1;
314                                 break;
315
316                         case 31:        /* ra */
317                                 ra = kdbpeek((int *)(sp + (short)i.IType.imm));
318                         }
319                         break;
320
321                 case OP_SD:
322                         /* look for saved registers on the stack */
323                         if (i.IType.rs != 29)
324                                 break;
325                         /* only restore the first one */
326                         if (mask & (1 << i.IType.rt))
327                                 break;
328                         mask |= (1 << i.IType.rt);
329                         switch (i.IType.rt) {
330                         case 4:/* a0 */
331                                 args[0] = kdbpeekd((int *)(sp + (short)i.IType.imm));
332                                 valid_args[0] = 1;
333                                 break;
334
335                         case 5:/* a1 */
336                                 args[1] = kdbpeekd((int *)(sp + (short)i.IType.imm));
337                                 valid_args[1] = 1;
338                                 break;
339
340                         case 6:/* a2 */
341                                 args[2] = kdbpeekd((int *)(sp + (short)i.IType.imm));
342                                 valid_args[2] = 1;
343                                 break;
344
345                         case 7:/* a3 */
346                                 args[3] = kdbpeekd((int *)(sp + (short)i.IType.imm));
347                                 valid_args[3] = 1;
348                                 break;
349
350                         case 31:        /* ra */
351                                 ra = kdbpeekd((int *)(sp + (short)i.IType.imm));
352                         }
353                         break;
354
355                 case OP_ADDI:
356                 case OP_ADDIU:
357                 case OP_DADDI:
358                 case OP_DADDIU:
359                         /* look for stack pointer adjustment */
360                         if (i.IType.rs != 29 || i.IType.rt != 29)
361                                 break;
362                         stksize = -((short)i.IType.imm);
363                 }
364         }
365
366 done:
367         (*printfn) ("%s+%x (", fn_name(subr), pc - subr);
368         for (j = 0; j < 4; j ++) {
369                 if (j > 0)
370                         (*printfn)(",");
371                 if (valid_args[j])
372                         (*printfn)("%x", args[j]);
373                 else
374                         (*printfn)("?");
375         }
376
377         (*printfn) (") ra %jx sp %jx sz %d\n", ra, sp, stksize);
378
379         if (ra) {
380                 if (pc == ra && stksize == 0)
381                         (*printfn) ("stacktrace: loop!\n");
382                 else {
383                         pc = ra;
384                         sp += stksize;
385                         ra = 0;
386                         goto loop;
387                 }
388         } else {
389 finish:
390                 if (curproc)
391                         (*printfn) ("pid %d\n", curproc->p_pid);
392                 else
393                         (*printfn) ("curproc NULL\n");
394         }
395 }
396
397
398 int
399 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
400 {
401
402         return(0);
403 }
404
405
406 int
407 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
408 {
409
410         return(0);
411 }
412
413
414 void
415 db_md_list_watchpoints()
416 {
417 }
418
419 void
420 db_trace_self(void)
421 {
422         db_trace_thread (curthread, -1);
423         return;
424 }
425
426 int
427 db_trace_thread(struct thread *thr, int count)
428 {
429         register_t pc, ra, sp;
430         struct pcb *ctx;
431
432         if (thr == curthread) {
433                 sp = (register_t)(intptr_t)__builtin_frame_address(0);
434                 ra = (register_t)(intptr_t)__builtin_return_address(0);
435
436                 __asm __volatile(
437                         "jal 99f\n"
438                         "nop\n"
439                         "99:\n"
440                          "move %0, $31\n" /* get ra */
441                          "move $31, %1\n" /* restore ra */
442                          : "=r" (pc)
443                          : "r" (ra));
444
445         } else {
446                 ctx = kdb_thr_ctx(thr);
447                 sp = (register_t)ctx->pcb_context[PCB_REG_SP];
448                 pc = (register_t)ctx->pcb_context[PCB_REG_PC];
449                 ra = (register_t)ctx->pcb_context[PCB_REG_RA];
450         }
451
452         stacktrace_subr(pc, sp, ra,
453             (int (*) (const char *, ...))db_printf);
454
455         return (0);
456 }
457
458 void
459 db_show_mdpcpu(struct pcpu *pc)
460 {
461
462         db_printf("ipis         = 0x%x\n", pc->pc_pending_ipis);
463         db_printf("next ASID    = %d\n", pc->pc_next_asid);
464         db_printf("GENID        = %d\n", pc->pc_asid_generation);
465         return;
466 }