Code example
#include <stdio.h> #include <unwind.h> #include <stdint.h> #include <signal.h> struct sigaction act_old; static _Unwind_Reason_Code unwind_backtrace_callback(struct _Unwind_Context* context, void* arg) { uintptr_t pc = _Unwind_GetIP(context); if (pc) { printf("unwind got pc ...0x%x\n", pc); } return _URC_NO_REASON; } ssize_t unwind_backtrace() { _Unwind_Reason_Code rc = _Unwind_Backtrace(unwind_backtrace_callback, 0); return rc == _URC_END_OF_STACK ? 0 : -1; } void func_1() { int ret = unwind_backtrace(); printf("unwind_backtrace return ...%d\n", ret); } void func_2() { func_1(); } static void crash_handler_more(int sig, struct siginfo* info, void* buf) { unwind_backtrace(); sigaction(sig, &act_old, 0); } void initCrashHandler() { struct sigaction act; act.sa_sigaction = crash_handler_more; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGKILL, &act, 0); sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); sigaction(SIGILL, &act, 0); sigaction(SIGABRT, &act, 0); sigaction(SIGBUS, &act, 0); sigaction(SIGSEGV, &act, &act_old); } void triggerCrash() { char *p = 0; p[100] = 'a'; } int main() { initCrashHandler(); func_2(); triggerCrash(); return 0; }
The sample code grabs the backtrace of function calls in both normal calls and crash cases. The backtrace of program crash can be saved to analyze the crash problem. The Dl_info can be extracted from the pc value of dladdr function to get the function symbol name, or can be transformed by addr2line tool.
Because the libc of android system is not standard gnulibc, the commonly used backtrace capture function android system does not support it. After verification, _Unwind_Backtrace can be used normally in android system, and all pc values of backtrace can be obtained accurately.