Coredump GDB" Backtrace停止了:框架没有保存PC"

时间:2017-03-29 16:11:35

标签: c gdb coredump toolchain backtrace

在GDB中尝试分析coredump的回溯(由SIGABRT从assert转发的进程)时,我得到以下输出:

(gdb) bt
#0  0x76d6bc54 in raise () from ./lib/libc.so.1
#1  0x76d63bb8 in abort () from ./lib/libc.so.1
Backtrace stopped: frame did not save the PC
(gdb) thread apply all bt

二进制文件用" -g"编译所有链接的库都是如此,除了工具链中的那些(例如libc,它甚至没有符号),我无法确定它是如何构建的。

这个堆栈是否损坏,或者是libc被编译为" fomit-frame-pointer"等的结果。

作为一个普遍的问题,如果一个未捕获的异常发生在运行时链接库中,并且该库不是为调试而构建的,即coredump是否仍然包含有用的信息?

由于

2 个答案:

答案 0 :(得分:0)

改进包含来自没有调试符号的共享对象的函数的回溯的一种方法是安装调试符号,其中gdb可以看到它们。有关如何执行此操作的详细信息取决于您的环境。一个例子是,如果libc.so.6包由Debian系统上的libc6包提供,安装libc6-dbg包会在/usr/lib/debug/.build-id下面放置一些符号表({{1}除了libc6之外,package还提供了许多其他剥离的共享对象。如果您正在为非本机核心使用调试器环境(正如libc.so.6中的前导.所建议的那样),您可能会提取此类软件包而不是安装它(在Debian系统上{ {1}}是一种方法。)

除了调试符号的问题之外,在某些情况下,您可以通过确保gdb看到的共享对象(剥离或以其他方式)正确对应于转储核心的进程正在使用的共享对象来改进回溯。 。检查这种方法的一种方法是比较./lib/libc.so.1命令报告的(在典型的Linux系统上)构建ID。这只有在您可以可靠地确定核心转储时正在使用哪些共享对象时才有用,并且它假定您的共享对象是以包含构建ID的方式构建的。

在某些情况下,可以从核心文件本身可靠地提取可执行文件的构建ID和所有相关的共享对象。在Linux系统上,这需要在核心中存在文件注释,并且存在可执行文件的第一页和每个共享对象。最近配置了典型默认值的Linux内核包括所有这些。

https://github.com/wackrat/structer提供了python代码,它从核心文件中提取构建ID,满足其假设。根据核心文件的大小,最好使用64位系统,即使核心本身来自32位系统。

如果事实证明gdb正在为此核心使用正确的共享对象(或者如果没有可行的方法来确认或反驳),另一种可能性是在gdb报告的两个堆栈帧中反汇编代码。如果gdb看到的共享对象不是这个核心的正确对象,那么反汇编很可能是神秘的,因为gdb依赖于它用来与核心文件时该位置的内容对齐的共享对象的内容被转储(只读段通常从核心文件中排除,但提供每个构建ID的第一页除外)。根据我的经验,即使没有帧指针,gdb通常也可以提供没有调试符号的连贯回溯,但如果使用了错误的共享对象,gdb可能会将其回溯基于与该位置的正确内容不对应的指令。

答案 1 :(得分:0)

我认为罪魁祸首是应用程序正在加载的libc。它可能编译了一些选项,使coredump无用。我所做的是创建一个自定义工具链(使用从buildroot编译的工具链)并使用该工具链编译和运行应用程序。然后,我成功地阅读了coredump。