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".