Sample watchpoints or breakpoints with GDB (and FlameGraph)
Published:
Updated:
GDB can be used to get the stack each time a breakpoint is reached.
GDB in batch mode can be used to get the stack each time a breakpoint/watchpoint is hit:
Sampling breakpoints
# This is sample.gdb:
# my_function may not be availabe straight away.
# First get into main:
break main
run
delete
# Now, we can set the breakpoint:
break my_function
commands
silent
backtrace
continue
end
# Resume the program:
continue
And run it with:
gdb --batch -x sample.gdb ./my_program > my_program.txt
Sampling breakpoints as a Python script
We can use Python instead which is simpler and more flexible:
class MyBreakpoint(gdb.Breakpoint):
def stop (self):
gdb.execute("backtrace")
return False
main = MyBreakpoint("my_function");
gdb.execute("run")
The script must end in .py
in order to be recognised by GDB as a Python script:
gdb --batch -x sample.py ./my_program > my_program.txt
Example
Here is an example with a watchpoint I used to find where an expected value in a program was coming from:
# Run the program a first time.
# The program calls abort() when the expected value is reached.
# A conditional breakpoint could be used instead.
run
# At this point, setup a watchpoint on the location of this unexpected value:
frame 3
# -l is used in order to set the breakpoint on a given address:
watch -l *(int*) ((char*)heap_region1->start_addr + ((char*)&heapinfo1->type-(char*)heap_region1->data))
commands
backtrace
continue
end
# Restart the application in order to figure out who writes at this address:
run
In order to have stable addresses between the two runs, we need to disable Address space layout randomization (ASLR):
setarch x86_64 -R gdb --batch -x ./my_program > my_program.txt
We can even generate a FlameGraph: