Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to set a breakpoint in gdb that is conditional on the call stack?

I am debugging C++ in gdb 7.1 on Linux.

I have a function a() that is called in many places in the code. I want to set a breakpoint in it, but only if it was called from b(). Is there any way to do it?

Is there any way to do it only if b() was called from c(), and so on ad infinitum?

like image 708
Nathan Fellman Avatar asked Mar 17 '11 08:03

Nathan Fellman


People also ask

How do you set conditional breakpoints in GDB?

Conditional breakpoints can help with this. Here [CONDITION] is a boolean expression, which, in GDB is true if the result is nonzero, otherwise it is false. The condition can include a function call, the value of a variable or the result of any GDB expression. Type help condition at the GDB prompt for more.

What is a conditional breakpoint?

Conditional breakpoints allow you to break inside a code block when a defined expression evaluates to true. Conditional breakpoints highlight as orange instead of blue. Add a conditional breakpoint by right clicking a line number, selecting Add Conditional Breakpoint , and entering an expression.

What command is used in GDB to set a breakpoint?

Breakpoints are set with the break command (abbreviated b ). The debugger convenience variable `$bpnum' records the number of the breakpoint you've set most recently; see section Convenience variables, for a discussion of what you can do with convenience variables.

How do you break a loop in GDB?

Like you can cancel a program on the command line, GDB lets you use ctrl-c to stop a program wherever it currently is. Hit ctrl-c now to break the infinite loop.


2 Answers

Update: There is now a better answer to this question: use GDB _is_caller convenience function.

The need you describe comes up quite often, usually in the context of some_utility_fn being called a lot, but you only are interested in the call which comes from some_other_fn.

You could probably script this entire interaction using the new embedded Python support in GDB from CVS trunk.

Without Python, you are limited in what you can do, but the usual technique is to have a disabled breakpoint on a(), and enable it from a command, attached to a breakpoint on b().

Here is an example:

int a(int x) {   return x + 1; }  int b() {   return a(1); }  int call_a_lots() {   int i, sum = 0;   for (i = 0; i < 100; i++)     sum += a(i); }  int main() {   call_a_lots();   return b(); }  gcc -g t.c gdb -q ./a.out Reading symbols from /tmp/a.out...done. (gdb) break a Breakpoint 1 at 0x4004cb: file t.c, line 3. (gdb) disable 1 (gdb) break b Breakpoint 2 at 0x4004d7: file t.c, line 8. (gdb) command 2 >silent >enable 1 >continue >end (gdb) run  Breakpoint 1, a (x=1) at t.c:3 3     return x + 1; (gdb) bt #0  a (x=1) at t.c:3 #1  0x00000000004004e1 in b () at t.c:8 #2  0x000000000040052c in main () at t.c:21 (gdb) q 

Voila: we've stopped on a() called from b(), ignoring previous 100 calls to a().

like image 171
Employed Russian Avatar answered Sep 19 '22 17:09

Employed Russian


gdb can handle this directly now without any need for Python. Just do this:

b a if $_caller_is("b") 
like image 39
Jeff Trull Avatar answered Sep 21 '22 17:09

Jeff Trull