| 81 | #endif |
| 82 | |
| 83 | static void |
| 84 | stacktrace_subr(register_t pc, register_t sp, register_t ra) |
| 85 | { |
| 86 | InstFmt i; |
| 87 | /* |
| 88 | * Arrays for a0..a3 registers and flags if content |
| 89 | * of these registers is valid, e.g. obtained from the stack |
| 90 | */ |
| 91 | int valid_args[4]; |
| 92 | register_t args[4]; |
| 93 | register_t va, subr, cause, badvaddr; |
| 94 | unsigned instr, mask; |
| 95 | unsigned int frames = 0; |
| 96 | int more, stksize, j; |
| 97 | register_t next_ra; |
| 98 | bool trapframe; |
| 99 | |
| 100 | /* Jump here when done with a frame, to start a new one */ |
| 101 | loop: |
| 102 | |
| 103 | /* |
| 104 | * Invalidate arguments values |
| 105 | */ |
| 106 | valid_args[0] = 0; |
| 107 | valid_args[1] = 0; |
| 108 | valid_args[2] = 0; |
| 109 | valid_args[3] = 0; |
| 110 | next_ra = 0; |
| 111 | stksize = 0; |
| 112 | subr = 0; |
| 113 | trapframe = false; |
| 114 | if (frames++ > 100) { |
| 115 | db_printf("\nstackframe count exceeded\n"); |
| 116 | return; |
| 117 | } |
| 118 | |
| 119 | /* Check for bad SP: could foul up next frame. */ |
| 120 | if (!MIPS_IS_VALID_KERNELADDR(sp)) { |
| 121 | db_printf("SP 0x%jx: not in kernel\n", (uintmax_t)sp); |
| 122 | ra = 0; |
| 123 | subr = 0; |
| 124 | goto done; |
| 125 | } |
| 126 | #define Between(x, y, z) \ |
| 127 | ( ((x) <= (y)) && ((y) < (z)) ) |
| 128 | #define pcBetween(a,b) \ |
| 129 | Between((uintptr_t)a, pc, (uintptr_t)b) |
| 130 | |
| 131 | /* |
| 132 | * Check for current PC in exception handler code that don't have a |
| 133 | * preceding "j ra" at the tail of the preceding function. Depends |
| 134 | * on relative ordering of functions in exception.S, swtch.S. |
| 135 | */ |
| 136 | if (pcBetween(MipsKernGenException, MipsUserGenException)) { |
| 137 | subr = (uintptr_t)MipsKernGenException; |
| 138 | trapframe = true; |
| 139 | } else if (pcBetween(MipsUserGenException, MipsKernIntr)) |
| 140 | subr = (uintptr_t)MipsUserGenException; |
no test coverage detected