我一直在处理一些有问题的代码,并想安装一个 SIGSEGV 处理程序来获取有关崩溃的更多信息。但是,我注意到我的处理程序没有被调用。
我一直在寻找一个原因,它似乎与损坏的堆栈指针值有关(它肯定不会被屏蔽)。这是我编写的一些概念验证代码以进行验证:
static void catch_function(int sig, siginfo_t *info, void *cntxt)
{
puts("handler works");
}
void main(int argc, char **argv)
{
struct sigaction sa;
sa.sa_sigaction = (void *)catch_function;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_NODEFER ;
sigaction(SIGSEGV, &sa, NULL);
puts("testing handler");
raise(SIGSEGV);
puts("back");
__asm__ ( "xor %rax, %rax\n\t"
"mov %rax, %rsp\n\t"
"push 0"
);
// never reached...
}
这个想法是将 RSP 设置为 0(无效偏移),然后将其用于某些事情。但是,第二个 SIGSEGV 不会被处理程序捕获,而是终止进程。
显然,调用信号处理程序需要一个健全的堆栈指针开始——但为什么呢?这不是反对处理信号的想法吗?有机会解决这个问题吗?
我正在运行 Linux 版本 3.19.0-25-generic。