我在 Linux x64 上有一个核心转储。在某些时候 SIGSEGV 发生了,不幸的是应用程序处理了这个信号(但最终还是失败了)。所以核心转储不直接包含原始 SIGSEGV 的帧。
我能够确定失败指令的 SP 和 IP(以及其他寄存器)。基本上我有完整的 ucontext 结构。
有没有办法使用 GDB/LLDB 而不是在线程上显示堆栈只是从已知的 SP/IP 展开回溯?
我在 Linux x64 上有一个核心转储。在某些时候 SIGSEGV 发生了,不幸的是应用程序处理了这个信号(但最终还是失败了)。所以核心转储不直接包含原始 SIGSEGV 的帧。
我能够确定失败指令的 SP 和 IP(以及其他寄存器)。基本上我有完整的 ucontext 结构。
有没有办法使用 GDB/LLDB 而不是在线程上显示堆栈只是从已知的 SP/IP 展开回溯?
我上周遇到了同样的问题。我在没有主要可执行文件或支持库的情况下发生崩溃,因此 gdb 无法显示我需要调试的库的回溯。我最终通过使用 magic_elf 修改核心文件来修复它,以便将该线程中的 RSP 和 RIP 设置为 segfault 处理程序报告的寄存器。
我写了一个关于如何做到这一点的小教程:
有没有办法使用 GDB/LLDB 而不是在线程上显示堆栈只是从已知的 SP/IP 展开回溯?
RSP
和RIP
是必要的,但还不够:您还需要知道崩溃时堆栈的内容。
从您的描述中听起来,您的信号处理程序试图从这次崩溃中恢复(可能是siglongjmp
通过退出),在这种情况下,堆栈已展开并且其内容可能已经消失。
事实并非如此,您也许可以手动展开堆栈,但是(据我所知)GDB 不支持这样做。您必须检查展开描述符 ( readelf -wf a.out
) 并手动执行必要的寄存器恢复操作。
如果您的二进制文件是使用帧指针构建的(这不是x86_64
优化构建中的默认设置),这会容易得多:您只需要恢复RBP
然后遵循帧指针链。