【问题标题】:GDB conditional break on function parameter函数参数的 GDB 条件中断
【发布时间】:2014-11-12 16:45:07
【问题描述】:

如果函数参数大于某个值,我想在函数参数上设置断点。下面的虚拟代码:

int main(void)
{
    uint64_t num = 123456;
    uint64_t x   = 847534;

    uint64_t other = (num*x) - (x/num);

    .... other stuff here (multithreaded stuff)

    calc(other);
}

void calc(uint64_t size)
{
    ...do some stuff with size
}

我尝试通过以下方式设置断点:

(gdb) b calc if size == 852479

但它不知道大小是多少,因为它是我猜测的参数。如果参数等于某个数字,我将如何中断。中断对该函数的所有调用不是一个选项,因为它在多线程环境中被调用了十亿次。

【问题讨论】:

  • 你试过在函数代码的第一行设置断点吗?
  • @RickyMutschlechner 我看过那个 1 并且它不是重复的,因为在那个代码 x (有问题的变量)的情况下,gdb 假设它可以中断,因为它是在函数外部声明的变量。在我的例子中,这个变量是一个函数的参数。我能够成功打破在函数外部声明的变量,但无法通过条件中断来打破参数
  • @Nick.D,我的意思是有条件的休息
  • 那个条件断点命令对我来说很好用(CentOS 7 上的 gcc 4.8.2、gdb 7.6.1-51.el7)。我在启动 gdb 后立即键入它,而不运行目标。您在哪些 gcc/gdb 版本和操作系统上看到此问题?

标签: c gdb


【解决方案1】:

来自gdb 提示:

break "file.c":100 if (size=852479)

break "file.c":100 if (size>852479)

这里我假设你想要第 100 行的条件断点并且你的 src 文件是 file.c

即,如果您想在调用 calc 的行上中断,那么这将是第 100 行 - 酌情修改(在这种情况下,您还必须将 size 替换为 other

如果您使用了行号。这是calc 函数中的第一条语句之一,那么您将坚持使用size

【讨论】:

  • 我遇到的问题是 gdb 在启动程序之前不知道“大小”,可能是因为它是参数名称,而不是在函数外部声明的变量。我现在正在尝试的一件事是在函数上设置断点,运行程序,现在 gdb 知道大小变量,现在我正在对该变量进行条件中断。下面的示例 (gdb) break file.c:calc (gdb) run Breakpoint 1, calc (size=48) at file.c:67 in file.c (gdb) b if size = 852479 //这是 size 的实际位置被 gdb (gdb) c 识别
  • gdb 在启动程序之前 知道任何事情吗? 'other' 是在调用 calc 之前声明和实例化的变量 - 因此在其上设置条件断点应该没有问题(也许我仍然误解了这里的问题?)
  • size 应该有一个“==”而不是一个“=”,应该是这样的:break "file.c":100 if (size==852479)
【解决方案2】:

假设 x86-64 calling conventions 在 GNU/Linux 平台上,您可以直接检查 %rdi(64 位)寄存器来检查函数的第一个参数:

b calc if $rdi == 852479

即使您没有加载调试符号(因此没有代码列表,即list calc),这也允许您中断函数calc

请注意,如果函数由optimizing compiler 内联,则此方法将失败。

【讨论】:

    【解决方案3】:

    如果break foo if arg1 == 14 因某种原因无法正常工作(我遇到过一些函数/二进制文件可以使用,也可以不使用),您可以尝试将其替换为commands

    commands 允许您设置一些 gdb 命令,这些命令将在每次遇到断点时运行。要达到预期的效果 - 条件断点 - 您可以执行以下操作:

    (gdb) b foo
    Breakpoint 1 at 0x400633: file test.c, line 6.
    (gdb) commands 1
    Type commands for breakpoint(s) 1, one per line.
    End with a line saying just "end".
    >silent
    >if arg1 != 14
     >cont
     >end
    >end
    

    只有在arg1 == 14 时才会在断点处停止执行。

    唯一的缺点是silent 抑制了典型的“断点命中”消息。您可以删除silent,但即使commands 脚本跳过断点,gdb 也会打印消息,如果断点经常被命中,这是不可取的。

    不过,您可以在 command 脚本中添加一些自定义通知。

    【讨论】:

      猜你喜欢
      • 2016-06-18
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 2019-02-07
      相关资源
      最近更新 更多