如何在 SIGSEGV 上使用 _Unwind_Backtrace 获取 fullstacktrace
我通过代码处理 SIGSEGV:
int C()
{
int *i = NULL;
*i = 10; // Crash there
}
int B()
{
return C();
}
int A()
{
return B();
}
int main(void)
{
struct sigaction handler;
memset(&handler,0,sizeof(handler));
handler.sa_sigaction = handler_func;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV,&handler,NULL);
return(C());
}
其中处理程序代码是:
static int handler_func(int signal, siginfo_t info, void* rserved)
{
const void* stack[MAX_DEPTH];
StackCrowlState state;
state.addr = stack;
state.count = MAX_DEPTH;
_Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state);
printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code);
kill(getpid(),SIGKILL);
}
static _Unwind_Reason_Code trace_func(void* context, void* arg)
{
StackCrowlState *state = (StackCrowlState *)arg;
if(state->count>0)
{
void *ip = (void *)_Unwind_GetIP(context);
if(ip)
{
state->addr[0] = ip;
state->count--;
state->addr++;
}
}
return(_URC_NO_REASON);
}
但是 trace_func
仅调用一次,并且仅在 _Unwind_Backtrace
调用时显示。是否可以使用 _Unwind_Backtrace
获取导致 SIGSEGV 信号的代码的堆栈跟踪?
I handle SIGSEGV by code:
int C()
{
int *i = NULL;
*i = 10; // Crash there
}
int B()
{
return C();
}
int A()
{
return B();
}
int main(void)
{
struct sigaction handler;
memset(&handler,0,sizeof(handler));
handler.sa_sigaction = handler_func;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV,&handler,NULL);
return(C());
}
Where handler code are:
static int handler_func(int signal, siginfo_t info, void* rserved)
{
const void* stack[MAX_DEPTH];
StackCrowlState state;
state.addr = stack;
state.count = MAX_DEPTH;
_Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state);
printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code);
kill(getpid(),SIGKILL);
}
static _Unwind_Reason_Code trace_func(void* context, void* arg)
{
StackCrowlState *state = (StackCrowlState *)arg;
if(state->count>0)
{
void *ip = (void *)_Unwind_GetIP(context);
if(ip)
{
state->addr[0] = ip;
state->count--;
state->addr++;
}
}
return(_URC_NO_REASON);
}
But trace_func
where called only once, and shows only on _Unwind_Backtrace
calls. Is it possible to get stacktrace of code which cause SIGSEGV signal using _Unwind_Backtrace
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您想特别使用
_Unwind_Context()
,您可以这样做(该代码是32位ARM特定的):但我建议您不要使用
_Unwind_Context()
code>,而是使用针对 32 位 ARM 的预编译libunwind
,与现代 Android NDK 捆绑在一起(位于sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a
)以及所有 LLVM。您必须使用 libc++ (LLVM STL)。我的答案演示了如何做到这一点,您必须结合此处的示例。https://stackoverflow.com/a/50027799/1016580
如果您使用 libstdc++ (GNU STL),则可以使用Dar Hoo 的解决方案:
https://stackoverflow.com/a/48593413/1016580
If you want to use particularly
_Unwind_Context()
, you can do it like this (the code is 32-bit ARM specific):But I am advising you to not use
_Unwind_Context()
, but instead use precompiledlibunwind
for 32-bit ARM, bundled with modern Android NDKs (atsources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a
) and with all LLVM. You will have to use use libc++ (LLVM STL). How to do it, is demonstrated in this my answer, you'd have to combine the examples here.https://stackoverflow.com/a/50027799/1016580
If you use libstdc++ (GNU STL), you could use the Dar Hoo's solution:
https://stackoverflow.com/a/48593413/1016580
您想从信号触发函数进行回溯,但您却从信号处理函数进行回溯。这是两个不同的堆栈。 (注意,sigaction中的SA_ONSTACK标志与您的问题无关。)
要查找触发函数的堆栈指针,请使用处理程序的第三个参数,即void *rserved。您可以参考这个问题的答案:获取从信号处理程序保存的指令指针地址
You want to backtrace from the signal triggering function, but you backtrace from the signal handler function. That's two different stacks. (Note, the SA_ONSTACK flag in sigaction is irrelevant to your question.)
To find the stack pointer of the of the triggering function, use the third parameter of the handler, i.e. void *rserved. You can reference to the answer in this question: Getting the saved instruction pointer address from a signal handler
最好使用 backtrace 和 backtrace_symbols_fd 从信号处理程序获取堆栈跟踪。
better you use backtrace and backtrace_symbols_fd to get a stacktrace from a signal handler.
您可以使用 __gnu_Unwind_Backtrace 来代替。 ARM32 示例:
You may use
__gnu_Unwind_Backtrace
instead. Example for ARM32: