如果你想使用_Unwind_Context()
,可以像这样做(代码是特定于32位ARM的):
struct BacktraceState {
const ucontext_t* signal_ucontext;
size_t address_count = 0;
static const size_t address_count_max = 30;
uintptr_t addresses[address_count_max] = {};
BacktraceState(const ucontext_t* ucontext) : signal_ucontext(ucontext) {}
bool AddAddress(uintptr_t ip) {
if (address_count >= address_count_max)
return false;
const uintptr_t thumb_bit = 1;
ip &= ~thumb_bit;
if (ip == 0)
return true;
if (address_count > 0 && ip == addresses[address_count - 1])
return true;
addresses[address_count++] = ip;
return true;
}
};
void ProcessRegisters(
_Unwind_Context* unwind_context, BacktraceState* state) {
assert(state);
assert(unwind_context);
const ucontext_t* signal_ucontext = state->signal_ucontext;
assert(signal_ucontext);
const sigcontext* signal_mcontext = &(signal_ucontext->uc_mcontext);
assert(signal_mcontext);
_Unwind_SetGR(unwind_context, REG_R0, signal_mcontext->arm_r0);
_Unwind_SetGR(unwind_context, REG_R1, signal_mcontext->arm_r1);
_Unwind_SetGR(unwind_context, REG_R2, signal_mcontext->arm_r2);
_Unwind_SetGR(unwind_context, REG_R3, signal_mcontext->arm_r3);
_Unwind_SetGR(unwind_context, REG_R4, signal_mcontext->arm_r4);
_Unwind_SetGR(unwind_context, REG_R5, signal_mcontext->arm_r5);
_Unwind_SetGR(unwind_context, REG_R6, signal_mcontext->arm_r6);
_Unwind_SetGR(unwind_context, REG_R7, signal_mcontext->arm_r7);
_Unwind_SetGR(unwind_context, REG_R8, signal_mcontext->arm_r8);
_Unwind_SetGR(unwind_context, REG_R9, signal_mcontext->arm_r9);
_Unwind_SetGR(unwind_context, REG_R10, signal_mcontext->arm_r10);
_Unwind_SetGR(unwind_context, REG_R11, signal_mcontext->arm_fp);
_Unwind_SetGR(unwind_context, REG_R12, signal_mcontext->arm_ip);
_Unwind_SetGR(unwind_context, REG_R13, signal_mcontext->arm_sp);
_Unwind_SetGR(unwind_context, REG_R14, signal_mcontext->arm_lr);
_Unwind_SetGR(unwind_context, REG_R15, signal_mcontext->arm_pc);
state->AddAddress(signal_mcontext->arm_pc);
#if __clang__
state->AddAddress(signal_mcontext->arm_lr);
#endif
}
_Unwind_Reason_Code UnwindBacktraceCallback(
struct _Unwind_Context* unwind_context, void* state_voidp) {
assert(unwind_context);
assert(state_voidp);
BacktraceState* state = (BacktraceState*)state_voidp;
assert(state);
if (state->address_count == 0) {
ProcessRegisters(unwind_context, state);
return _URC_NO_REASON;
}
uintptr_t ip = _Unwind_GetIP(unwind_context);
bool ok = state->AddAddress(ip);
if (!ok)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
void CaptureBacktrace(BacktraceState* state) {
assert(state);
_Unwind_Backtrace(UnwindBacktraceCallback, state);
}
void SigActionHandler(int sig, siginfo_t* info, void* ucontext) {
const ucontext_t* signal_ucontext = (const ucontext_t*)ucontext;
assert(signal_ucontext);
BacktraceState backtrace_state(signal_ucontext);
CaptureBacktrace(&backtrace_state);
}
但我建议您不要使用
_Unwind_Context()
,而是使用预编译的
libunwind
来针对32位ARM进行操作,这个库已经随现代Android NDK捆绑在一起(在
sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a
中),并且可以与所有LLVM一起使用。您将需要使用libc++(LLVM STL)。如何做到这一点,在我的答案中有演示,您需要结合这里的示例。
https://dev59.com/bGsz5IYBdhLWcg3wFUG_#50027799
如果您使用libstdc++(GNU STL),则可以使用Dar Hoo的解决方案:
https://dev59.com/42025IYBdhLWcg3wChOc#48593413
unw_set_reg
而不是_Unwind_SetGR
,它们有什么不同?谢谢! - rogerdpack