Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gdb在重新编译后找不到断言失败位置_Gdb_Fpic - Fatal编程技术网

Gdb在重新编译后找不到断言失败位置

Gdb在重新编译后找不到断言失败位置,gdb,fpic,Gdb,Fpic,在我重新编译代码之后,gdb似乎无法找到断言失败的代码位置。更准确地说,我希望信号升高相对于断言失败的位置是 0x00007ffff7a5ff00 in raise () from /lib64/libc.so.`6 而我却得到了 0x00007ffff7a5ff00 in ?? () 例如,考虑下面的代码 #include <assert.h> int main() { assert(0); return 0; } 在第一次运行gdb时,找到位置,并正确报告回溯:

在我重新编译代码之后,gdb似乎无法找到断言失败的代码位置。更准确地说,我希望信号升高相对于断言失败的位置是

0x00007ffff7a5ff00 in raise () from /lib64/libc.so.`6
而我却得到了

0x00007ffff7a5ff00 in ?? ()

例如,考虑下面的代码

#include <assert.h>

int main()
{
  assert(0);
  return 0;
}
在第一次运行gdb时,找到位置,并正确报告回溯:

GNU gdb (Gentoo 8.0.1 p1) 8.0.1 
...
(gdb) r
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
#1  0x00007ffff7a61baa in abort () from /lib64/libc.so.6
#2  0x00007ffff7a57cb7 in ?? () from /lib64/libc.so.6
#3  0x00007ffff7a57d72 in __assert_fail () from /lib64/libc.so.6
#4  0x00005555555546b3 in main () at main.c:5
(gdb)
当我重新编译代码时,问题就出现了。在重新编译之后,我在同一个gdb实例中发出run命令。Gdb重新读取符号,从头开始启动程序,但未找到正确的位置:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
`/home/myself/a.out' has changed; re-reading symbols.
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in ?? ()
(gdb) bt
#0  0x00007ffff7a5ff00 in ?? ()
#1  0x0000000000000000 in ?? ()
(gdb) up
Initial frame selected; you cannot go up.
(gdb) n
Cannot find bounds of current function
此时调试器不可用。一个人不能上去,向前走一步。 作为一种解决方法,我可以手动重新加载文件,然后再次找到位置

(gdb) file a.out
Load new symbol table from "a.out"? (y or n) y
Reading symbols from a.out...done.
(gdb) r
Starting program: /home/myself/a.out 
a.out: main.c:5: main: Assertion `0' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff7a5ff00 in raise () from /lib64/libc.so.6
(gdb) 
不幸的是,以这种方式重新加载文件后,gdb无法重置断点

勘误表:我在使用gdb 7.12.1重置断点时遇到了失败。升级到8.0.1后,问题消失了。据推测,这与错误修复有关。但是,仍然无法正确找到断言失败的代码位置

有人知道这里发生了什么吗

这在系统更新后开始发生。系统更新将所有系统库(包括glibc)重新编译为独立于位置的代码,即使用-fPIC编译


另外,我使用的gcc版本是6.4.0,在您更改源文件并重新编译后,您生成的文件与加载到GDB的文件不同

您需要停止正在运行的调试割让并重新加载文件

您无法将文件中先前定义的断点和监视点保存到已更改的源中,因为gdb实际上正在向源中插入额外的代码以支持断点和注册器处理程序

如果更改源,则行为未定义,需要重置这些断点

您可以参考gdb手册,了解如何将断点保存在文件中 马克·普洛特尼克建议,但如果你更改文件(根据我的经验),它将不起作用

这里有一个解决方法。由于
file
可以正确地重新读取符号,而
run
不能正确读取符号,因此我们可以为命令
run
定义一个钩子,以便在执行
file
之前:

define hook-run
  pi gdb.execute("file %s" % gdb.current_progspace().filename)
end

调试不同的文件时,如何使用为旧文件定义的断点?使用IDE。它们足够聪明,可以在一行上附加一个断点,并在它启动时告诉调试器。他们也足够聪明,知道当您在断点之前添加一行时,断点位置会发生变化。非常有用。我不知道这是如何在gdb中实现的。我认为在重新编译之后,能够重新运行代码并重用断点是可取的。我可以预期,可能行断点不合适,但不需要每次
文件a.out
不重新启动gdb时都重新启动gdb。它加载正确的二进制文件。可以说,因为添加或删除了一行,所以让所有断点都位于错误的位置听起来没有什么用处。我同意。事实上,我希望在函数上找到断点。但这里的问题是gdb找不到任何位置(例如,断言失败的位置),不管断点是什么。重新编译后,我再次发出“run”命令,返回消息“/home/imf/a.out”已更改;重读符号。但是gdb无法找到断言失败的正确位置。我不知道如何“保存”断点。重新加载文件时需要重置它们。我认为这是因为您尝试检查的表达式的虚拟地址已更改(在更改文件后),并且先前设置的断点与它无关。如果有一种方法可以指定gdb行号断点,并在该行及其周围使用一些源代码片段,就像一个ctags,它索引了源代码的每一行。这样,断点列表就可以在较小的代码编辑中幸存下来。也许IDE可以做到这一点。事实上,它可以做到。然而,我遇到的问题比这更微妙。这与在run命令之后重置断点失败有关。这是一个带有PIE可执行文件的bug,在8.0.1版中已修复。我相应地更新了帖子
define hook-run
  pi gdb.execute("file %s" % gdb.current_progspace().filename)
end