I am trying to debug a C program which allocates and frees various instances of a particular structure during its lifetime. At some point, one of these instances is getting corrupted.
To debug it, I would like to set watchpoints shortly after these structures are allocated and remove the watchpoints shortly before they are free'd. For that, I wrote a python gdb script (see below) which implements two subclasses of gdb.Breakpoint
: BreakpointAlloc()
and BreakpointFree()
. The former has a stop()
method which adds a watchpoint on the allocated structure and the latter has a stop()
method which removes the watchpoint. (Watchpoints are kept in a dict indexed by a string containing the address of the allocated instance.)
Due to the large number of instances allocated (over 100), I cannot use hardware watchpoints. When using software watchpoints (by first running gdb.execute("set can-use-hw-watchpoints 0")
), however, the program seems to wedge and I can't tell what's happening.
#!/usr/bin/env python
import gdb
wps = {}
def BreakpointAlloc(gdb.Breakpoint):
def stop(self):
ptr = gdb.parse_and_eval("ptr").address
wp = gdb.Breakpoint("*({0})({1})".format(ptr.type, ptr), gdb.BP_WATCHPOINT)
wps["{0}".format(ptr)] = wp
return False
def BreakpointFree(gdb.Breakpoint):
def stop(self):
ptr = gdb.parse_and_eval("ptr").address
wp = wps["{0}".format(ptr)]
wp.delete()
del wps["{0}".format(wp)]
return False
bp_alloc = BreakpointAlloc("prog.c:111")
bp_free = BreakpointFree("prog.c:222")
gdb.execute("set can-use-hw-watchpoints 0")
The documentation for the gdb python API suggests you shouldn't do what I'm doing. I believe that may explain why the program is wedging:
Function: Breakpoint.stop (self)
...
You should not alter the execution state of the inferior (i.e., step, next, etc.), alter the current frame context (i.e., change the current active frame), or alter, add or delete any breakpoint.
Considering the documentation, I have also tried modifying my program to add/del the watchpoints via stop events (see below). When using software watchpoints, the same problem occurs: the program seems to wedge.
#!/usr/bin/env python
import gdb
wps = {}
bp_alloc = gdb.Breakpoint("prog.c:111")
bp_free = gdb.Breakpoint("proc.c:222")
def stopAlloc():
ptr = gdb.parse_and_eval("ptr").address
wp = gdb.Breakpoint("*({0})({1})".format(ptr.type, ptr), gdb.BP_WATCHPOINT)
wps["{0}".format(ptr)] = wp
def stopFree():
ptr = gdb.parse_and_eval("ptr").address
wp = wps["{0}".format(ptr)]
wp.delete()
del wps["{0}".format(ptr)]
def handleStop(stopEvent):
for bp in stopEvent.breakpoints:
if bp == bp_alloc:
stopAlloc()
elif bp == bp_free:
stopFree()
gdb.events.stop(handleStop)
gdb.execute("set can-use-hw-watchpoints 0")
Any ideas on how I could manipulate watchpoints off breakpoints?
(Or any other ideas on how to debug this issue?)