summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-11-23 16:40:36 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-11-23 16:40:36 (GMT)
commitb17d2aa552e0b2b5d17a036ad32aa59ddd59b2cc (patch)
treefd98b65e1d8995791d5bad6bca7eadbb06326a0e
parentc17565e4a90a6b4c9e31edf5030030a365600db6 (diff)
downloadcpython-b17d2aa552e0b2b5d17a036ad32aa59ddd59b2cc.zip
cpython-b17d2aa552e0b2b5d17a036ad32aa59ddd59b2cc.tar.gz
cpython-b17d2aa552e0b2b5d17a036ad32aa59ddd59b2cc.tar.bz2
Issue #19308: fix the gdb plugin on gdbs linked with Python 3
-rw-r--r--Lib/test/test_gdb.py2
-rw-r--r--Tools/gdb/libpython.py121
2 files changed, 70 insertions, 53 deletions
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index 284c8d8..981f1b1 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -59,7 +59,7 @@ def run_gdb(*args, **env_vars):
return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
# 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:
raise unittest.SkipTest("gdb not built with embedded python support")
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index a85f505..aa57fed 100644
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -40,11 +40,21 @@ the type names are known to the debugger
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 os
import locale
import sys
+if sys.version_info[0] >= 3:
+ unichr = chr
+ xrange = range
+ long = int
+
# Look up the gdb.Type for some standard types:
_type_char_ptr = gdb.lookup_type('char').pointer() # 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
-Py_TPFLAGS_HEAPTYPE = (1L << 9)
+Py_TPFLAGS_HEAPTYPE = (1 << 9)
-Py_TPFLAGS_LONG_SUBCLASS = (1L << 24)
-Py_TPFLAGS_LIST_SUBCLASS = (1L << 25)
-Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26)
-Py_TPFLAGS_BYTES_SUBCLASS = (1L << 27)
-Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28)
-Py_TPFLAGS_DICT_SUBCLASS = (1L << 29)
-Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30)
-Py_TPFLAGS_TYPE_SUBCLASS = (1L << 31)
+Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
+Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
+Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
+Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
+Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
+Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
+Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
+Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
MAX_OUTPUT_LEN=1024
@@ -90,32 +100,39 @@ def safety_limit(val):
def safe_range(val):
# As per range, but don't trust the value too much: cap it to a safety
# threshold in case the data was corrupted
- return xrange(safety_limit(val))
-
-def write_unicode(file, text):
- # Write a byte or unicode string to file. Unicode strings are encoded to
- # 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):
- if not isinstance(filename, unicode):
- return filename
- encoding = sys.getfilesystemencoding()
- if encoding == 'mbcs':
- # mbcs doesn't support surrogateescape
- return filename.encode(encoding)
- encoded = []
- for char in filename:
- # surrogateescape error handler
- if 0xDC80 <= ord(char) <= 0xDCFF:
- byte = chr(ord(char) - 0xDC00)
- else:
- byte = char.encode(encoding)
- encoded.append(byte)
- return ''.join(encoded)
+ return xrange(safety_limit(int(val)))
+
+if sys.version_info[0] >= 3:
+ def write_unicode(file, text):
+ file.write(text)
+else:
+ def write_unicode(file, text):
+ # Write a byte or unicode string to file. Unicode strings are encoded to
+ # ENCODING encoding with 'backslashreplace' error handler to avoid
+ # UnicodeEncodeError.
+ if isinstance(text, unicode):
+ text = text.encode(ENCODING, 'backslashreplace')
+ file.write(text)
+
+try:
+ os_fsencode = os.fsencode
+except ImportError:
+ def os_fsencode(filename):
+ if not isinstance(filename, unicode):
+ return filename
+ encoding = sys.getfilesystemencoding()
+ if encoding == 'mbcs':
+ # mbcs doesn't support surrogateescape
+ return filename.encode(encoding)
+ encoded = []
+ for char in filename:
+ # surrogateescape error handler
+ if 0xDC80 <= ord(char) <= 0xDCFF:
+ byte = chr(ord(char) - 0xDC00)
+ else:
+ byte = char.encode(encoding)
+ encoded.append(byte)
+ return ''.join(encoded)
class StringTruncated(RuntimeError):
pass
@@ -322,8 +339,8 @@ class PyObjectPtr(object):
# class
return cls
- #print 'tp_flags = 0x%08x' % tp_flags
- #print 'tp_name = %r' % tp_name
+ #print('tp_flags = 0x%08x' % tp_flags)
+ #print('tp_name = %r' % tp_name)
name_map = {'bool': PyBoolObjectPtr,
'classobj': PyClassObjectPtr,
@@ -733,14 +750,14 @@ class PyLongObjectPtr(PyObjectPtr):
'''
ob_size = long(self.field('ob_size'))
if ob_size == 0:
- return 0L
+ return 0
ob_digit = self.field('ob_digit')
if gdb.lookup_type('digit').sizeof == 2:
- SHIFT = 15L
+ SHIFT = 15
else:
- SHIFT = 30L
+ SHIFT = 30
digits = [long(ob_digit[i]) * 2**(SHIFT*i)
for i in safe_range(abs(ob_size))]
@@ -1595,12 +1612,12 @@ class PyList(gdb.Command):
# py-list requires an actual PyEval_EvalFrameEx frame:
frame = Frame.get_selected_bytecode_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
pyop = frame.get_pyop()
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
filename = pyop.filename()
@@ -1656,9 +1673,9 @@ def move_in_stack(move_up):
frame = iter_frame
if move_up:
- print 'Unable to find an older python frame'
+ print('Unable to find an older python frame')
else:
- print 'Unable to find a newer python frame'
+ print('Unable to find a newer python frame')
class PyUp(gdb.Command):
'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()
if not frame:
- print 'Unable to locate python frame'
+ print('Unable to locate python frame')
return
pyop_frame = frame.get_pyop()
if not pyop_frame:
- print 'Unable to read information on python frame'
+ print('Unable to read information on python frame')
return
pyop_var, scope = pyop_frame.get_var_by_name(name)
if pyop_var:
- print ('%s %r = %s'
+ print('%s %r = %s'
% (scope,
name,
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
else:
- print '%r not found' % name
+ print('%r not found' % name)
PyPrint()
@@ -1774,16 +1791,16 @@ class PyLocals(gdb.Command):
frame = Frame.get_selected_python_frame()
if not frame:
- print 'Unable to locate python frame'
+ print('Unable to locate python frame')
return
pyop_frame = frame.get_pyop()
if not pyop_frame:
- print 'Unable to read information on python frame'
+ print('Unable to read information on python frame')
return
for pyop_name, pyop_value in pyop_frame.iter_locals():
- print ('%s = %s'
+ print('%s = %s'
% (pyop_name.proxyval(set()),
pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))