Stack specific breakpoints in gdb

From raju

Objective

The idea here is to set a breakpoint in function A only when it is called from function B.

Solution

(gdb) break funcA if $_caller_is("funcB")

For example consider the following program

rajulocal@hogwarts ~/work/cpp % cat breakpoint_by_stack.cpp
#include <iostream>
#include <cmath>

using namespace std;

double power(const double x, const double m)
{
        return pow(x, m);
}

double square(const double x)
{
        return power(x,2);
}

double cube(const double x)
{
        return power(x,3);
}

void drive()
{
        int i;
        for (i=1; i<=5; i++)
        {
                cout << "square(" << i << ") = " << square(i) << endl;
        }

        cout << "cube(" << i << ") = " << cube(i) << endl;

        for (i=6; i<=10; i++)
        {
                cout << "square(" << i << ") = " << square(i) << endl;
        }
}

int main()
{

        drive();
        return 0;
}

Compile it

rajulocal@hogwarts ~/work/cpp % g++ -g breakpoint_by_stack.cpp -o breakpoint_by_stack

Run it

rajulocal@hogwarts ~/work/cpp % ./a.out 
square(1) = 1
square(2) = 4
square(3) = 9
square(4) = 16
square(5) = 25
cube(6) = 216
square(6) = 36
square(7) = 49
square(8) = 64
square(9) = 81
square(10) = 100

When debugging, set a breakpoint in the power function only if it was called from the cube() and skip the rest of the calls initiated from square().

rajulocal@hogwarts ~/work/cpp % ~/software/myroot/gdb-7.9/bin/gdb ./breakpoint_by_stack
GNU gdb (GDB) 7.9
...
(gdb) b power if $_caller_is("cube")
Breakpoint 1 at 0x400948: file breakpoint_by_stack.cpp, line 18.
(gdb) r
Starting program: /home/rajulocal/work/cpp/breakpoint_by_stack 
square(1) = 1
square(2) = 4
square(3) = 9
square(4) = 16
square(5) = 25

Breakpoint 1, power (x=6, m=3) at breakpoint_by_stack.cpp:18
18              return pow(x, m);
(gdb) bt
#0  power (x=6, m=3) at breakpoint_by_stack.cpp:18
#1  0x00000000004009eb in cube (x=6) at breakpoint_by_stack.cpp:28
#2  0x0000000000400a7d in drive () at breakpoint_by_stack.cpp:39
#3  0x0000000000400b3f in main () at breakpoint_by_stack.cpp:50
(gdb) c
Continuing.
cube(6) = 216
square(6) = 36
square(7) = 49
square(8) = 64
square(9) = 81
square(10) = 100
[Inferior 1 (process 17983) exited normally]
(gdb) quit

Notice how I am using ~/software/myroot/gdb-7.9/bin/gdb instead of the usual /usr/bin/gdb . That is because this feature is only available in gdb 7.9 onwards which is not readily available in Debian at the moment.

rajulocal@hogwarts ~/work/cpp % dpkg -l gdb | grep ^ii
ii  gdb                                                           7.7.1+dfsg-5                        amd64                               GNU Debugger

rajulocal@hogwarts ~/work/cpp % rmadison gdb      
debian:
 gdb | 7.0.1-2        | squeeze           | source, ia64, mips
 gdb | 7.0.1-2+b1     | squeeze           | amd64, armel, i386, kfreebsd-amd64, kfreebsd-i386, mipsel, powerpc, s390, sparc
 gdb | 7.3-1~bpo60+1  | squeeze-backports | source, amd64, armel, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, sparc
 gdb | 7.4.1+dfsg-0.1 | wheezy            | source, amd64, armel, armhf, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, s390x, sparc
 gdb | 7.7.1+dfsg-5   | jessie            | source, amd64, arm64, armel, armhf, i386, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, ppc64el, s390x
 gdb | 7.7.1+dfsg-5   | sid               | source, amd64, arm64, armel, armhf, hurd-i386, i386, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, ppc64el, s390x, sparc
 gdb | 7.8.1-1        | experimental      | source, hurd-i386
 gdb | 7.8.2-1        | experimental      | source, amd64, arm64, armel, armhf, i386, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, ppc64el, s390x, sparc
new:

However, compiling gdb is super easy. First install all the dependencies, download the source code and unzip it.

rajulocal@hogwarts ~ % cd ~/software 

rajulocal@hogwarts ~/software % ls
compiledLibs/  compileHere/  myroot/  unZipped/  zipped/

rajulocal@hogwarts ~/software % sudo apt-get build-dep gdb

rajulocal@hogwarts ~/software % cd zipped 

rajulocal@hogwarts ~/software/zipped
 % wget http://ftp.gnu.org/gnu/gdb/gdb-7.9.tar.xz

rajulocal@hogwarts ~/software/zipped
 % cd ../unZipped 

rajulocal@hogwarts ~/software/unZipped
 % tar xJvf ../zipped/gdb-7.9.tar.xz 

then configure, compile and install

rajulocal@hogwarts ~/software/unZipped
 % cd ../compileHere 

rajulocal@hogwarts ~/software/compileHere
 % mkdir gdb-7.9 

rajulocal@hogwarts ~/software/compileHere
 % cd gdb-7.9 

rajulocal@hogwarts ~/software/compileHere/gdb-7.9
 % ../../unZipped/gdb-7.9/configure --prefix=/home/rajulocal/software/myroot/gdb-7.9 |& tee configure_$(date +'%Y%m%d_%H%M').log

rajulocal@hogwarts ~/software/compileHere/gdb-7.9
 % make |& tee make_$(date +'%Y%m%d_%H%M').log

rajulocal@hogwarts ~/software/compileHere/gdb-7.9
 % make install |& tee install_$(date +'%Y%m%d_%H%M').log

Check if the new gdb is working fine

rajulocal@hogwarts ~/software/compileHere/gdb-7.9
 % cd ../../myroot/gdb-7.9 

rajulocal@hogwarts ~/software/myroot/gdb-7.9
 % ls        
bin/  include/  lib/  share/

rajulocal@hogwarts ~/software/myroot/gdb-7.9
 % bin/gdb --version
GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".

Related links