在 gdb 中如何在具有特定单词的任何行上设置断点?

In gdb how to set breakpoint on any line that has a particular word?

我希望当我的程序在 gdb 下执行时,
在执行任何代码行之前检查该行是否有特定的单词示例宏名称或变量名或任何特定的单词,如果有则停止执行。
如果能用正则表达式就更好了。

我知道有一个命令 rbreakrb 但它在匹配的函数名称上设置断点,这不是我想要的。

那有可能吗?

is it possible?

没有

GDB 根本您的源。它只是在某些位置插入断点,然后全速运行程序,直到遇到其中一个断点。

你要求的是让 GDB 重复执行 next 命令,然后如果你所在的行与你的正则表达式不匹配,则有条件地继续。我不确定是否可以编写脚本,但即使可以,对于任何 non-trivial 程序来说,这将是 不切实际的慢

在 gdb 之外,您可以先搜索您的源代码并列出您的断点,然后使用 -x 标志调用 gdb 来设置这些断点。

计划

  • grep over the source for user-defined patterns ( eg. erase, delete )
  • generate the break statements based on above line numbers, write these to file
  • call gdb with -x flag and point at generated file with break statements

man gdb

   ...
   -x file
       Execute GDB commands from file file.
   ...

write_breakpoints.sh

#!/bin/bash

sourcename="";
patterns="";
outbreaks="";

grep -En "" "" | \
  cut -d: -f1 | \
  sed "s/^\(.\+\)$/break :/g" 1>>"";

example.c

#include <stdio.h> 

void delete()
{
  printf("!! data is being deleted..\n");
}

void erase()
{
  printf("!! data is being erased..\n");
}

int main(void)
{
  printf("this line is safe..\n");
  erase();
  delete();
  return 0;
}

用法

$ gcc -g example.c -o example
$ ./write_breakpoints.sh example.c "(delete|erase)" "breakpoints.txt"

$ gdb -x breakpoints.txt example
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from example...done.
Breakpoint 1 at 0x400531: file example.c, line 3.
Breakpoint 2 at 0x400531: file example.c, line 5.
Breakpoint 3 at 0x400541: file example.c, line 8.
Breakpoint 4 at 0x400541: file example.c, line 10.
Breakpoint 5 at 0x40055b: file example.c, line 16.
Breakpoint 6 at 0x400565: file example.c, line 17.
(gdb) run
Starting program: /path/to/example 
this line is safe..

Breakpoint 5, main () at example.c:16
16    erase();
(gdb) c
Continuing.

Breakpoint 3, erase () at example.c:10
10    printf("!! data is being erased..\n");
(gdb) c
Continuing.
!! data is being erased..

Breakpoint 6, main () at example.c:17
17    delete();
(gdb) c
Continuing.

Breakpoint 1, delete () at example.c:5
5     printf("!! data is being deleted..\n");
(gdb) c
Continuing.
!! data is being deleted..
[Inferior 1 (process 26130) exited normally]
(gdb) quit

笔记

  • 可以使用多个源文件调用 write_breakpoints(因为它附加了 break 语句)
  • 也可以在 gdb 中使用 forward-search 和 b
  • 执行此操作

根据@amdixon 的回答,我写了一个对 git repos 友好的单行代码(并且对 svn、merc 等不难修改)它可以是 运行 来自 repo 根目录或任何子目录。

git ls-files '*.cpp' -z | xargs -n1 -P4 -0 awk -v wd=$(pwd) '/[REGEX]/ {print "break \"" wd "/" FILENAME ":" NR "\""}' >outbreak

其中 [REGEX] 是您的正则表达式。该文件适用于任何目录中的 运行,所以在我的例子中:

mv outbreak /pathToExecutable
cd !$
cgdb -x outbreak executable

说明

-z-0\"都是为了处理路径中的spaces/eols。 -n1 导致 awk 一次解析一个文件(否则行号将是错误的,因为它将把它当作一个巨大的 glob)。 P4 允许 awk 一次 运行 4 个进程(为了速度——可选)。 -v wd=$(pwd) 将工作目录传递给 awk,因为 wdFILENAMENR 是 awk 内置函数。