| 54 | #include <ddb/db_output.h> |
| 55 | |
| 56 | static void |
| 57 | db_stack_trace_cmd(struct unwind_state *state) |
| 58 | { |
| 59 | const char *name; |
| 60 | db_expr_t value; |
| 61 | db_expr_t offset; |
| 62 | c_db_sym_t sym; |
| 63 | u_int reg, i; |
| 64 | char *sep; |
| 65 | uint16_t upd_mask; |
| 66 | bool finished; |
| 67 | |
| 68 | finished = false; |
| 69 | while (!finished) { |
| 70 | finished = unwind_stack_one(state, 1); |
| 71 | |
| 72 | /* Print the frame details */ |
| 73 | sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset); |
| 74 | if (sym == C_DB_SYM_NULL) { |
| 75 | value = 0; |
| 76 | name = "(null)"; |
| 77 | } else |
| 78 | db_symbol_values(sym, &name, &value); |
| 79 | db_printf("%s() at ", name); |
| 80 | db_printsym(state->start_pc, DB_STGY_PROC); |
| 81 | db_printf("\n"); |
| 82 | db_printf("\t pc = 0x%08x lr = 0x%08x (", state->start_pc, |
| 83 | state->registers[LR]); |
| 84 | db_printsym(state->registers[LR], DB_STGY_PROC); |
| 85 | db_printf(")\n"); |
| 86 | db_printf("\t sp = 0x%08x fp = 0x%08x", |
| 87 | state->registers[SP], state->registers[FP]); |
| 88 | |
| 89 | /* Don't print the registers we have already printed */ |
| 90 | upd_mask = state->update_mask & |
| 91 | ~((1 << SP) | (1 << FP) | (1 << LR) | (1 << PC)); |
| 92 | sep = "\n\t"; |
| 93 | for (i = 0, reg = 0; upd_mask != 0; upd_mask >>= 1, reg++) { |
| 94 | if ((upd_mask & 1) != 0) { |
| 95 | db_printf("%s%sr%d = 0x%08x", sep, |
| 96 | (reg < 10) ? " " : "", reg, |
| 97 | state->registers[reg]); |
| 98 | i++; |
| 99 | if (i == 2) { |
| 100 | sep = "\n\t"; |
| 101 | i = 0; |
| 102 | } else |
| 103 | sep = " "; |
| 104 | } |
| 105 | } |
| 106 | db_printf("\n"); |
| 107 | |
| 108 | if (finished) |
| 109 | break; |
| 110 | |
| 111 | /* |
| 112 | * Stop if directed to do so, or if we've unwound back to the |
| 113 | * kernel entry point, or if the unwind function didn't change |
no test coverage detected