[Python-checkins] [3.7] bpo-32962: Backport python-gdb.py and test_gdb.py from master (GH-7710)

Victor Stinner webhook-mailer at python.org
Fri Jun 15 13:11:55 EDT 2018


https://github.com/python/cpython/commit/ca4cb8492c643d1fcac2c5b749595ad5377673ab
commit: ca4cb8492c643d1fcac2c5b749595ad5377673ab
branch: 3.7
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018年06月15日T19:11:45+02:00
summary:
[3.7] bpo-32962: Backport python-gdb.py and test_gdb.py from master (GH-7710)
* bpo-32962: python-gdb catchs ValueError on read_var() (GH-7692)
python-gdb now catchs ValueError on read_var(): when Python has no
debug symbols for example.
(cherry picked from commit 019d33b7a447e78057842332fb5d3bad01922122)
* bpo-32962: python-gdb catchs UnicodeDecodeError (GH-7693)
python-gdb now catchs UnicodeDecodeError exceptions when calling
string().
(cherry picked from commit d22fc0bc7de7882da204abe50884bbde2da4f9e7)
* bpo-32962: Fix test_gdb failure in debug build with -mcet -fcf-protection -O0 (GH-6754)
When Python is built with the intel control-flow protection flags,
-mcet -fcf-protection, gdb is not able to read the stack without
actually jumping inside the function. This means an extra
'next' command is required to make the $pc (program counter)
enter the function and make the stack of the function exposed to gdb.
(cherry picked from commit 9b7c74ca32d1bec7128d550a9ab1b2ddc7046287)
files:
A Misc/NEWS.d/next/Tests/2018-05-10-16-59-15.bpo-32962.S-rcIN.rst
A Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-16-53.bpo-32962.2YfdwI.rst
A Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-23-07.bpo-32962.Q3Dwns.rst
M Lib/test/test_gdb.py
M Tools/gdb/libpython.py
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 9e0eaea8c8f6..d341a17f1fec 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -162,7 +162,11 @@ def get_stack_trace(self, source=None, script=None,
 commands += ['set print entry-values no']
 
 if cmds_after_breakpoint:
- commands += cmds_after_breakpoint
+ # bpo-32962: When Python is compiled with -mcet -fcf-protection,
+ # arguments are unusable before running the first instruction
+ # of the function entry point. The 'next' command makes the
+ # required first step.
+ commands += ['next'] + cmds_after_breakpoint
 else:
 commands += ['backtrace']
 
@@ -847,9 +851,12 @@ def __init__(self):
 id("first break point")
 l = MyList()
 ''')
+ # bpo-32962: same case as in get_stack_trace():
+ # we need an additional 'next' command in order to read
+ # arguments of the innermost function of the call stack.
 # Verify with "py-bt":
 gdb_output = self.get_stack_trace(cmd,
- cmds_after_breakpoint=['break wrapper_call', 'continue', 'py-bt'])
+ cmds_after_breakpoint=['break wrapper_call', 'continue', 'next', 'py-bt'])
 self.assertRegex(gdb_output,
 r"<method-wrapper u?'__init__' of MyList object at ")
 
diff --git a/Misc/NEWS.d/next/Tests/2018-05-10-16-59-15.bpo-32962.S-rcIN.rst b/Misc/NEWS.d/next/Tests/2018-05-10-16-59-15.bpo-32962.S-rcIN.rst
new file mode 100644
index 000000000000..97328ebafe6e
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2018-05-10-16-59-15.bpo-32962.S-rcIN.rst
@@ -0,0 +1 @@
+Fixed test_gdb when Python is compiled with flags -mcet -fcf-protection -O0.
diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-16-53.bpo-32962.2YfdwI.rst b/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-16-53.bpo-32962.2YfdwI.rst
new file mode 100644
index 000000000000..de40070795e9
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-16-53.bpo-32962.2YfdwI.rst
@@ -0,0 +1,2 @@
+python-gdb now catchs ValueError on read_var(): when Python has no debug
+symbols for example.
diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-23-07.bpo-32962.Q3Dwns.rst b/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-23-07.bpo-32962.Q3Dwns.rst
new file mode 100644
index 000000000000..fc14261019a0
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2018-06-14-16-23-07.bpo-32962.Q3Dwns.rst
@@ -0,0 +1,2 @@
+python-gdb now catchs ``UnicodeDecodeError`` exceptions when calling
+``string()``.
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index 7df7c9bd5416..27eabcb0d3d0 100755
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -270,12 +270,13 @@ def is_optimized_out(self):
 
 def safe_tp_name(self):
 try:
- return self.type().field('tp_name').string()
- except NullPyObjectPtr:
- # NULL tp_name?
- return 'unknown'
- except RuntimeError:
- # Can't even read the object at all?
+ ob_type = self.type()
+ tp_name = ob_type.field('tp_name')
+ return tp_name.string()
+ # NullPyObjectPtr: NULL tp_name?
+ # RuntimeError: Can't even read the object at all?
+ # UnicodeDecodeError: Failed to decode tp_name bytestring
+ except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
 return 'unknown'
 
 def proxyval(self, visited):
@@ -349,7 +350,9 @@ def subclass_from_type(cls, t):
 try:
 tp_name = t.field('tp_name').string()
 tp_flags = int(t.field('tp_flags'))
- except RuntimeError:
+ # RuntimeError: NULL pointers
+ # UnicodeDecodeError: string() fails to decode the bytestring
+ except (RuntimeError, UnicodeDecodeError):
 # Handle any kind of error e.g. NULL ptrs by simply using the base
 # class
 return cls
@@ -617,7 +620,10 @@ class PyCFunctionObjectPtr(PyObjectPtr):
 
 def proxyval(self, visited):
 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
- ml_name = m_ml['ml_name'].string()
+ try:
+ ml_name = m_ml['ml_name'].string()
+ except UnicodeDecodeError:
+ ml_name = '<ml_name:UnicodeDecodeError>'
 
 pyop_m_self = self.pyop_field('m_self')
 if pyop_m_self.is_null():
@@ -1340,13 +1346,13 @@ def safe_name(self):
 try:
 name = self.field('descr')['d_base']['name'].string()
 return repr(name)
- except (NullPyObjectPtr, RuntimeError):
+ except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
 return '<unknown name>'
 
 def safe_tp_name(self):
 try:
 return self.field('self')['ob_type']['tp_name'].string()
- except (NullPyObjectPtr, RuntimeError):
+ except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
 return '<unknown tp_name>'
 
 def safe_self_addresss(self):
@@ -1552,15 +1558,22 @@ def is_other_python_frame(self):
 # Use the prettyprinter for the func:
 func = frame.read_var(arg_name)
 return str(func)
+ except ValueError:
+ return ('PyCFunction invocation (unable to read %s: '
+ 'missing debuginfos?)' % arg_name)
 except RuntimeError:
 return 'PyCFunction invocation (unable to read %s)' % arg_name
 
 if caller == 'wrapper_call':
+ arg_name = 'wp'
 try:
- func = frame.read_var('wp')
+ func = frame.read_var(arg_name)
 return str(func)
+ except ValueError:
+ return ('<wrapper_call invocation (unable to read %s: '
+ 'missing debuginfos?)>' % arg_name)
 except RuntimeError:
- return '<wrapper_call invocation>'
+ return '<wrapper_call invocation (unable to read %s)>' % arg_name
 
 # This frame isn't worth reporting:
 return False


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /