Commit c6807afd authored by Stefan Behnel's avatar Stefan Behnel

Update libpython from latest CPython upstream (1ceb3a3d17).

parent 4eef0edd
......@@ -9,7 +9,7 @@
From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
to be extended with Python code e.g. for library-specific data visualizations,
such as for the C++ STL types. Documentation on this API can be seen at:
https://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
This python module deals with the case when the process being debugged (the
......@@ -48,7 +48,7 @@ The module also extends gdb with some python-specific commands.
'''
# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
# compatible (2.7+ and 3.3+). See #19308.
# compatible (2.6+ and 3.0+). See #19308.
from __future__ import print_function
import gdb
......@@ -276,12 +276,13 @@ class PyObjectPtr(object):
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):
......@@ -315,7 +316,7 @@ class PyObjectPtr(object):
def __repr__(self):
# For the NULL pointer, we have no way of knowing a type, so
# special-case it as per
# https://bugs.python.org/issue8032#msg100882
# http://bugs.python.org/issue8032#msg100882
if self.address == 0:
return '0x0'
return '<%s at remote 0x%x>' % (self.tp_name, self.address)
......@@ -355,7 +356,9 @@ class PyObjectPtr(object):
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
......@@ -623,7 +626,10 @@ class PyCFunctionObjectPtr(PyObjectPtr):
def proxyval(self, visited):
m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
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():
......@@ -736,7 +742,7 @@ class PyDictObjectPtr(PyObjectPtr):
else:
offset = 8 * dk_size
ent_addr = keys['dk_indices']['as_1'].address
ent_addr = keys['dk_indices'].address
ent_addr = ent_addr.cast(_type_unsigned_char_ptr()) + offset
ent_ptr_t = gdb.lookup_type('PyDictKeyEntry').pointer()
ent_addr = ent_addr.cast(ent_ptr_t)
......@@ -934,35 +940,50 @@ class PyFrameObjectPtr(PyObjectPtr):
if long(f_trace) != 0:
# we have a non-NULL f_trace:
return self.f_lineno
else:
#try:
try:
return self.co.addr2line(self.f_lasti)
#except ValueError:
# return self.f_lineno
except Exception:
# bpo-34989: addr2line() is a complex function, it can fail in many
# ways. For example, it fails with a TypeError on "FakeRepr" if
# gdb fails to load debug symbols. Use a catch-all "except
# Exception" to make the whole function safe. The caller has to
# handle None anyway for optimized Python.
return None
def current_line(self):
'''Get the text of the current source line as a string, with a trailing
newline character'''
if self.is_optimized_out():
return '(frame information optimized out)'
lineno = self.current_line_num()
if lineno is None:
return '(failed to get frame line number)'
filename = self.filename()
try:
f = open(os_fsencode(filename), 'r')
with open(os_fsencode(filename), 'r') as fp:
lines = fp.readlines()
except IOError:
return None
with f:
all_lines = f.readlines()
# Convert from 1-based current_line_num to 0-based list offset:
return all_lines[self.current_line_num()-1]
try:
# Convert from 1-based current_line_num to 0-based list offset
return lines[lineno - 1]
except IndexError:
return None
def write_repr(self, out, visited):
if self.is_optimized_out():
out.write('(frame information optimized out)')
return
out.write('Frame 0x%x, for file %s, line %i, in %s ('
lineno = self.current_line_num()
lineno = str(lineno) if lineno is not None else "?"
out.write('Frame 0x%x, for file %s, line %s, in %s ('
% (self.as_address(),
self.co_filename.proxyval(visited),
self.current_line_num(),
lineno,
self.co_name.proxyval(visited)))
first = True
for pyop_name, pyop_value in self.iter_locals():
......@@ -981,9 +1002,11 @@ class PyFrameObjectPtr(PyObjectPtr):
sys.stdout.write(' (frame information optimized out)\n')
return
visited = set()
sys.stdout.write(' File "%s", line %i, in %s\n'
lineno = self.current_line_num()
lineno = str(lineno) if lineno is not None else "?"
sys.stdout.write(' File "%s", line %s, in %s\n'
% (self.co_filename.proxyval(visited),
self.current_line_num(),
lineno,
self.co_name.proxyval(visited)))
class PySetObjectPtr(PyObjectPtr):
......@@ -1092,6 +1115,7 @@ class PyBytesObjectPtr(PyObjectPtr):
out.write(quote)
# Added in Cython for Py2 backwards compatibility.
class PyStringObjectPtr(PyBytesObjectPtr):
_typename = 'PyStringObject'
......@@ -1166,7 +1190,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
def proxyval(self, visited):
global _is_pep393
if _is_pep393 is None:
fields = gdb.lookup_type('PyUnicodeObject').target().fields()
fields = gdb.lookup_type('PyUnicodeObject').fields()
_is_pep393 = 'data' in [f.name for f in fields]
if _is_pep393:
# Python 3.3 and newer
......@@ -1351,13 +1375,13 @@ class wrapperobject(PyObjectPtr):
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):
......@@ -1435,8 +1459,8 @@ The following code should ensure that the prettyprinter is registered
if the code is autoloaded by gdb when visiting libpython.so, provided
that this python file is installed to the same path as the library (or its
.debug file) plus a "-gdb.py" suffix, e.g:
/usr/lib/libpython3.7.so.1.0-gdb.py
/usr/lib/debug/usr/lib/libpython3.7.so.1.0.debug-gdb.py
/usr/lib/libpython2.6.so.1.0-gdb.py
/usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
"""
def register (obj):
if obj is None:
......@@ -1451,7 +1475,7 @@ register (gdb.current_objfile ())
# Unfortunately, the exact API exposed by the gdb module varies somewhat
# from build to build
# See https://bugs.python.org/issue8279?#msg102276
# See http://bugs.python.org/issue8279?#msg102276
class Frame(object):
'''
......@@ -1563,15 +1587,22 @@ class Frame(object):
# 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
......@@ -1730,6 +1761,9 @@ class PyList(gdb.Command):
filename = pyop.filename()
lineno = pyop.current_line_num()
if lineno is None:
print('Unable to read python frame line number')
return
if start is None:
start = lineno - 5
......
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