How to Set a Breakpoint in Gdb That Is Conditional on the Call Stack

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

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().

Can GDB set a breakpoint on a sequence of function calls?

You can use a conditional breakpoint with the the $_caller_is convenience function. Something like this:

(gdb) break connect
Breakpoint 1 at 0x7ffff7ee6820
(gdb) cond 1 $_caller_is("curl_connect") && $_caller_is("get_file", 2) && $_caller_is("init_assets", 3)

Create a conditional breakpoint base on the call stack

You can query the stack trace programatically, using System.Diagnostics Namespace. Yoy may do something like this:

System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
var f = st.GetFrames();
var names = f.Select(f => f.GetMethod().Name).ToList();
if (names.Contains("DoSomething4"))
{
var a = 0; // Set breakpoint in this line or use Debugger.Launch()
}

You can use #if DEBUG and #endif so this code doesn't go into release

Also, you can create a condition for a breakpoint using this class

gdb: conditionally break on function only if the caller function is not equal certain value

I like to set up the conditional breakpoint in gdb such that gdb will break into "gdb>" only when the caller function of malloc() is not equal to my_mallc().

In other words, you want to break on malloc when it is not called by my_malloc.

One way to do that is to set three breakpoints: one on malloc, one on my_malloc entry, and one on my_malloc return. Then (assuming the breakpoints are 1, 2 and 3 respectively).

(gdb) commands 2
silent # don't announce hitting breakpoint #2
disable 1 # don't stop when malloc is called within my_malloc
continue # continue execution when BP#2 is hit
end

(gdb) commands 3
silent
enable 1 # re-enable malloc breakpoint
continue
end

This technique only works for single-threaded applications.

In Gdb how to set conditional breakpoint to a function's 3rd line

How about defining your own command file for gdb and then just sourcing it during debug? That would help reduce a fair bit of typing. Try this:

Create a file, let's call it mydef and here's its contents:

define cmd
b function-where-you-want-to-break
r
b +2
c
end

Once you load the executable in gdb, type in source mydef in gdb prompt followed by cmd

Now you are into the 2nd line from where function began. :)
Hope this helps!

How do I set a breakpoint in GDB, but not have the breakpoint halt execution? I just want to be notified in the console if the line is hit

I want the option to be notified of the breakpoint traversal, but not halt execution.

(gdb) break foo.c:123
(gdb) commands $bpnum
continue
end

This attaches a command to the breakpoint. GDB will print that a breakpoint is hit, then run the attached command, which will continue execution.

You could also print some variables before continuing, or even continue only if some condition is true, and stop otherwise. E.g. "continue if x > 100, but stop if it's not".

Is it possible to break on a breakpoint only when a certain method is present in the call stack?

Recent versions of gdb ship with some convenience functions written in Python for just this case. Take a look at $_caller_is and friends. (FWIW this exact use case was what motivated me to work on adding Python to gdb...)

A simple use would be:

(gdb) break foo if $_any_caller_matches("bar")

If the call stack contains more functions in between foo and bar calls resulting in a stack that looks like the following,

foo()
...
...
...
bar()
...
...
...
main()

you could pass an extra argument to _any_caller_matches which indicates the number of frames to check for the occurrence of bar

(gdb) break foo if $_any_caller_matches("bar", 10)

Reference: https://sourceware.org/gdb/current/onlinedocs/gdb/Convenience-Funs.html

$_any_caller_matches(regexp[, number_of_frames])

Returns one if any
calling function’s name matches the regular expression regexp.
Otherwise it returns zero.

If the optional argument number_of_frames is provided, it is the
number of frames up in the stack to look. The default is 1.

This function differs from $_caller_matches in that this function
checks all stack frames from the immediate caller to the frame
specified by number_of_frames, whereas $_caller_matches only checks
the frame specified by number_of_frames.

How do I set a conditional breakpoint in gdb, when char* x points to a string whose value equals hello?

You can use strcmp:

break x:20 if strcmp(y, "hello") == 0

20 is line number, x can be any filename and y can be any variable.



Related Topics



Leave a reply



Submit