代码示例
#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;
}
示例代码在正常调用和程序crash两种情况下抓取函数调用的backtrace, 程序崩溃的backtrace可以保存下来用于分析崩溃问题.可以用dladdr函数通过pc值提取出Dl_info, 从而拿到函数符号名, 也可以通过 addr2line工具进行转换.
由于android系统的libc不是标准的gnulibc, 常用的backtrace抓取函数android系统并不支持, 经过验证, _Unwind_Backtrace可以在android系统正常使用, backtrace的所有pc值都可以被准确获取.