# 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

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.