没有共享系统库的精确调试符号的远程事后分析 coredump 分析

Posted

技术标签:

【中文标题】没有共享系统库的精确调试符号的远程事后分析 coredump 分析【英文标题】:Remote Post-mortem coredump analysis without having exact debug symbols for shared system libraries 【发布时间】:2011-05-18 19:35:36 【问题描述】:

您通常如何解决这个问题?想象一下,一个线程在 Computer1 上的 libc 代码(这是一个系统共享库)内崩溃,然后生成一个 coredump。但是将在其上分析此 coredump 的 Computer2 可能具有不同版本的 libc。

所以:

    在远程计算机上拥有相同的共享库有多重要? gdb 会在 Computer2 上没有完全相同版本的 libc 的情况下正确重建堆栈跟踪吗?

    为 libc 提供正确的调试符号有多重要? gdb 会在 Computer2 上没有完全相同的调试符号的情况下正确重建堆栈跟踪吗?

    对于共享系统库,避免这种调试符号不匹配问题的“正确”方法是什么?对我来说,似乎没有单一的解决方案可以优雅地解决这个问题?也许有人可以分享他的经验?

【问题讨论】:

【参考方案1】:

    视情况而定。在某些处理器上,例如x86_64,GDB 需要正确的unwind descriptors 才能正确展开堆栈。在这样的机器上,用不匹配的 libc 分析 coredump 可能会产生完全的垃圾。

    您不需要 libc 的调试符号来获取堆栈跟踪。如果没有调试符号,您将无法获得文件和行号,但您应该获得正确的函数名称(除非发生内联)。

    您问题的前提是错误的-调试符号与此无关。当在 C1 上生成 coredump 时,在 C2 上分析 coredump 的“正确”方法是拥有 C1 库的副本(例如 /tmp/C1/lib/...)并指示 GDB 使用该副本而不是 C2 安装的 libc

    (gdb) set solib-absolute-prefix /tmp/C1

命令。

注意:在将内核加载到 GDB 之前,上述设置必须生效。这个:

gdb exe core
(gdb) set solib-absolute-prefix /tmp/C1

将不起作用(在设置生效之前读取核心)。

这是正确的方法:

gdb exe
(gdb) set solib-absolute-prefix /tmp/C1
(gdb) core core

(我试图在网上找到对此的参考,但没有)。

什么是展开描述符?

在没有帧指针的情况下编译代码时需要展开描述符(优化模式下 x86_64 的默认设置)。此类代码保存 %rbp 寄存器,因此需要告知 GDB 如何从当前帧“退回”到调用者帧(此过程也称为堆栈展开)。

为什么 C1 的 libc.so 没有包含在核心中?

核心文件通常只包含程序地址空间的可写段的内容。通常不需要只读段(可执行代码和展开描述符所在的位置)——您可以直接从磁盘上的 libc.so 中读取它们。

除非在 C2 上分析 C1 的核心时这不起作用!

一些(但不是全部)操作系统允许配置“完整核心转储”,操作系统也会在其中转储只读映射,这样您就可以在任何机器上分析核心。

【讨论】:

1.您能否解释一下“正确的展开描述符”一词-您指的是被压入堆栈的 SP 和 BP 寄存器吗? 2. coredump生成时所有的共享库也包含在coredump中,因为它基本上是内存转储?那么为什么 GDB 需要有 libc.so 文件,而它可以使用 coredump 中的 libc 呢? 我已经回答了您的其他问题(尽我所能)。 谢谢 - 答案非常好!我仍然很好奇在哪里可以找到有关“展开描述符如何工作”的更多信息......

以上是关于没有共享系统库的精确调试符号的远程事后分析 coredump 分析的主要内容,如果未能解决你的问题,请参考以下文章

使用dbghelp生成dump文件以及事后调试分析

使用dbghelp生成dump文件以及事后调试分析

当另一个库具有相同的符号时,gdb 不显示来自共享库的符号

在Eclipse中调试时如何查看android SDK系统库的符号?

使用 mpirun 时,如何使分析器(valgrind、perf、pprof)拾取/使用带有调试符号的本地版本库?

iOS系统符号符号服务