mirror of
https://github.com/python/cpython.git
synced 2025-01-19 06:54:52 +08:00
Issue #19308: fix the gdb plugin on gdbs linked with Python 3
This commit is contained in:
parent
5bef410471
commit
e50240c504
@ -63,7 +63,7 @@ def run_gdb(*args, **env_vars):
|
|||||||
return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
|
return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
|
||||||
|
|
||||||
# Verify that "gdb" was built with the embedded python support enabled:
|
# Verify that "gdb" was built with the embedded python support enabled:
|
||||||
gdbpy_version, _ = run_gdb("--eval-command=python import sys; print sys.version_info")
|
gdbpy_version, _ = run_gdb("--eval-command=python import sys; print(sys.version_info)")
|
||||||
if not gdbpy_version:
|
if not gdbpy_version:
|
||||||
raise unittest.SkipTest("gdb not built with embedded python support")
|
raise unittest.SkipTest("gdb not built with embedded python support")
|
||||||
|
|
||||||
|
@ -40,11 +40,21 @@ the type names are known to the debugger
|
|||||||
|
|
||||||
The module also extends gdb with some python-specific commands.
|
The module also extends gdb with some python-specific commands.
|
||||||
'''
|
'''
|
||||||
from __future__ import with_statement
|
|
||||||
|
# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
|
||||||
|
# compatible (2.6+ and 3.0+). See #19308.
|
||||||
|
|
||||||
|
from __future__ import print_function, with_statement
|
||||||
import gdb
|
import gdb
|
||||||
|
import os
|
||||||
import locale
|
import locale
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info[0] >= 3:
|
||||||
|
unichr = chr
|
||||||
|
xrange = range
|
||||||
|
long = int
|
||||||
|
|
||||||
# Look up the gdb.Type for some standard types:
|
# Look up the gdb.Type for some standard types:
|
||||||
_type_char_ptr = gdb.lookup_type('char').pointer() # char*
|
_type_char_ptr = gdb.lookup_type('char').pointer() # char*
|
||||||
_type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char*
|
_type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char*
|
||||||
@ -58,16 +68,16 @@ _is_pep393 = None
|
|||||||
SIZEOF_VOID_P = _type_void_ptr.sizeof
|
SIZEOF_VOID_P = _type_void_ptr.sizeof
|
||||||
|
|
||||||
|
|
||||||
Py_TPFLAGS_HEAPTYPE = (1L << 9)
|
Py_TPFLAGS_HEAPTYPE = (1 << 9)
|
||||||
|
|
||||||
Py_TPFLAGS_LONG_SUBCLASS = (1L << 24)
|
Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
|
||||||
Py_TPFLAGS_LIST_SUBCLASS = (1L << 25)
|
Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
|
||||||
Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26)
|
Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
|
||||||
Py_TPFLAGS_BYTES_SUBCLASS = (1L << 27)
|
Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
|
||||||
Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28)
|
Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
|
||||||
Py_TPFLAGS_DICT_SUBCLASS = (1L << 29)
|
Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
|
||||||
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30)
|
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
|
||||||
Py_TPFLAGS_TYPE_SUBCLASS = (1L << 31)
|
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
|
||||||
|
|
||||||
|
|
||||||
MAX_OUTPUT_LEN=1024
|
MAX_OUTPUT_LEN=1024
|
||||||
@ -90,32 +100,39 @@ def safety_limit(val):
|
|||||||
def safe_range(val):
|
def safe_range(val):
|
||||||
# As per range, but don't trust the value too much: cap it to a safety
|
# As per range, but don't trust the value too much: cap it to a safety
|
||||||
# threshold in case the data was corrupted
|
# threshold in case the data was corrupted
|
||||||
return xrange(safety_limit(val))
|
return xrange(safety_limit(int(val)))
|
||||||
|
|
||||||
def write_unicode(file, text):
|
if sys.version_info[0] >= 3:
|
||||||
# Write a byte or unicode string to file. Unicode strings are encoded to
|
def write_unicode(file, text):
|
||||||
# ENCODING encoding with 'backslashreplace' error handler to avoid
|
file.write(text)
|
||||||
# UnicodeEncodeError.
|
else:
|
||||||
if isinstance(text, unicode):
|
def write_unicode(file, text):
|
||||||
text = text.encode(ENCODING, 'backslashreplace')
|
# Write a byte or unicode string to file. Unicode strings are encoded to
|
||||||
file.write(text)
|
# ENCODING encoding with 'backslashreplace' error handler to avoid
|
||||||
|
# UnicodeEncodeError.
|
||||||
|
if isinstance(text, unicode):
|
||||||
|
text = text.encode(ENCODING, 'backslashreplace')
|
||||||
|
file.write(text)
|
||||||
|
|
||||||
def os_fsencode(filename):
|
try:
|
||||||
if not isinstance(filename, unicode):
|
os_fsencode = os.fsencode
|
||||||
return filename
|
except ImportError:
|
||||||
encoding = sys.getfilesystemencoding()
|
def os_fsencode(filename):
|
||||||
if encoding == 'mbcs':
|
if not isinstance(filename, unicode):
|
||||||
# mbcs doesn't support surrogateescape
|
return filename
|
||||||
return filename.encode(encoding)
|
encoding = sys.getfilesystemencoding()
|
||||||
encoded = []
|
if encoding == 'mbcs':
|
||||||
for char in filename:
|
# mbcs doesn't support surrogateescape
|
||||||
# surrogateescape error handler
|
return filename.encode(encoding)
|
||||||
if 0xDC80 <= ord(char) <= 0xDCFF:
|
encoded = []
|
||||||
byte = chr(ord(char) - 0xDC00)
|
for char in filename:
|
||||||
else:
|
# surrogateescape error handler
|
||||||
byte = char.encode(encoding)
|
if 0xDC80 <= ord(char) <= 0xDCFF:
|
||||||
encoded.append(byte)
|
byte = chr(ord(char) - 0xDC00)
|
||||||
return ''.join(encoded)
|
else:
|
||||||
|
byte = char.encode(encoding)
|
||||||
|
encoded.append(byte)
|
||||||
|
return ''.join(encoded)
|
||||||
|
|
||||||
class StringTruncated(RuntimeError):
|
class StringTruncated(RuntimeError):
|
||||||
pass
|
pass
|
||||||
@ -322,8 +339,8 @@ class PyObjectPtr(object):
|
|||||||
# class
|
# class
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
#print 'tp_flags = 0x%08x' % tp_flags
|
#print('tp_flags = 0x%08x' % tp_flags)
|
||||||
#print 'tp_name = %r' % tp_name
|
#print('tp_name = %r' % tp_name)
|
||||||
|
|
||||||
name_map = {'bool': PyBoolObjectPtr,
|
name_map = {'bool': PyBoolObjectPtr,
|
||||||
'classobj': PyClassObjectPtr,
|
'classobj': PyClassObjectPtr,
|
||||||
@ -733,14 +750,14 @@ class PyLongObjectPtr(PyObjectPtr):
|
|||||||
'''
|
'''
|
||||||
ob_size = long(self.field('ob_size'))
|
ob_size = long(self.field('ob_size'))
|
||||||
if ob_size == 0:
|
if ob_size == 0:
|
||||||
return 0L
|
return 0
|
||||||
|
|
||||||
ob_digit = self.field('ob_digit')
|
ob_digit = self.field('ob_digit')
|
||||||
|
|
||||||
if gdb.lookup_type('digit').sizeof == 2:
|
if gdb.lookup_type('digit').sizeof == 2:
|
||||||
SHIFT = 15L
|
SHIFT = 15
|
||||||
else:
|
else:
|
||||||
SHIFT = 30L
|
SHIFT = 30
|
||||||
|
|
||||||
digits = [long(ob_digit[i]) * 2**(SHIFT*i)
|
digits = [long(ob_digit[i]) * 2**(SHIFT*i)
|
||||||
for i in safe_range(abs(ob_size))]
|
for i in safe_range(abs(ob_size))]
|
||||||
@ -1595,12 +1612,12 @@ class PyList(gdb.Command):
|
|||||||
# py-list requires an actual PyEval_EvalFrameEx frame:
|
# py-list requires an actual PyEval_EvalFrameEx frame:
|
||||||
frame = Frame.get_selected_bytecode_frame()
|
frame = Frame.get_selected_bytecode_frame()
|
||||||
if not frame:
|
if not frame:
|
||||||
print 'Unable to locate gdb frame for python bytecode interpreter'
|
print('Unable to locate gdb frame for python bytecode interpreter')
|
||||||
return
|
return
|
||||||
|
|
||||||
pyop = frame.get_pyop()
|
pyop = frame.get_pyop()
|
||||||
if not pyop or pyop.is_optimized_out():
|
if not pyop or pyop.is_optimized_out():
|
||||||
print 'Unable to read information on python frame'
|
print('Unable to read information on python frame')
|
||||||
return
|
return
|
||||||
|
|
||||||
filename = pyop.filename()
|
filename = pyop.filename()
|
||||||
@ -1656,9 +1673,9 @@ def move_in_stack(move_up):
|
|||||||
frame = iter_frame
|
frame = iter_frame
|
||||||
|
|
||||||
if move_up:
|
if move_up:
|
||||||
print 'Unable to find an older python frame'
|
print('Unable to find an older python frame')
|
||||||
else:
|
else:
|
||||||
print 'Unable to find a newer python frame'
|
print('Unable to find a newer python frame')
|
||||||
|
|
||||||
class PyUp(gdb.Command):
|
class PyUp(gdb.Command):
|
||||||
'Select and print the python stack frame that called this one (if any)'
|
'Select and print the python stack frame that called this one (if any)'
|
||||||
@ -1740,23 +1757,23 @@ class PyPrint(gdb.Command):
|
|||||||
|
|
||||||
frame = Frame.get_selected_python_frame()
|
frame = Frame.get_selected_python_frame()
|
||||||
if not frame:
|
if not frame:
|
||||||
print 'Unable to locate python frame'
|
print('Unable to locate python frame')
|
||||||
return
|
return
|
||||||
|
|
||||||
pyop_frame = frame.get_pyop()
|
pyop_frame = frame.get_pyop()
|
||||||
if not pyop_frame:
|
if not pyop_frame:
|
||||||
print 'Unable to read information on python frame'
|
print('Unable to read information on python frame')
|
||||||
return
|
return
|
||||||
|
|
||||||
pyop_var, scope = pyop_frame.get_var_by_name(name)
|
pyop_var, scope = pyop_frame.get_var_by_name(name)
|
||||||
|
|
||||||
if pyop_var:
|
if pyop_var:
|
||||||
print ('%s %r = %s'
|
print('%s %r = %s'
|
||||||
% (scope,
|
% (scope,
|
||||||
name,
|
name,
|
||||||
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
|
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
|
||||||
else:
|
else:
|
||||||
print '%r not found' % name
|
print('%r not found' % name)
|
||||||
|
|
||||||
PyPrint()
|
PyPrint()
|
||||||
|
|
||||||
@ -1774,16 +1791,16 @@ class PyLocals(gdb.Command):
|
|||||||
|
|
||||||
frame = Frame.get_selected_python_frame()
|
frame = Frame.get_selected_python_frame()
|
||||||
if not frame:
|
if not frame:
|
||||||
print 'Unable to locate python frame'
|
print('Unable to locate python frame')
|
||||||
return
|
return
|
||||||
|
|
||||||
pyop_frame = frame.get_pyop()
|
pyop_frame = frame.get_pyop()
|
||||||
if not pyop_frame:
|
if not pyop_frame:
|
||||||
print 'Unable to read information on python frame'
|
print('Unable to read information on python frame')
|
||||||
return
|
return
|
||||||
|
|
||||||
for pyop_name, pyop_value in pyop_frame.iter_locals():
|
for pyop_name, pyop_value in pyop_frame.iter_locals():
|
||||||
print ('%s = %s'
|
print('%s = %s'
|
||||||
% (pyop_name.proxyval(set()),
|
% (pyop_name.proxyval(set()),
|
||||||
pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
|
pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user