是否有可能调试最初由可执行文件生成的已删除符号的核心文件?

Is it possible to debug a core file originally produced by an executable which had symbols stripped?

本文关键字:删除 符号 核心 文件 调试 有可能 可执行文件 是否      更新时间:2023-10-16

核心文件是由代码(g++)的发布版本生成的,该版本删除了符号。

采用相同(SVN)版本的代码,我修改了构建选项以包含符号。

我应该能够调试的核心文件使用可执行文件,我已经建立了其中包括符号?看起来我做不到,但我只是想确保这不是我做错了什么。

bash-3.2$ gdb ./MyTest.53519 -c  ~/public_html/core.20375.MyTest 
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-42.el5)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/me/tmp/MyTest.53519...done.
warning: core file may not match specified executable file.
[New Thread 20388]
[New Thread 20389]
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./MyTest -np1 -p1'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007f99c19b39e0 in ?? ()
(gdb) bt
#0  0x00007f99c19b39e0 in ?? ()
#1  0x00007f99bc438650 in ?? ()
#2  0x00007f99c19b58cf in ?? ()
#3  0x00007f9994008880 in ?? ()
#4  0x00007f99b8013080 in ?? ()
#5  0x00007f99bc4386f0 in ?? ()
#6  0x00007f99bc438b00 in ?? ()
#7  0x00007f99bc438810 in ?? ()
#8  0x00007f99c19aa489 in ?? ()

理论上,通过重新构建程序应该可以复制符号。但它要求你有完全相同版本的编译器,完全相同的设置,相同版本的操作系统和相同版本的库,系统头文件等,并且操作系统不做地址随机化[或调试器理解地址变换]。

然而,似乎在"如果……"的链条中缺少了一些东西。和…,这意味着你的堆栈和它的内容不是特别有意义。

您可能想要执行x/1000zg $rsp,并查看堆栈内容是否以这种方式看起来比反向跟踪更合理。你总是可以在一个单独的gdb实例中加载带有调试符号的可执行文件,然后使用disass 0x124213,+123来反汇编进程中0x123213(和123字节)的内容。

另外,假设您不是100%确定线程,请尝试info thread查看线程是关于什么的。

我不羡慕你…

我不得不这样做,让我告诉你这并不容易。

我最后使用的方法和你的很像。我用所有相同的选项,加上调试符号,构建了一个库的副本。

然后我查看了核心转储以找到崩溃的位置。我使用gdb反汇编视图查找机器指令并备份,直到找到函数start。

然后在没有符号的原始库上进入objdump -dC,通过搜索匹配的机器指令序列来找到匹配的位置。这给了我库中的偏移量

然后我能够进入用调试符号构建的库并找到相同的函数。它通常在相同的区域,尽管由于编译器使用的随机数可能会发生小的移动。(注意:我后来开始使用GCC的-frandom-seed选项来强制在每次编译运行时使用相同的随机数。阅读文档。每个源文件必须有不同的种子)

接下来就是阅读拆解来确定哪里出了问题。如果核心转储说它因为读取寄存器$r12中的NULL指针而崩溃,我必须从调试符号版本中找出$r12的值在哪里。

在这样做了几次之后,我改变了构建系统,为每个构建使用相同的随机种子,并从一开始构建一个调试符号版本,它被剥离以产生最终的二进制文件。所有版本都被塞到SVN服务器中,以便以后根据需要提取。尽管由于每个构建都有唯一的目录名,一个简单的NFS目录也可以工作。