Commit 5fe59f8e authored by Łukasz Langa's avatar Łukasz Langa Committed by GitHub

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.
parent ea57923e
...@@ -1185,6 +1185,7 @@ Berker Peksag ...@@ -1185,6 +1185,7 @@ Berker Peksag
Andreas Pelme Andreas Pelme
Steven Pemberton Steven Pemberton
Bo Peng Bo Peng
Bruno "Polaco" Penteado
Santiago Peresón Santiago Peresón
George Peristerakis George Peristerakis
Thomas Perl Thomas Perl
......
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.
...@@ -99,6 +99,8 @@ hexdigits = "0123456789abcdef" ...@@ -99,6 +99,8 @@ hexdigits = "0123456789abcdef"
ENCODING = locale.getpreferredencoding() ENCODING = locale.getpreferredencoding()
EVALFRAME = '_PyEval_EvalFrameDefault'
class NullPyObjectPtr(RuntimeError): class NullPyObjectPtr(RuntimeError):
pass pass
...@@ -1492,18 +1494,18 @@ class Frame(object): ...@@ -1492,18 +1494,18 @@ class Frame(object):
# - everything else # - everything else
def is_python_frame(self): 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 frame? (see is_other_python_frame for what "important" means in this
context)''' context)'''
if self.is_evalframeex(): if self.is_evalframe():
return True return True
if self.is_other_python_frame(): if self.is_other_python_frame():
return True return True
return False return False
def is_evalframeex(self): def is_evalframe(self):
'''Is this a PyEval_EvalFrameEx frame?''' '''Is this a _PyEval_EvalFrameDefault frame?'''
if self._gdbframe.name() == 'PyEval_EvalFrameEx': if self._gdbframe.name() == EVALFRAME:
''' '''
I believe we also need to filter on the inline I believe we also need to filter on the inline
struct frame_id.inline_depth, only regarding frames with struct frame_id.inline_depth, only regarding frames with
...@@ -1512,7 +1514,7 @@ class Frame(object): ...@@ -1512,7 +1514,7 @@ class Frame(object):
So we reject those with type gdb.INLINE_FRAME So we reject those with type gdb.INLINE_FRAME
''' '''
if self._gdbframe.type() == gdb.NORMAL_FRAME: if self._gdbframe.type() == gdb.NORMAL_FRAME:
# We have a PyEval_EvalFrameEx frame: # We have a _PyEval_EvalFrameDefault frame:
return True return True
return False return False
...@@ -1626,7 +1628,7 @@ class Frame(object): ...@@ -1626,7 +1628,7 @@ class Frame(object):
frame = cls.get_selected_frame() frame = cls.get_selected_frame()
while frame: while frame:
if frame.is_evalframeex(): if frame.is_evalframe():
return frame return frame
frame = frame.older() frame = frame.older()
...@@ -1634,7 +1636,7 @@ class Frame(object): ...@@ -1634,7 +1636,7 @@ class Frame(object):
return None return None
def print_summary(self): def print_summary(self):
if self.is_evalframeex(): if self.is_evalframe():
pyop = self.get_pyop() pyop = self.get_pyop()
if pyop: if pyop:
line = pyop.get_truncated_repr(MAX_OUTPUT_LEN) line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
...@@ -1653,7 +1655,7 @@ class Frame(object): ...@@ -1653,7 +1655,7 @@ class Frame(object):
sys.stdout.write('#%i\n' % self.get_index()) sys.stdout.write('#%i\n' % self.get_index())
def print_traceback(self): def print_traceback(self):
if self.is_evalframeex(): if self.is_evalframe():
pyop = self.get_pyop() pyop = self.get_pyop()
if pyop: if pyop:
pyop.print_traceback() pyop.print_traceback()
......
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