本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
代码示例
#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 值都可以被准确获取.