使用 GDB 展开已知堆栈和指令指针

Unwind known stack and instruction pointer with GDB

我在 Linux x64 上有一个核心转储。在某些时候 SIGSEGV 发生了,不幸的是应用程序处理了这个信号(但最终还是失败了)。所以核心转储不直接包含原始 SIGSEGV 的帧。

我能够确定失败指令的 SP 和 IP(以及其他寄存器)。基本上我有完整的 ucontext 结构。

有没有 GDB/LLDB 的方法,而不是在线程上显示堆栈,只是展开已知 SP/IP 的回溯?

Is there a way with GDB/LLDB instead of showing stacks on threads just unwind the backtrace from known SP/IP ?

RSPRIP是必要的,但还不够:您还需要了解内容 崩溃点的堆栈。

根据您的描述,您的信号处理程序试图从这次崩溃中恢复(可能通过 siglongjmp退出),在这种情况下,堆栈已展开,其内容可能已消失。

事实并非如此,您可以手动展开堆栈,但是(据我所知)GDB 不支持这样做。您必须检查展开描述符 (readelf -wf a.out) 并手动执行必要的寄存器恢复操作。

如果您的二进制文件是使用帧指针构建的(这不是优化构建中 x86_64 的默认设置),这会容易得多:您只需要恢复 RBP 然后按照帧指针链。

我认为上周遇到了同样的问题。我在没有主要可执行文件或支持库的情况下发生崩溃,因此 gdb 无法显示我需要调试的库的回溯。我最终通过使用 magic_elf 修改核心文件来修复它,以便将该线程中的 RSP 和 RIP 设置为段错误处理程序报告的寄存器。

我写了一个关于如何做到这一点的小教程:

http://www.mikekohn.net/software/core_file_analysis.php