只有当函数的返回值等于“值”时,gdb 才能有条件地非交互式地中断函数吗?

Ski*_*ter 5 c++ unix linux debugging gdb

我使用带有 -x 参数的 gdb 进行调试,而不必在每个断点处以交互方式继续。

[root@StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123
commands
bt
cont
end
Run Code Online (Sandbox Code Playgroud)

然后我附加到一个在执行中使用 SomeSourceFile.cpp 的进程:

[root@StackOverflow.com] $ gdb -p 'pidof SomeRunningProgram' -x gdb_cmds_01
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
...
<GDB outputs a set S of backtraces as instructed by gdb_cmds_01>
Run Code Online (Sandbox Code Playgroud)

现在,让 SomeSourceFile.cpp:123 包含如下一行:

if (foo(person, &place, *time) == "Alice") { ... <do stuff > ... }
Run Code Online (Sandbox Code Playgroud)

再假设我想在SomeSourceFile打破:123只有回归foo(...)不是等于“爱丽丝”。

基于: 如何在 GDB 中检查函数的返回值?,我知道gdb可以检查函数的返回值。

https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html告诉我,我可以检查一个变量非交互的价值:

<...>

例如,这里是如何使用断点命令在 x 为正数时将 x 的值打印到 foo 的方法。

break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end
Run Code Online (Sandbox Code Playgroud)

<...>

我尝试过类似的事情:

[root@StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123 if foo(person, &place, *time) != "Alice"
commands
bt
cont
end
Run Code Online (Sandbox Code Playgroud)

但是 GDB 吐槽了:

gdb_cmds_01:1: Error in sourced command file:
No symbol "place" in current context.
Run Code Online (Sandbox Code Playgroud)

这可以解决吗?

为了仅在 SomeSourceFile.cpp:123 上中断foo(...) != "Alice",我还可以非交互地检查函数的返回值吗?

换句话说,我只想看到回溯集合 S 的一个子集 R,这样对于 R 中的所有回溯 b,返回的foo(...)总是不等于“爱丽丝”。

Emp*_*ian 2

Suppose I want to break on SomeSourceFile:123 only if the return of foo(...) is not equal to "Alice".

This fairly easy to do if you go to the lower (assembly level), and if the code is built without optimization.

It is also trivial to do if you can modify the source like so:

if (foo(...) == "Alice") { ...
} else {
  int x = 0; if (x) abort(); // break here
}
Run Code Online (Sandbox Code Playgroud)

Now you can simply set breakpoint on line 125, and you are done.

So how can you do this without modifying the source?

You must understand that the compiler invokes some bool operator==(), compares the return to true or false, and conditionally jumps around the body of if when the condition is false.

The (gdb) info line 123 will give you range of instructions that were produced for this source line.

Disassembling that range of instructions will allow you to locate the call to operator==, and show you the instruction that compares EAX (JE or JNE) with 0 or 1.

You can then set the breakpoint on the conditional jump instruction, and use $EAX (or $RAX for 64-bit code) is the condition on that breakpoint.