简体   繁体   中英

Can gdb conditionally break non-interactively on function only if the function's return value is equal to “Value”?

I'm using gdb with the -x parameter in order to debug without having to interactively continue at each breakpoint.

[root@StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123
commands
bt
cont
end

I'm then attaching to a process that uses SomeSourceFile.cpp in it's execution:

[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>

Now, Let SomeSourceFile.cpp:123 contain a line like:

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

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

Based on: How to inspect the return value of a function in GDB? , I know that gdb can inspect the return value of a function.

And https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html tells me that I can inspect the value of a variable non-interactively:

<...>

For example, here is how you could use breakpoint commands to print the value of x at entry to foo whenever x is positive.

break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end

<...>

I have tried something like:

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

But GDB spits out:

gdb_cmds_01:1: Error in sourced command file:
No symbol "place" in current context.

Can this be worked around?

In order to break on SomeSourceFile.cpp:123 only when foo(...) != "Alice" , can I also inspect the return value of a function non-interactively?

In other words, I want to see only a subset R of the set of backtraces S such that for all backtraces b in R, the return of foo(...) is always unequal to "Alice".

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
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM