是否可以调试最初由已剥离符号的可执行文件生成的核心文件?

问题描述 投票:0回答:2

核心文件是由删除了符号的发布版本代码(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 ?? ()
c++ linux coredump crash-dumps
2个回答
3
投票

理论上,应该可以通过再次构建程序来重现符号。但它要求你有完全相同版本的编译器,具有完全相同的设置,相同版本的操作系统和相同版本的库,系统头文件等,并且操作系统不进行地址随机化[或者调试器理解地址洗牌]。

然而,我上面列出的“如果......和......”链中似乎缺少一些东西 - 这意味着你的堆栈及其内容并不是特别有意义。

您可能想要执行

x/1000zg $rsp
操作,看看堆栈内容是否看起来比回溯更合理。您始终可以在单独的 gdb 实例中加载带有调试符号的可执行文件,并使用
disass 0x124213,+123
反汇编该进程中
0x123213
(以及 123 个字节)处的内容。

此外,假设您不能 100% 确定线程,请尝试

info thread
查看线程的内容。

我不羡慕你...


3
投票

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

我最终使用的方法很像你的。我构建了该库的副本,其中包含所有相同的选项以及调试符号。

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

然后我进入没有符号的原始库上的

objdump -dC
,通过搜索匹配的一系列机器指令来找到匹配的位置。这给了我图书馆中的偏移量。

然后我能够进入使用调试符号构建的库并找到相同的函数。它通常位于相同的一般区域,尽管由于编译器使用的随机数可能会发生小的变化。 (注意:我后来开始使用 GCC 的

-frandom-seed
选项强制在每次编译运行时使用相同的随机数。阅读文档。每个源文件必须使用不同的种子。)

从这里开始,就需要阅读反汇编代码来确定出了什么问题。如果核心转储表明它因读取寄存器 $r12 中的 NULL 指针而崩溃,我必须从调试符号版本中找出 $r12 的值在哪里。

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

© www.soinside.com 2019 - 2024. All rights reserved.