From af9fbdbca325989c7835bd0fb9b18f7e8faf4798 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Wed, 15 Dec 2010 19:43:26 +0100 Subject: [PATCH] Fix breakpoint approach for stepping (make stepping repeatable with breakpoints that are set and deleted instead of disabled) --- .../Debugger/Tests/test_libcython_in_gdb.py | 5 +- Cython/Debugger/libcython.py | 2 - Cython/Debugger/libpython.py | 91 ++++--------------- 3 files changed, 18 insertions(+), 80 deletions(-) diff --git a/Cython/Debugger/Tests/test_libcython_in_gdb.py b/Cython/Debugger/Tests/test_libcython_in_gdb.py index 4c84a433..2c9e7ef5 100644 --- a/Cython/Debugger/Tests/test_libcython_in_gdb.py +++ b/Cython/Debugger/Tests/test_libcython_in_gdb.py @@ -74,9 +74,6 @@ class DebugTestCase(unittest.TestCase): gdb.execute('set args -c "import codefile"') - libcython.cy.step.static_breakpoints.clear() - libcython.cy.step.runtime_breakpoints.clear() - libcython.cy.step.init_breakpoints() class TestDebugInformationClasses(DebugTestCase): @@ -130,7 +127,7 @@ class TestParameters(unittest.TestCase): class TestBreak(DebugTestCase): def test_break(self): - breakpoint_amount = len(gdb.breakpoints()) + breakpoint_amount = len(gdb.breakpoints() or ()) gdb.execute('cy break codefile.spam') self.assertEqual(len(gdb.breakpoints()), breakpoint_amount + 1) diff --git a/Cython/Debugger/libcython.py b/Cython/Debugger/libcython.py index 85e09419..09961442 100644 --- a/Cython/Debugger/libcython.py +++ b/Cython/Debugger/libcython.py @@ -706,8 +706,6 @@ class CyImport(CythonCommand): for c_lineno in c_linenos: cython_module.lineno_c2cy[c_lineno] = cython_lineno - self.cy.step.init_breakpoints() - class CyBreak(CythonCommand): """ diff --git a/Cython/Debugger/libpython.py b/Cython/Debugger/libpython.py index f05579e4..9c916715 100644 --- a/Cython/Debugger/libpython.py +++ b/Cython/Debugger/libpython.py @@ -1892,79 +1892,25 @@ class ExecutionControlCommandBase(gdb.Command): interface. 'name' is the name of the command. """ - stepper = False - static_breakpoints = {} - runtime_breakpoints = {} - def __init__(self, name, lang_info): super(ExecutionControlCommandBase, self).__init__( name, gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE) self.lang_info = lang_info - def _break_func(self, funcname): - result = gdb.execute('break %s' % funcname, to_string=True) - return re.search(r'Breakpoint (\d+)', result).group(1) - - def init_breakpoints(self): - """ - Keep all breakpoints around and simply disable/enable them each time - we are stepping. We need this because if you set and delete a - breakpoint, gdb will not repeat your command (this is due to 'delete'). - We also can't use the breakpoint API because there's no option to make - breakpoint setting silent. - - This method must be called whenever the list of functions we should - step into changes. It can be called on any GenericCodeStepper instance. - """ - break_funcs = set(self.lang_info.static_break_functions()) - - for funcname in break_funcs: - if funcname not in self.static_breakpoints: - try: - gdb.Breakpoint('', gdb.BP_BREAKPOINT, internal=True) - except (AttributeError, TypeError): - # gdb.Breakpoint does not take an 'internal' argument, or - # gdb.Breakpoint does not exist. - breakpoint = self._break_func(funcname) - except RuntimeError: - # gdb.Breakpoint does take an 'internal' argument, use it - # and hide output - result = gdb.execute(textwrap.dedent("""\ - python bp = gdb.Breakpoint(%r, gdb.BP_BREAKPOINT, \ - internal=True); \ - print bp.number""", - to_string=True)) - - breakpoint = int(result) - - self.static_breakpoints[funcname] = breakpoint - - for bp in set(self.static_breakpoints) - break_funcs: - gdb.execute("delete " + self.static_breakpoints[bp]) - - self.disable_breakpoints() - - def enable_breakpoints(self): - for bp in self.static_breakpoints.itervalues(): - gdb.execute('enable ' + bp) - - runtime_break_functions = self.lang_info.runtime_break_functions() - if runtime_break_functions is None: - return - - for funcname in runtime_break_functions: - if (funcname not in self.static_breakpoints and - funcname not in self.runtime_breakpoints): - self.runtime_breakpoints[funcname] = self._break_func(funcname) - elif funcname in self.runtime_breakpoints: - gdb.execute('enable ' + self.runtime_breakpoints[funcname]) + def install_breakpoints(self): + all_locations = itertools.chain( + self.lang_info.static_break_functions(), + self.lang_info.runtime_break_functions()) - def disable_breakpoints(self): - chain = itertools.chain(self.static_breakpoints.itervalues(), - self.runtime_breakpoints.itervalues()) - for bp in chain: - gdb.execute('disable ' + bp) - + for location in all_locations: + result = gdb.execute('break %s' % location, to_string=True) + yield re.search(r'Breakpoint (\d+)', result).group(1) + + + + def delete_breakpoints(self, breakpoint_list): + for bp in breakpoint_list: + gdb.execute("delete %s" % bp) def filter_output(self, result): output = [] @@ -2066,7 +2012,7 @@ class ExecutionControlCommandBase(gdb.Command): PyFrameObjectPtr.current_line_num and PyFrameObjectPtr.addr2line. """ if stepinto: - self.enable_breakpoints() + breakpoint_list = list(self.install_breakpoints()) beginframe = gdb.selected_frame() @@ -2100,9 +2046,7 @@ class ExecutionControlCommandBase(gdb.Command): m = re.search(r'Breakpoint (\d+)', result) if m: - bp = self.runtime_breakpoints.get(framename) - if (bp is None or - (is_relevant_function and bp == m.group(1))): + if is_relevant_function and m.group(1) in breakpoint_list: # although we hit a breakpoint, we still need to check # that the function, in case hit by a runtime breakpoint, # is in the right context @@ -2127,7 +2071,7 @@ class ExecutionControlCommandBase(gdb.Command): break if stepinto: - self.disable_breakpoints() + self.delete_breakpoints(breakpoint_list) self.finish_executing(result) @@ -2179,7 +2123,7 @@ class LanguageInfo(object): Implement this if the list of step-into functions depends on the context. """ - + return () class PythonInfo(LanguageInfo): @@ -2276,7 +2220,6 @@ py_run = PyRun('py-run', PythonInfo()) py_cont = PyCont('py-cont', PythonInfo()) gdb.execute('set breakpoint pending on') -py_step.init_breakpoints() Py_single_input = 256 Py_file_input = 257 -- 2.26.2