Tracing function calls
Sometimes you want to see functions of a library, as they’re called. I know of two ways of doing this.
Let’s have a super simple test program:
#include<iostream>
#include<unistd.h>
void func1() {}
void func2() {}
int main()
{
std::cout << "Hello world\n";
func1();
func2();
func1();
// Wait a bit for bpftrace to be able to aquire the function name.
// Not applicable for something that doesn't exist.
sleep(1);
}
bpftrace
Start a bpftrace in one terminal, and run the program in another.
$ sudo bpftrace -e 'uprobe:./a.out:func* { print(func); }'
Attaching 2 probes...
func1()
func2()
func1()
GDB
$ gdb a.out
[…]
(gdb) rbreak func.*
[…]
(gdb) commands
Type commands for breakpoint(s) 1-3, one per line.
End with a line saying just "end".
>silent
>bt 1
>cont
>end
(gdb) r
Starting program: […]/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
#0 0x0000555555555215 in _GLOBAL__sub_I__Z5func1v ()
Hello world
#0 0x000055555555516d in func1() ()
#0 0x0000555555555174 in func2() ()
#0 0x000055555555516d in func1() ()
[Inferior 1 (process 424744) exited normally]
(gdb)
Which to use?
bpftrace is lower (but Continue reading