使用 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 ?
RSP
和RIP
是必要的,但还不够:您还需要了解内容 崩溃点的堆栈。
根据您的描述,您的信号处理程序试图从这次崩溃中恢复(可能通过 siglongjmp
退出),在这种情况下,堆栈已展开,其内容可能已消失。
事实并非如此,您可以手动展开堆栈,但是(据我所知)GDB 不支持这样做。您必须检查展开描述符 (readelf -wf a.out
) 并手动执行必要的寄存器恢复操作。
如果您的二进制文件是使用帧指针构建的(这不是优化构建中 x86_64
的默认设置),这会容易得多:您只需要恢复 RBP
然后按照帧指针链。
我认为上周遇到了同样的问题。我在没有主要可执行文件或支持库的情况下发生崩溃,因此 gdb 无法显示我需要调试的库的回溯。我最终通过使用 magic_elf 修改核心文件来修复它,以便将该线程中的 RSP 和 RIP 设置为段错误处理程序报告的寄存器。
我写了一个关于如何做到这一点的小教程:
我在 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 ?
RSP
和RIP
是必要的,但还不够:您还需要了解内容 崩溃点的堆栈。
根据您的描述,您的信号处理程序试图从这次崩溃中恢复(可能通过 siglongjmp
退出),在这种情况下,堆栈已展开,其内容可能已消失。
事实并非如此,您可以手动展开堆栈,但是(据我所知)GDB 不支持这样做。您必须检查展开描述符 (readelf -wf a.out
) 并手动执行必要的寄存器恢复操作。
如果您的二进制文件是使用帧指针构建的(这不是优化构建中 x86_64
的默认设置),这会容易得多:您只需要恢复 RBP
然后按照帧指针链。
我认为上周遇到了同样的问题。我在没有主要可执行文件或支持库的情况下发生崩溃,因此 gdb 无法显示我需要调试的库的回溯。我最终通过使用 magic_elf 修改核心文件来修复它,以便将该线程中的 RSP 和 RIP 设置为段错误处理程序报告的寄存器。
我写了一个关于如何做到这一点的小教程: