如何在不退出和丢失断点的情况下在gdb中重新加载重新编译的二进制文件?

use*_*937 8 c++ gdb

根据这份出色的指南,应该能够重新编译源文件,并且只需使用“ r”使gdb开始调试新的,经过更改的二进制文件。

在gdb手册中,这似乎也暗示着:“如果自上次GDB读取符号以来,符号文件的修改时间已更改,则GDB会丢弃其符号表,然后再次读取它。”

我正在尝试在Ubuntu 16.10上调试一个简单的单个.cpp文件。通过编译后g++ -ggdb -std=c++11 589.cpp,我可以照常进行调试。

GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu2) 7.11.90.20161005-git
[...]
(gdb) break main
Breakpoint 1 at 0x2754: file 589.cpp, line 204.
(gdb) r
Starting program: /home/code/589

Breakpoint 1, main () at 589.cpp:204
(gdb) n
(gdb) k
Kill the program being debugged? (y or n) y
Run Code Online (Sandbox Code Playgroud)

在这里,我对源文件进行了较小的更改,然后重新编译。尝试再次运行文件时:

(gdb) r
/home/code/589' has changed; re-reading symbols.
Error in re-setting breakpoint 1: Cannot access memory at address 0x55555555674b
Starting program: /home/code/598
warning: Probes-based dynamic linker interface failed.
Reverting to original interface.

[Inferior 1 (process 20898) exited normally]
Run Code Online (Sandbox Code Playgroud)

有没有办法在保持断点完好的情况下成功重新加载二进制文件?

编辑:这篇文章有我正在寻找的答案。您使用file binaryname命令重新加载可执行文件。

(gdb) file 589
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
A program is being debugged already.
Load new symbol table from "589"? (y or n) y
Reading symbols from 589...done.
Error in re-setting breakpoint 1: Cannot access memory at address 0x274b
Error in re-setting breakpoint 2: Cannot access memory at address 0x274b
Run Code Online (Sandbox Code Playgroud)

我们看到断点仍然存在,只是被禁用了:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x0000555555556754
        breakpoint already hit 1 time
2       breakpoint     keep n   0x000055555555677b 
Run Code Online (Sandbox Code Playgroud)

因此,我们只需启用它们:

(gdb) enable
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000555555556754 
        breakpoint already hit 1 time
2       breakpoint     keep y   0x000055555555677b
(gdb) 
Run Code Online (Sandbox Code Playgroud)

这行得通,但是我很想听听是否有人对简单使用run是否确实有进一步的建议或意见。

小智 6

当我使用gdb 5时,在重新编译后仅使用'run'就足以重新加载符号。现在,对于gdb 8.1,我需要在“运行”之前键入“文件可执行文件”,以强制gdb在重新编译后重新加载符号。


小智 6

这是我在 gdb 8.3 中使用的脚本(稍微适应了这个答案):

define make
    shell make
    python gdb.execute("file " + gdb.current_progspace().filename)
    # clear cache
    directory
end
Run Code Online (Sandbox Code Playgroud)

你需要有带 Python 的 gdb。请注意directory更新源文件缓存的命令。


小智 5

特别是断点和 PIE 的问题似乎已在 gdb 8.3.1 中得到修复 - 请参阅https://www.gnu.org/software/gdb/news/和 PR 25011。

由于该问题是由位置无关的可执行文件 (PIE) 引起的,因此重新链接程序-no-pie也应该可以解决该问题。

让我想到这个问题的问题是,符号的自动重新加载似乎在新的 gdb 中被破坏了,但似乎变化不在 gdb 中,而是 Linux 发行版开始在 gcc 中默认启用 PIE。-no-pie还为我修复了符号重新加载的链接。