【问题标题】:Unwind known stack and instruction pointer with GDB使用 GDB 展开已知堆栈和指令指针
【发布时间】:2018-02-21 18:04:09
【问题描述】:

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

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

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

【问题讨论】:

    标签: gdb coredump postmortem-debugging


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      RSP 和RIP 是必要的,但还不够:您还需要知道崩溃时堆栈的内容。

      从您的描述中可以看出,您的信号处理程序试图从这次崩溃中恢复(可能是siglongjmping out),在这种情况下,堆栈已展开并且其内容可能已经消失。

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

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

      【讨论】:

      • 是的,当然。正在讨论的应用程序是 .NET Core。我真的不明白为什么他们用信号处理程序做了所有这些魔术,而在 SIGSEGV 上崩溃应该没问题。无论如何,现在看来我需要现场重现它。
      猜你喜欢
      • 2015-06-16
      • 1970-01-01
      • 2016-01-28
      • 1970-01-01
      • 2021-09-17
      • 2013-01-20
      • 1970-01-01
      • 2018-04-01
      • 2012-05-02
      相关资源
      最近更新 更多