【问题标题】:How to reload a recompiled binary in gdb without exiting and losing breakpoints?如何在不退出和丢失断点的情况下在 gdb 中重新加载重新编译的二进制文件?
【发布时间】:2026-02-14 01:25:01
【问题描述】:

根据this excellent guide,应该能够重新编译源文件并简单地使用 'r' 让 gdb 开始调试新的、更改的二进制文件。

in the gdb manual 似乎也暗示了“如果自 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

在这里,我对源文件做了一个小改动,然后重新编译。再次尝试运行文件时:

(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]

有没有办法在保持断点完整的同时成功重新加载二进制文件?

编辑:This post 得到了我正在寻找的答案。您使用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

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

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

所以我们只启用它们:

(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 是否确实可行有进一步的建议或意见。

【问题讨论】:

  • 断点可能位于对您的新代码不再有效的位置。请记住,即使它仍在有效位置,也可能与您预期的位置不同。
  • 另外,请考虑一下您发布的问题的标题。问题不在于重新加载程序,而在于保留断点。
  • 用解决方案编辑,确实在GDB中已经存在很长时间了。断点有效,显示的示例是源中的单个字符差异。除了一些暗示(gdb) r 将神奇地重新加载所有内容的指南之外,我找不到其他关于重新加载相同二进制文件的参考或问题。这是那些不太熟悉 gdb 的人可能会遇到并遇到困难的事情。
  • 简单的run 方法对我有用。为什么它对你失败是值得研究的。也许提交一个带有详细信息的 gdb 错误。
  • 以防万一您需要重新启动计算机*.com/questions/501486/…

标签: c++ gdb


【解决方案1】:

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

【讨论】:

  • 在 gdb 7.7 中,我还需要在run 命令之前运行file /PATH/TO/EXECUTABLE
【解决方案2】:

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

define make
    shell make
    python gdb.execute("file " + gdb.current_progspace().filename)
    # clear cache
    directory
end

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      最近更新 更多