ChatGPT解决这个技术问题 Extra ChatGPT

让 GDB 保存断点列表

好的,info break 列出了断点,但其格式不适合使用 --command as in this question 重复使用它们。 GDB 是否有一种方法可以将它们转储到可以再次输入的文件中?有时在调试会话中,需要在建立一组断点后重新启动 GDB 以进行测试。

.gdbinit 文件与 --command 有相同的问题。 info break 命令没有列出命令,而是一个供人类使用的表格。

详细地说,这里是信息中断的一个示例:

(gdb) info break
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x08048517 <foo::bar(void)+7>

P
Peter Mortensen

从 GDB 7.2 (2011-08-23) 开始,您现在可以使用 save breakpoints 命令。

save breakpoints <filename>
  Save all current breakpoint definitions to a file suitable for use
  in a later debugging session.  To read the saved breakpoint
  definitions, use the `source' command.

使用 source <filename> 从文件中恢复保存的断点。


如果它们来自共享库负载怎么办?它默认回答 N 似乎... Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
请注意,当您有一个在启动时无法解析的断点条件 (break g_log if log_level==G_LOG_LEVEL_CRITICAL),那么至少 gdb 7.8.1 将停止解析进一步的命令。如果您有应针对该断点执行的其他命令,请将 commands 行放在 condition 行之前。
@Andry 我将您的编辑回滚到我原来的块引用,因为文本是文档中的逐字引用...如果是我自己的话,我会同意您的编辑。
@aculich:我明白了。在任何情况下,我都建议使用引用样式而不是代码样式。
P
Peter Mortensen

这个答案已经过时了。 GDB 现在支持直接保存。请参阅 this answer

您可以使用日志记录:

(gdb) b main
Breakpoint 1 at 0x8049329
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) set logging file breaks.txt
(gdb) set logging on
Copying output to breaks.txt.
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>
(gdb) q

文件breaks.txt 现在包含:

Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08049329 <main+16>

编写将其转换为对 .gdbinit--command 文件有用的格式的 AWK 脚本很容易。或者您甚至可以让脚本向 GDB 命令行发出单独的 --eval-command...

将这个小宏添加到 .gdbinit 将帮助您做到这一点:

# Call with dump_breaks file.txt
define dump_breaks
    set logging file $arg0
    set logging redirect on
    set logging on
    info breakpoints
    set logging off
    set logging redirect off
end

可以很容易地使用剪切和粘贴,但脚本方法似乎是要走的路。
我不认为剪切和粘贴比只编写一次脚本,然后每次再次使用它更容易:) 毕竟,这就是你首先提出这个问题的原因,我认为 :)
嗯,我的意思是使用剪切和粘贴而不是记录方法。到目前为止,脚本是肯定的。
哇! gdb 失败!我每天都使用它,并且喜欢它的许多功能。但缺乏只是愚蠢的。
这个答案现在已经超过 2 年了,所以如果你使用的是新版本的 gdb,它可能已经过时了。从 gdb 7.2 开始,您现在可以使用 save breakpoints 命令。
P
Peter Mortensen

将 GDB 命令和断点放在 .gdbinit file 中,就像在 gdb> 提示符下键入它们一样,GDB 将在启动时自动加载和运行它们。这是一个按目录的文件,因此您可以为不同的项目使用不同的文件。


这实际上不起作用,我得到“警告:保存跟踪点:没有要保存的跟踪点。”尽管设置了断点,但使用 gdb 6.8。
这对我有用。 GDB 需要在您的 $HOME/.gdbinit 中存在一个全局 .gdbinit,其内容为“add-auto-load-safe-path /home/johnny/src/.gdbinit”,因此 src/ 文件夹也有一个单独的 .gdbinit
P
Peter Mortensen

anon's extensionJohannes' answer 的扩展:

.gdbinit:

define bsave
    shell rm -f brestore.txt
    set logging file brestore.txt
    set logging on
    info break
    set logging off
    # Reformat on-the-fly to a valid GDB command file
    shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

define brestore
  source brestore.gdb
end
document brestore
  restore breakpoints saved by bsave
end

然后,您可以使用 brestore 恢复使用 bsave 保存的断点。


这是一个更好的正则表达式: perl -ne "print \"break \$1 \n\" if /at\s(.*:\d+)/" brestore.txt
P
Peter Mortensen

the answer from Johannes 的扩展:您可以自动将 info break 的输出重新格式化为有效的 GDB 命令文件:

.gdbinit:

define bsave
   shell rm -f brestore.txt
   set logging file brestore.txt
   set logging on
   info break
   set logging off
   # Reformat on-the-fly to a valid gdb command file
   shell perl -n -e 'print "break $1\n" if /^\d+.+?(\S+)$/g' brestore.txt > brestore.gdb
end
document bsave
  store actual breakpoints
end

之后,您在 brestore.gdb 中有一个有效的命令文件。

当应用程序使用 -g 编译时,这对我有用。

我还在 Ubuntu 9.10 (Karmic Koala) 上使用 GDB v6.8 成功测试了它。


谢谢你的这个片段!效果很好。在 Mac OS 10.5.8 上使用 CarbonEmacs GNU Emacs 22.3.1(i386-apple-darwin9.6.0,Carbon 版本 1.6.0)中的 GNU gdb 6.3.50-20050815(Apple 版本 gdb-966)成功测试。
P
Peter Mortensen

将以下内容放入 ~/.gdbinit 以将 bsavebrestore 定义为 GDB 命令以保存和恢复断点。

define bsave
    save breakpoints ~/.breakpoints
end

define brestore
   source ~/.breakpoints
end

P
Peter Mortensen

也许是这样:

save breakpoints [filename]


这已在 the accepted answer 中介绍。
P
Peter Mortensen

我发现对先前答案的以下补充对于将断点保存/加载到特定文件很有用。

保存断点:bsave {filename}

加载断点:bload {filename}

与上一个答案一样,将以下代码添加到文件 ~/.gdbinit

# Save breakpoints to a file
define bsave
    if $argc != 1
        help bsave
    else
    save breakpoints $arg0
    end
end
document bsave
Saves all current defined breakpoints to the defined file in the PWD
Usage: bsave <filename>
end

# Loads breakpoints from a file
define bload
    if $argc != 1
        help bload
    else
        source $arg0
    end
end
document bload
Loads all breakpoints from the defined file in the PWD
Usage: bload <filename>
end

P
Peter Mortensen

警告:当前输出协议不支持重定向

尝试在 TUI 模式下启用日志记录时,我也在 GDB 中收到此错误/警告。但是,日志记录似乎在“非 TUI”模式下工作。所以每当我想记录一些东西时,我都会离开 TUI 模式。 (使用 Ctrl + XCtrl + A 来回切换到 TUI 模式)。

这是我的工作方式:

启动 GDB(在正常模式下)启用日志记录:设置日志记录 - 现在它不应该抱怨了。来回切换到 TUI 模式并在我想要记录某些内容(如巨大的回溯转储)时执行 GDB 操作 - 切换到正常模式


哦,如果你喜欢使用“屏幕”(就像我一样),它会变得有点混乱,因为它使用相同的热键。
P
Peter Mortensen

问题是设置断点是上下文相关的。如果你有两个名为 foo 的静态函数怎么办?

如果您已经在调试定义 foo 的模块之一,那么 GDB 将假定您的意思是那个。但是,如果您只是将“break foo”转储到一个文件中,然后在启动时读取该文件,则不清楚您指的是哪个函数 foo。


P
Peter Mortensen

还有其他想法吗?我有

warning: Current output protocol does not support redirection

set logging on

编辑:

我知道这个问题是“如何保存断点列表”,但是我刚刚发现,使用 GDB,我们可以简单地设置“保存在文件中”的断点

gdb> source breakpoints.txt

其中 breakpoints.txt 是这样的文件:

break main.cpp:25
break engine.cpp:465
break wheel.cpp:57

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅