我知道:
-
当安装带有
sigaction
和sa_sigaction
(而不是sa_handler
(的SIGSEGV
信号处理程序时,信号处理程序会收到一个siginfo_t*
,其中si_addr
是发生故障的地址。 -
使用
ucontext_t
我们可以检查寄存器的值,例如指令指针,尽管不是以独立于平台的方式(Linux 信号处理。如何获取中断指令的地址?
我的问题:我们还能知道哪个寄存器导致了故障吗?鉴于我们没有内存到内存的移动,这应该只有一个寄存器(毕竟也只有一个si_addr
(。当然,我可以检查所有寄存器并搜索si_addr
,但可能有多个匹配项。
我对不独立于平台的解决方案非常满意。
加载/存储地址可能不在任何单个寄存器中;它可能是寻址模式的结果,如[rdi + rax*4 + 100]
或其他什么。
没有简单的解决方案可以打印完整调试器的内容,除了像正常人一样在调试器下运行程序以首先捕获错误。 或者让它生成一个核心转储,供你离线分析,如果你需要调试发生在其他人的系统上的崩溃。
Linux 内核选择转储从错误的代码地址开始的指令字节(或者实际上在它之前一点作为上下文(,以及所有寄存器的内容。 反汇编以查看错误指令可以在事后从崩溃日志中完成,同时查看寄存器内容,而无需在内核本身中包含反汇编器。 请参阅 Linux 内核崩溃消息中的"代码"是什么?举个例子来说明 Linux 的作用,以及手动将其拆开而不是使用decodecode
.