Commit cfe5930a authored by Mark Florisson's avatar Mark Florisson

Python breakpoints (cy break -p / py-break)

parent 38f33b6e
...@@ -132,6 +132,10 @@ class TestBreak(DebugTestCase): ...@@ -132,6 +132,10 @@ class TestBreak(DebugTestCase):
assert bp.enabled assert bp.enabled
def test_python_break(self):
gdb.execute('cy break -p join')
assert 'def join(' in gdb.execute('cy run', to_string=True)
class DebugStepperTestCase(DebugTestCase): class DebugStepperTestCase(DebugTestCase):
def step(self, varnames_and_values, source_line=None, lineno=None): def step(self, varnames_and_values, source_line=None, lineno=None):
......
...@@ -494,7 +494,6 @@ class CythonCommand(gdb.Command, CythonBase): ...@@ -494,7 +494,6 @@ class CythonCommand(gdb.Command, CythonBase):
""" """
command_class = gdb.COMMAND_NONE command_class = gdb.COMMAND_NONE
completer_class = gdb.COMPLETE_NONE
@classmethod @classmethod
def _register(cls, clsname, args, kwargs): def _register(cls, clsname, args, kwargs):
...@@ -656,6 +655,15 @@ class CyBreak(CythonCommand): ...@@ -656,6 +655,15 @@ class CyBreak(CythonCommand):
or for a line number: or for a line number:
cy break cython_module:lineno... cy break cython_module:lineno...
Set a Python breakpoint:
Break on any function or method named 'func' in module 'modname'
cy break -p modname.func...
Break on any function or method named 'func'
cy break -p func...
""" """
name = 'cy break' name = 'cy break'
...@@ -717,8 +725,17 @@ class CyBreak(CythonCommand): ...@@ -717,8 +725,17 @@ class CyBreak(CythonCommand):
gdb.execute('break %s' % func.pf_cname) gdb.execute('break %s' % func.pf_cname)
def invoke(self, function_names, from_tty): def invoke(self, function_names, from_tty):
for funcname in string_to_argv(function_names.encode('UTF-8')): argv = string_to_argv(function_names.encode('UTF-8'))
if ':' in funcname: if function_names.startswith('-p'):
argv = argv[1:]
python_breakpoints = True
else:
python_breakpoints = False
for funcname in argv:
if python_breakpoints:
gdb.execute('py-break %s' % funcname)
elif ':' in funcname:
self._break_pyx(funcname) self._break_pyx(funcname)
else: else:
self._break_funcname(funcname) self._break_funcname(funcname)
......
...@@ -1467,6 +1467,64 @@ PyLocals("py-locals", gdb.COMMAND_DATA, gdb.COMPLETE_NONE) ...@@ -1467,6 +1467,64 @@ PyLocals("py-locals", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
PyGlobals("py-globals", gdb.COMMAND_DATA, gdb.COMPLETE_NONE) PyGlobals("py-globals", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
class PyNameEquals(gdb.Function):
def _get_pycurframe_attr(self, attr):
frame = Frame(gdb.selected_frame())
if frame.is_evalframeex():
pyframe = frame.get_pyop()
if pyframe is None:
return None
return str(getattr(pyframe, attr))
return None
def invoke(self, funcname):
attr = self._get_pycurframe_attr('co_name')
return attr is not None and attr == funcname.string()
PyNameEquals("pyname_equals")
class PyModEquals(PyNameEquals):
def invoke(self, modname):
attr = self._get_pycurframe_attr('co_filename')
if attr is not None:
filename, ext = os.path.splitext(os.path.basename(attr))
return filename == modname.string()
return False
PyModEquals("pymod_equals")
class PyBreak(gdb.Command):
"""
Set a Python breakpoint. Examples:
Break on any function or method named 'func' in module 'modname'
py-break modname.func
Break on any function or method named 'func'
py-break func
"""
def invoke(self, funcname, from_tty):
if '.' in funcname:
modname, dot, funcname = funcname.rpartition('.')
cond = '$pyname_equals("%s") && $pymod_equals("%s")' % (funcname,
modname)
else:
cond = '$pyname_equals("%s")' % funcname
gdb.execute('break PyEval_EvalFrameEx if ' + cond)
PyBreak("py-break", gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE)
class _LoggingState(object): class _LoggingState(object):
""" """
State that helps to provide a reentrant gdb.execute() function. State that helps to provide a reentrant gdb.execute() function.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment