3

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?)

FelipeFR
  • 61
  • 7
  • Try to use `valgrind` or `rr` if possible. – Velkan Feb 01 '18 at 14:15
  • @velkan: I've previously tried `record full` with gdb and it didn't work because my program is multi-threaded. Will look into `rr` some more and try `valgrind` as well. – FelipeFR Feb 01 '18 at 16:17

0 Answers0