summaryrefslogtreecommitdiffstats
path: root/Tools/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/gdb')
-rwxr-xr-xTools/gdb/libpython.py84
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()