Commit f0dd51b1 authored by Mark Florisson's avatar Mark Florisson

Fix Python stepping watchpoints + cy step repeatability

parent 05444495
...@@ -882,12 +882,12 @@ class CythonExecutionControlCommand(CythonCommand, ...@@ -882,12 +882,12 @@ class CythonExecutionControlCommand(CythonCommand,
class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin): class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
"Step through Cython, Python or C code." "Step through Cython, Python or C code."
name = 'cy step' name = 'cy -step'
stepinto = True stepinto = True
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
if self.is_python_function(): if self.is_python_function():
self.python_step(args, self.stepinto) self.python_step(self.stepinto)
elif not self.is_cython_function(): elif not self.is_cython_function():
if self.stepinto: if self.stepinto:
command = 'step' command = 'step'
...@@ -900,9 +900,9 @@ class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin): ...@@ -900,9 +900,9 @@ class CyStep(CythonExecutionControlCommand, libpython.PythonStepperMixin):
class CyNext(CyStep): class CyNext(CyStep):
"Step-over Python code." "Step-over Cython, Python or C code."
name = 'cy next' name = 'cy -next'
stepinto = False stepinto = False
...@@ -1295,4 +1295,25 @@ class CyLine(gdb.Function, CythonBase): ...@@ -1295,4 +1295,25 @@ class CyLine(gdb.Function, CythonBase):
cython_info = CythonInfo() cython_info = CythonInfo()
cy = CyCy.register() cy = CyCy.register()
cython_info.cy = cy cython_info.cy = cy
\ No newline at end of file
def register_defines():
libpython.source_gdb_script(textwrap.dedent("""\
define cy step
cy -step
end
define cy next
cy -next
end
document cy step
%s
end
document cy next
%s
end
""") % (CyStep.__doc__, CyNext.__doc__))
register_defines()
\ No newline at end of file
...@@ -1843,6 +1843,39 @@ def get_selected_inferior(): ...@@ -1843,6 +1843,39 @@ def get_selected_inferior():
if thread == selected_thread: if thread == selected_thread:
return inferior return inferior
def source_gdb_script(script_contents, to_string=False):
"""
Source a gdb script with script_contents passed as a string. This is useful
to provide defines for py-step and py-next to make them repeatable (this is
not possible with gdb.execute()). See
http://sourceware.org/bugzilla/show_bug.cgi?id=12216
"""
fd, filename = tempfile.mkstemp()
f = os.fdopen(fd, 'w')
f.write(script_contents)
f.close()
gdb.execute("source %s" % filename, to_string=to_string)
def register_defines():
source_gdb_script(textwrap.dedent("""\
define py-step
-py-step
end
define py-next
-py-next
end
document py-step
%s
end
document py-next
%s
end
""") % (PyStep.__doc__, PyNext.__doc__))
def stackdepth(frame): def stackdepth(frame):
"Tells the stackdepth of a gdb frame." "Tells the stackdepth of a gdb frame."
depth = 0 depth = 0
...@@ -2194,36 +2227,18 @@ class PythonInfo(LanguageInfo): ...@@ -2194,36 +2227,18 @@ class PythonInfo(LanguageInfo):
class PythonStepperMixin(object): class PythonStepperMixin(object):
""" """
Make this a mixin so CyStep can also inherit from this and use a Make this a mixin so CyStep can also inherit from this and use a
CythonCodeStepper at the same time CythonCodeStepper at the same time.
""" """
def _watchpoint_step(self, stepinto): def python_step(self, stepinto):
# Set a watchpoint for a frame once as deleting it will make py-step frame = gdb.selected_frame()
# unrepeatable. framewrapper = Frame(frame)
# See http://sourceware.org/bugzilla/show_bug.cgi?id=12216
# When the watchpoint goes out of scope it will automatically
# disappear.
newframe = gdb.selected_frame()
framewrapper = Frame(newframe)
if (newframe != getattr(self, 'lastframe', None) and
framewrapper.is_evalframeex()):
self.lastframe = newframe
output = gdb.execute('watch f->f_lasti', to_string=True)
self.step(stepinto=stepinto, stepover_command='finish')
# match = re.search(r'[Ww]atchpoint (\d+):', output) output = gdb.execute('watch f->f_lasti', to_string=True)
# if match: watchpoint = int(re.search(r'[Ww]atchpoint (\d+):', output).group(1))
# watchpoint = match.group(1) self.step(stepinto=stepinto, stepover_command='finish')
# gdb.execute('delete %s' % watchpoint) gdb.execute('delete %s' % watchpoint)
def python_step(self, args, stepinto):
if args in ('-w', '--watchpoint'):
self._watchpoint_step(stepinto)
else:
self.step(stepinto)
class PyStep(ExecutionControlCommandBase, PythonStepperMixin): class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
"Step through Python code." "Step through Python code."
...@@ -2231,7 +2246,7 @@ class PyStep(ExecutionControlCommandBase, PythonStepperMixin): ...@@ -2231,7 +2246,7 @@ class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
stepinto = True stepinto = True
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
self.python_step(args, stepinto=self.stepinto) self.python_step(stepinto=self.stepinto)
class PyNext(PyStep): class PyNext(PyStep):
"Step-over Python code." "Step-over Python code."
...@@ -2252,9 +2267,10 @@ class PyCont(ExecutionControlCommandBase): ...@@ -2252,9 +2267,10 @@ class PyCont(ExecutionControlCommandBase):
invoke = ExecutionControlCommandBase.cont invoke = ExecutionControlCommandBase.cont
# Wrap py-step and py-next in gdb defines to make them repeatable.
py_step = PyStep('py-step', PythonInfo()) py_step = PyStep('-py-step', PythonInfo())
py_next = PyNext('py-next', PythonInfo()) py_next = PyNext('-py-next', PythonInfo())
register_defines()
py_finish = PyFinish('py-finish', PythonInfo()) py_finish = PyFinish('py-finish', PythonInfo())
py_run = PyRun('py-run', PythonInfo()) py_run = PyRun('py-run', PythonInfo())
py_cont = PyCont('py-cont', PythonInfo()) py_cont = PyCont('py-cont', PythonInfo())
...@@ -2510,5 +2526,8 @@ class PyExec(gdb.Command): ...@@ -2510,5 +2526,8 @@ class PyExec(gdb.Command):
executor.evalcode(expr, input_type, global_dict, local_dict) executor.evalcode(expr, input_type, global_dict, local_dict)
py_exec = FixGdbCommand('py-exec', '-py-exec') if hasattr(gdb, 'GdbError'):
_py_exec = PyExec("-py-exec", gdb.COMMAND_DATA, gdb.COMPLETE_NONE) py_exec = FixGdbCommand('py-exec', '-py-exec')
_py_exec = PyExec("-py-exec", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
else:
warnings.warn("Use gdb 7.2 or higher to use the py-exec command.")
\ No newline at end of file
...@@ -100,7 +100,8 @@ def compile_cython_modules(profile=False, compile_more=False, cython_with_refnan ...@@ -100,7 +100,8 @@ def compile_cython_modules(profile=False, compile_more=False, cython_with_refnan
"Cython.Compiler.Parsing", "Cython.Compiler.Parsing",
"Cython.Compiler.Visitor", "Cython.Compiler.Visitor",
"Cython.Compiler.Code", "Cython.Compiler.Code",
"Cython.Runtime.refnanny"] "Cython.Runtime.refnanny",
"Cython.Debugger.do_repeat",]
if compile_more: if compile_more:
compiled_modules.extend([ compiled_modules.extend([
"Cython.Compiler.ParseTreeTransforms", "Cython.Compiler.ParseTreeTransforms",
......
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