diff options
Diffstat (limited to 'Tools/gdb')
-rwxr-xr-x | Tools/gdb/libpython.py | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 62eb197..a118d32 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -45,6 +45,7 @@ The module also extends gdb with some python-specific commands. # compatible (2.6+ and 3.0+). See #19308. from __future__ import print_function + import gdb import os import locale @@ -991,6 +992,11 @@ class PyFramePtr: def _f_lasti(self): return self._f_special("f_lasti", int_from_int) + def depth(self): + return self._f_special("depth", int_from_int) + + def previous(self): + return self._f_special("previous", PyFramePtr) def iter_globals(self): ''' @@ -1797,16 +1803,20 @@ class Frame(object): def print_summary(self): if self.is_evalframe(): - pyop = self.get_pyop() - if pyop: - line = pyop.get_truncated_repr(MAX_OUTPUT_LEN) - write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line)) - if not pyop.is_optimized_out(): - line = pyop.current_line() - if line is not None: - sys.stdout.write(' %s\n' % line.strip()) - else: - sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index()) + interp_frame = self.get_pyop() + while True: + if interp_frame: + line = interp_frame.get_truncated_repr(MAX_OUTPUT_LEN) + write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line)) + if not interp_frame.is_optimized_out(): + line = interp_frame.current_line() + if line is not None: + sys.stdout.write(' %s\n' % line.strip()) + if interp_frame.depth() == 0: + break + else: + sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index()) + interp_frame = interp_frame.previous() else: info = self.is_other_python_frame() if info: @@ -1816,15 +1826,19 @@ class Frame(object): def print_traceback(self): if self.is_evalframe(): - pyop = self.get_pyop() - if pyop: - pyop.print_traceback() - if not pyop.is_optimized_out(): - line = pyop.current_line() - if line is not None: - sys.stdout.write(' %s\n' % line.strip()) - else: - sys.stdout.write(' (unable to read python frame information)\n') + interp_frame = self.get_pyop() + while True: + if interp_frame: + interp_frame.print_traceback() + if not interp_frame.is_optimized_out(): + line = interp_frame.current_line() + if line is not None: + sys.stdout.write(' %s\n' % line.strip()) + if interp_frame.depth() == 0: + break + else: + sys.stdout.write(' (unable to read python frame information)\n') + interp_frame = interp_frame.previous() else: info = self.is_other_python_frame() if info: @@ -1914,11 +1928,15 @@ PyList() def move_in_stack(move_up): '''Move up or down the stack (for the py-up/py-down command)''' + # Important: + # The amount of frames that are printed out depends on how many frames are inlined + # in the same evaluation loop. As this command links directly the C stack with the + # Python stack, the results are sensitive to the number of inlined frames and this + # is likely to change between versions and optimizations. frame = Frame.get_selected_python_frame() if not frame: print('Unable to locate python frame') return - while frame: if move_up: iter_frame = frame.older() @@ -1940,9 +1958,10 @@ def move_in_stack(move_up): print('Unable to find an older python frame') else: print('Unable to find a newer python frame') + class PyUp(gdb.Command): - 'Select and print the python stack frame that called this one (if any)' + 'Select and print all python stack frame in the same eval loop starting from the one that called this one (if any)' def __init__(self): gdb.Command.__init__ (self, "py-up", @@ -1954,7 +1973,7 @@ class PyUp(gdb.Command): move_in_stack(move_up=True) class PyDown(gdb.Command): - 'Select and print the python stack frame called by this one (if any)' + 'Select and print all python stack frame in the same eval loop starting from the one called this one (if any)' def __init__(self): gdb.Command.__init__ (self, "py-down", @@ -2067,13 +2086,20 @@ class PyLocals(gdb.Command): return pyop_frame = frame.get_pyop() - if not pyop_frame: - print(UNABLE_READ_INFO_PYTHON_FRAME) - return + while True: + if not pyop_frame: + print(UNABLE_READ_INFO_PYTHON_FRAME) + + sys.stdout.write('Locals for %s\n' % (pyop_frame.co_name.proxyval(set()))) + + for pyop_name, pyop_value in pyop_frame.iter_locals(): + print('%s = %s' + % (pyop_name.proxyval(set()), + pyop_value.get_truncated_repr(MAX_OUTPUT_LEN))) + + if pyop_frame.depth() == 0: + break - for pyop_name, pyop_value in pyop_frame.iter_locals(): - print('%s = %s' - % (pyop_name.proxyval(set()), - pyop_value.get_truncated_repr(MAX_OUTPUT_LEN))) + pyop_frame = pyop_frame.previous() PyLocals() |