bpo-30983: [gdb] Fix py-bt, etc. for non-debug shared builds (#3153)

PEP 523 introduced _PyEval_EvalFrameDefault which inlines PyEval_EvalFrameEx on
non-debug shared builds.  This breaks the ability to use py-bt, py-up, and
a few other Python-specific gdb integrations.

This patch fixes the problem by only looking for _PyEval_EvalFrameDefault
frames.

test_gdb passes on both a debug and a non-debug build.

Original patch by Bruno "Polaco" Penteado.
This commit is contained in:
Łukasz Langa 2017-08-21 16:40:29 -07:00 committed by GitHub
parent ea57923e89
commit 5fe59f8e3a
3 changed files with 18 additions and 9 deletions

View File

@ -1185,6 +1185,7 @@ Berker Peksag
Andreas Pelme
Steven Pemberton
Bo Peng
Bruno "Polaco" Penteado
Santiago Peresón
George Peristerakis
Thomas Perl

View File

@ -0,0 +1,6 @@
gdb integration commands (py-bt, etc.) work on optimized shared builds now,
too. PEP 523 introduced _PyEval_EvalFrameDefault which inlines
PyEval_EvalFrameEx on non-debug shared builds. This broke the ability to
use py-bt, py-up, and a few other Python-specific gdb integrations. The
problem is fixed by only looking for _PyEval_EvalFrameDefault frames in
python-gdb.py. Original patch by Bruno "Polaco" Penteado.

View File

@ -99,6 +99,8 @@ hexdigits = "0123456789abcdef"
ENCODING = locale.getpreferredencoding()
EVALFRAME = '_PyEval_EvalFrameDefault'
class NullPyObjectPtr(RuntimeError):
pass
@ -1492,18 +1494,18 @@ class Frame(object):
# - everything else
def is_python_frame(self):
'''Is this a PyEval_EvalFrameEx frame, or some other important
'''Is this a _PyEval_EvalFrameDefault frame, or some other important
frame? (see is_other_python_frame for what "important" means in this
context)'''
if self.is_evalframeex():
if self.is_evalframe():
return True
if self.is_other_python_frame():
return True
return False
def is_evalframeex(self):
'''Is this a PyEval_EvalFrameEx frame?'''
if self._gdbframe.name() == 'PyEval_EvalFrameEx':
def is_evalframe(self):
'''Is this a _PyEval_EvalFrameDefault frame?'''
if self._gdbframe.name() == EVALFRAME:
'''
I believe we also need to filter on the inline
struct frame_id.inline_depth, only regarding frames with
@ -1512,7 +1514,7 @@ class Frame(object):
So we reject those with type gdb.INLINE_FRAME
'''
if self._gdbframe.type() == gdb.NORMAL_FRAME:
# We have a PyEval_EvalFrameEx frame:
# We have a _PyEval_EvalFrameDefault frame:
return True
return False
@ -1626,7 +1628,7 @@ class Frame(object):
frame = cls.get_selected_frame()
while frame:
if frame.is_evalframeex():
if frame.is_evalframe():
return frame
frame = frame.older()
@ -1634,7 +1636,7 @@ class Frame(object):
return None
def print_summary(self):
if self.is_evalframeex():
if self.is_evalframe():
pyop = self.get_pyop()
if pyop:
line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
@ -1653,7 +1655,7 @@ class Frame(object):
sys.stdout.write('#%i\n' % self.get_index())
def print_traceback(self):
if self.is_evalframeex():
if self.is_evalframe():
pyop = self.get_pyop()
if pyop:
pyop.print_traceback()