| 101 | } |
| 102 | |
| 103 | void OnCrash(int signo, siginfo_t const *si, const ucontext *uc) |
| 104 | { |
| 105 | if (!g_CrashDumpEnabled) |
| 106 | return; |
| 107 | |
| 108 | fflush(stdout); |
| 109 | fflush(stderr); |
| 110 | |
| 111 | if (unw_init_local) |
| 112 | { |
| 113 | // Found out by manual inspection of libunwind source code |
| 114 | // |
| 115 | // libcorkscrew has the convenient function _signal_arch where it can step |
| 116 | // into the stack frames from where the signal was triggered. Here, just |
| 117 | // build a context with information taken from the signal info. |
| 118 | unw_context_t ctx; |
| 119 | ctx.reg[0] = uc->uc_mcontext.arm_r0; |
| 120 | ctx.reg[1] = uc->uc_mcontext.arm_r1; |
| 121 | ctx.reg[2] = uc->uc_mcontext.arm_r2; |
| 122 | ctx.reg[3] = uc->uc_mcontext.arm_r3; |
| 123 | ctx.reg[4] = uc->uc_mcontext.arm_r4; |
| 124 | ctx.reg[5] = uc->uc_mcontext.arm_r5; |
| 125 | ctx.reg[6] = uc->uc_mcontext.arm_r6; |
| 126 | ctx.reg[7] = uc->uc_mcontext.arm_r7; |
| 127 | ctx.reg[8] = uc->uc_mcontext.arm_r8; |
| 128 | ctx.reg[9] = uc->uc_mcontext.arm_r9; |
| 129 | ctx.reg[10] = uc->uc_mcontext.arm_r10; |
| 130 | ctx.reg[11] = uc->uc_mcontext.arm_fp; |
| 131 | ctx.reg[12] = uc->uc_mcontext.arm_ip; |
| 132 | ctx.reg[13] = uc->uc_mcontext.arm_sp; |
| 133 | ctx.reg[14] = uc->uc_mcontext.arm_lr; |
| 134 | ctx.reg[15] = uc->uc_mcontext.arm_pc; |
| 135 | |
| 136 | unw_init_local(&s_cursor, &ctx); |
| 137 | g_AppState.m_PtrCount = 0; |
| 138 | while (g_AppState.m_PtrCount < AppState::PTRS_MAX) |
| 139 | { |
| 140 | // Reg number, see the 'white lie' in libunwind-arm.h in libunwind. Simulating passing |
| 141 | // in a request for the program counter. Bit confusing, but works. |
| 142 | unw_get_reg(&s_cursor, 14, (unw_word_t*) &g_AppState.m_Ptr[g_AppState.m_PtrCount++]); |
| 143 | if (!unw_step(&s_cursor)) |
| 144 | break; |
| 145 | } |
| 146 | } |
| 147 | else if (unwind_backtrace_signal_arch) |
| 148 | { |
| 149 | void *map = acquire_my_map_info_list(); |
| 150 | ssize_t count = unwind_backtrace_signal_arch((void*)si, (void*)uc, map, &s_CorkscrewFrames[0], 0, AppState::PTRS_MAX); |
| 151 | if (count > 0) |
| 152 | { |
| 153 | for (ssize_t i=0;i<count;i++) |
| 154 | { |
| 155 | g_AppState.m_Ptr[i] = (void*)s_CorkscrewFrames[i].absolute_pc; |
| 156 | } |
| 157 | g_AppState.m_PtrCount = count; |
| 158 | } |
| 159 | release_my_map_info_list(map); |
| 160 | } |
no test coverage detected