blob: 27eabcb0d3d0916a929f34b7d91efab8526fde89 [file] [log] [blame]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001#!/usr/bin/python
2'''
3From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
4to be extended with Python code e.g. for library-specific data visualizations,
5such as for the C++ STL types. Documentation on this API can be seen at:
6http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
7
8
9This python module deals with the case when the process being debugged (the
10"inferior process" in gdb parlance) is itself python, or more specifically,
11linked against libpython. In this situation, almost every item of data is a
12(PyObject*), and having the debugger merely print their addresses is not very
13enlightening.
14
15This module embeds knowledge about the implementation details of libpython so
16that we can emit useful visualizations e.g. a string, a list, a dict, a frame
17giving file/line information and the state of local variables
18
19In particular, given a gdb.Value corresponding to a PyObject* in the inferior
20process, we can generate a "proxy value" within the gdb process. For example,
21given a PyObject* in the inferior process that is in fact a PyListObject*
Victor Stinner67df3a42010-04-21 13:53:05 +000022holding three PyObject* that turn out to be PyBytesObject* instances, we can
Martin v. Löwis5ae68102010-04-21 22:38:42 +000023generate a proxy value within the gdb process that is a list of bytes
24instances:
25 [b"foo", b"bar", b"baz"]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000026
27Doing so can be expensive for complicated graphs of objects, and could take
28some time, so we also have a "write_repr" method that writes a representation
29of the data to a file-like object. This allows us to stop the traversal by
30having the file-like object raise an exception if it gets too much data.
31
32With both "proxyval" and "write_repr" we keep track of the set of all addresses
33visited so far in the traversal, to avoid infinite recursion due to cycles in
34the graph of object references.
35
36We try to defer gdb.lookup_type() invocations for python types until as late as
37possible: for a dynamically linked python binary, when the process starts in
38the debugger, the libpython.so hasn't been dynamically loaded yet, so none of
39the type names are known to the debugger
40
41The module also extends gdb with some python-specific commands.
42'''
Antoine Pitroue50240c2013-11-23 17:40:36 +010043
44# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
45# compatible (2.6+ and 3.0+). See #19308.
46
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)a68c1bc2016-09-08 13:47:41 -070047from __future__ import print_function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000048import gdb
Antoine Pitroue50240c2013-11-23 17:40:36 +010049import os
Victor Stinner150016f2010-05-19 23:04:56 +000050import locale
Georg Brandlb639c142010-07-14 08:54:40 +000051import sys
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000052
Antoine Pitroue50240c2013-11-23 17:40:36 +010053if sys.version_info[0] >= 3:
54 unichr = chr
55 xrange = range
56 long = int
57
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000058# Look up the gdb.Type for some standard types:
Victor Stinner4e75ca82016-04-20 18:07:21 +020059# Those need to be refreshed as types (pointer sizes) may change when
60# gdb loads different executables
61
Victor Stinner4e75ca82016-04-20 18:07:21 +020062def _type_char_ptr():
63 return gdb.lookup_type('char').pointer() # char*
64
65
66def _type_unsigned_char_ptr():
67 return gdb.lookup_type('unsigned char').pointer() # unsigned char*
68
69
Victor Stinner4e75ca82016-04-20 18:07:21 +020070def _type_unsigned_short_ptr():
71 return gdb.lookup_type('unsigned short').pointer()
72
73
74def _type_unsigned_int_ptr():
75 return gdb.lookup_type('unsigned int').pointer()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000076
Victor Stinner19620c52016-04-20 18:26:12 +020077
78def _sizeof_void_p():
79 return gdb.lookup_type('void').pointer().sizeof
80
81
Victor Stinner0c4fbff2011-12-08 00:08:22 +010082# value computed later, see PyUnicodeObjectPtr.proxy()
83_is_pep393 = None
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020084
Antoine Pitroue50240c2013-11-23 17:40:36 +010085Py_TPFLAGS_HEAPTYPE = (1 << 9)
Antoine Pitroue50240c2013-11-23 17:40:36 +010086Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
87Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
88Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
89Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
90Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
91Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
92Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
93Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000094
95
96MAX_OUTPUT_LEN=1024
97
Martin v. Löwis5ae68102010-04-21 22:38:42 +000098hexdigits = "0123456789abcdef"
99
Victor Stinner150016f2010-05-19 23:04:56 +0000100ENCODING = locale.getpreferredencoding()
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000101
Łukasz Langa5fe59f82017-08-21 16:40:29 -0700102EVALFRAME = '_PyEval_EvalFrameDefault'
103
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000104class NullPyObjectPtr(RuntimeError):
105 pass
106
107
108def safety_limit(val):
Martin Panter7462b6492015-11-02 03:37:02 +0000109 # Given an integer value from the process being debugged, limit it to some
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000110 # safety threshold so that arbitrary breakage within said process doesn't
111 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
112 return min(val, 1000)
113
114
115def safe_range(val):
116 # As per range, but don't trust the value too much: cap it to a safety
117 # threshold in case the data was corrupted
Antoine Pitroue50240c2013-11-23 17:40:36 +0100118 return xrange(safety_limit(int(val)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000119
Antoine Pitroue50240c2013-11-23 17:40:36 +0100120if sys.version_info[0] >= 3:
121 def write_unicode(file, text):
122 file.write(text)
123else:
124 def write_unicode(file, text):
125 # Write a byte or unicode string to file. Unicode strings are encoded to
126 # ENCODING encoding with 'backslashreplace' error handler to avoid
127 # UnicodeEncodeError.
128 if isinstance(text, unicode):
129 text = text.encode(ENCODING, 'backslashreplace')
130 file.write(text)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000131
Antoine Pitroue50240c2013-11-23 17:40:36 +0100132try:
133 os_fsencode = os.fsencode
Antoine Pitrou23828f62013-11-23 18:20:42 +0100134except AttributeError:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100135 def os_fsencode(filename):
136 if not isinstance(filename, unicode):
137 return filename
138 encoding = sys.getfilesystemencoding()
139 if encoding == 'mbcs':
140 # mbcs doesn't support surrogateescape
141 return filename.encode(encoding)
142 encoded = []
143 for char in filename:
144 # surrogateescape error handler
145 if 0xDC80 <= ord(char) <= 0xDCFF:
146 byte = chr(ord(char) - 0xDC00)
147 else:
148 byte = char.encode(encoding)
149 encoded.append(byte)
150 return ''.join(encoded)
Victor Stinner6ffbee72010-10-17 19:35:30 +0000151
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000152class StringTruncated(RuntimeError):
153 pass
154
155class TruncatedStringIO(object):
Serhiy Storchaka50254c52013-08-29 11:35:43 +0300156 '''Similar to io.StringIO, but can truncate the output by raising a
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000157 StringTruncated exception'''
158 def __init__(self, maxlen=None):
159 self._val = ''
160 self.maxlen = maxlen
161
162 def write(self, data):
163 if self.maxlen:
164 if len(data) + len(self._val) > self.maxlen:
165 # Truncation:
166 self._val += data[0:self.maxlen - len(self._val)]
167 raise StringTruncated()
168
169 self._val += data
170
171 def getvalue(self):
172 return self._val
173
174class PyObjectPtr(object):
175 """
Martin Panter7462b6492015-11-02 03:37:02 +0000176 Class wrapping a gdb.Value that's either a (PyObject*) within the
Victor Stinner67df3a42010-04-21 13:53:05 +0000177 inferior process, or some subclass pointer e.g. (PyBytesObject*)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000178
179 There will be a subclass for every refined PyObject type that we care
180 about.
181
182 Note that at every stage the underlying pointer could be NULL, point
183 to corrupt data, etc; this is the debugger, after all.
184 """
185 _typename = 'PyObject'
186
187 def __init__(self, gdbval, cast_to=None):
188 if cast_to:
189 self._gdbval = gdbval.cast(cast_to)
190 else:
191 self._gdbval = gdbval
192
193 def field(self, name):
194 '''
195 Get the gdb.Value for the given field within the PyObject, coping with
196 some python 2 versus python 3 differences.
197
198 Various libpython types are defined using the "PyObject_HEAD" and
199 "PyObject_VAR_HEAD" macros.
200
201 In Python 2, this these are defined so that "ob_type" and (for a var
202 object) "ob_size" are fields of the type in question.
203
204 In Python 3, this is defined as an embedded PyVarObject type thus:
205 PyVarObject ob_base;
206 so that the "ob_size" field is located insize the "ob_base" field, and
207 the "ob_type" is most easily accessed by casting back to a (PyObject*).
208 '''
209 if self.is_null():
210 raise NullPyObjectPtr(self)
211
212 if name == 'ob_type':
213 pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
214 return pyo_ptr.dereference()[name]
215
216 if name == 'ob_size':
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000217 pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
218 return pyo_ptr.dereference()[name]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000219
220 # General case: look it up inside the object:
221 return self._gdbval.dereference()[name]
222
223 def pyop_field(self, name):
224 '''
225 Get a PyObjectPtr for the given PyObject* field within this PyObject,
226 coping with some python 2 versus python 3 differences.
227 '''
228 return PyObjectPtr.from_pyobject_ptr(self.field(name))
229
230 def write_field_repr(self, name, out, visited):
231 '''
232 Extract the PyObject* field named "name", and write its representation
233 to file-like object "out"
234 '''
235 field_obj = self.pyop_field(name)
236 field_obj.write_repr(out, visited)
237
238 def get_truncated_repr(self, maxlen):
239 '''
240 Get a repr-like string for the data, but truncate it at "maxlen" bytes
241 (ending the object graph traversal as soon as you do)
242 '''
243 out = TruncatedStringIO(maxlen)
244 try:
245 self.write_repr(out, set())
246 except StringTruncated:
247 # Truncation occurred:
248 return out.getvalue() + '...(truncated)'
249
250 # No truncation occurred:
251 return out.getvalue()
252
253 def type(self):
254 return PyTypeObjectPtr(self.field('ob_type'))
255
256 def is_null(self):
257 return 0 == long(self._gdbval)
258
259 def is_optimized_out(self):
260 '''
261 Is the value of the underlying PyObject* visible to the debugger?
262
263 This can vary with the precise version of the compiler used to build
264 Python, and the precise version of gdb.
265
266 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
267 PyEval_EvalFrameEx's "f"
268 '''
269 return self._gdbval.is_optimized_out
270
271 def safe_tp_name(self):
272 try:
Victor Stinnerd22fc0b2018-06-14 22:34:52 +0200273 ob_type = self.type()
274 tp_name = ob_type.field('tp_name')
275 return tp_name.string()
276 # NullPyObjectPtr: NULL tp_name?
277 # RuntimeError: Can't even read the object at all?
278 # UnicodeDecodeError: Failed to decode tp_name bytestring
279 except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000280 return 'unknown'
281
282 def proxyval(self, visited):
283 '''
284 Scrape a value from the inferior process, and try to represent it
285 within the gdb process, whilst (hopefully) avoiding crashes when
286 the remote data is corrupt.
287
288 Derived classes will override this.
289
290 For example, a PyIntObject* with ob_ival 42 in the inferior process
291 should result in an int(42) in this process.
292
293 visited: a set of all gdb.Value pyobject pointers already visited
294 whilst generating this value (to guard against infinite recursion when
295 visiting object graphs with loops). Analogous to Py_ReprEnter and
296 Py_ReprLeave
297 '''
298
299 class FakeRepr(object):
300 """
301 Class representing a non-descript PyObject* value in the inferior
302 process for when we don't have a custom scraper, intended to have
303 a sane repr().
304 """
305
306 def __init__(self, tp_name, address):
307 self.tp_name = tp_name
308 self.address = address
309
310 def __repr__(self):
311 # For the NULL pointer, we have no way of knowing a type, so
312 # special-case it as per
313 # http://bugs.python.org/issue8032#msg100882
314 if self.address == 0:
315 return '0x0'
316 return '<%s at remote 0x%x>' % (self.tp_name, self.address)
317
318 return FakeRepr(self.safe_tp_name(),
319 long(self._gdbval))
320
321 def write_repr(self, out, visited):
322 '''
323 Write a string representation of the value scraped from the inferior
324 process to "out", a file-like object.
325 '''
326 # Default implementation: generate a proxy value and write its repr
327 # However, this could involve a lot of work for complicated objects,
328 # so for derived classes we specialize this
329 return out.write(repr(self.proxyval(visited)))
330
331 @classmethod
332 def subclass_from_type(cls, t):
333 '''
334 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
335 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
336 to use
337
338 Ideally, we would look up the symbols for the global types, but that
339 isn't working yet:
340 (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
341 Traceback (most recent call last):
342 File "<string>", line 1, in <module>
343 NotImplementedError: Symbol type not yet supported in Python scripts.
344 Error while executing Python code.
345
346 For now, we use tp_flags, after doing some string comparisons on the
347 tp_name for some special-cases that don't seem to be visible through
348 flags
349 '''
350 try:
351 tp_name = t.field('tp_name').string()
352 tp_flags = int(t.field('tp_flags'))
Victor Stinnerd22fc0b2018-06-14 22:34:52 +0200353 # RuntimeError: NULL pointers
354 # UnicodeDecodeError: string() fails to decode the bytestring
355 except (RuntimeError, UnicodeDecodeError):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000356 # Handle any kind of error e.g. NULL ptrs by simply using the base
357 # class
358 return cls
359
Antoine Pitroue50240c2013-11-23 17:40:36 +0100360 #print('tp_flags = 0x%08x' % tp_flags)
361 #print('tp_name = %r' % tp_name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000362
363 name_map = {'bool': PyBoolObjectPtr,
364 'classobj': PyClassObjectPtr,
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000365 'NoneType': PyNoneStructPtr,
366 'frame': PyFrameObjectPtr,
367 'set' : PySetObjectPtr,
368 'frozenset' : PySetObjectPtr,
369 'builtin_function_or_method' : PyCFunctionObjectPtr,
Victor Stinner61108332017-02-01 16:29:54 +0100370 'method-wrapper': wrapperobject,
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000371 }
372 if tp_name in name_map:
373 return name_map[tp_name]
374
375 if tp_flags & Py_TPFLAGS_HEAPTYPE:
376 return HeapTypeObjectPtr
377
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000378 if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
379 return PyLongObjectPtr
380 if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
381 return PyListObjectPtr
382 if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
383 return PyTupleObjectPtr
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000384 if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
Victor Stinner67df3a42010-04-21 13:53:05 +0000385 return PyBytesObjectPtr
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000386 if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
387 return PyUnicodeObjectPtr
388 if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
389 return PyDictObjectPtr
390 if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
391 return PyBaseExceptionObjectPtr
392 #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
393 # return PyTypeObjectPtr
394
395 # Use the base class:
396 return cls
397
398 @classmethod
399 def from_pyobject_ptr(cls, gdbval):
400 '''
401 Try to locate the appropriate derived class dynamically, and cast
402 the pointer accordingly.
403 '''
404 try:
405 p = PyObjectPtr(gdbval)
406 cls = cls.subclass_from_type(p.type())
407 return cls(gdbval, cast_to=cls.get_gdb_type())
408 except RuntimeError:
409 # Handle any kind of error e.g. NULL ptrs by simply using the base
410 # class
411 pass
412 return cls(gdbval)
413
414 @classmethod
415 def get_gdb_type(cls):
416 return gdb.lookup_type(cls._typename).pointer()
417
418 def as_address(self):
419 return long(self._gdbval)
420
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000421class PyVarObjectPtr(PyObjectPtr):
422 _typename = 'PyVarObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000423
424class ProxyAlreadyVisited(object):
425 '''
426 Placeholder proxy to use when protecting against infinite recursion due to
427 loops in the object graph.
428
429 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
430 '''
431 def __init__(self, rep):
432 self._rep = rep
433
434 def __repr__(self):
435 return self._rep
436
437
438def _write_instance_repr(out, visited, name, pyop_attrdict, address):
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100439 '''Shared code for use by all classes:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000440 write a representation to file-like object "out"'''
441 out.write('<')
442 out.write(name)
443
444 # Write dictionary of instance attributes:
445 if isinstance(pyop_attrdict, PyDictObjectPtr):
446 out.write('(')
447 first = True
448 for pyop_arg, pyop_val in pyop_attrdict.iteritems():
449 if not first:
450 out.write(', ')
451 first = False
452 out.write(pyop_arg.proxyval(visited))
453 out.write('=')
454 pyop_val.write_repr(out, visited)
455 out.write(')')
456 out.write(' at remote 0x%x>' % address)
457
458
459class InstanceProxy(object):
460
461 def __init__(self, cl_name, attrdict, address):
462 self.cl_name = cl_name
463 self.attrdict = attrdict
464 self.address = address
465
466 def __repr__(self):
467 if isinstance(self.attrdict, dict):
468 kwargs = ', '.join(["%s=%r" % (arg, val)
469 for arg, val in self.attrdict.iteritems()])
470 return '<%s(%s) at remote 0x%x>' % (self.cl_name,
471 kwargs, self.address)
472 else:
473 return '<%s at remote 0x%x>' % (self.cl_name,
474 self.address)
475
476def _PyObject_VAR_SIZE(typeobj, nitems):
Victor Stinnerd2084162011-12-19 13:42:24 +0100477 if _PyObject_VAR_SIZE._type_size_t is None:
478 _PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t')
479
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000480 return ( ( typeobj.field('tp_basicsize') +
481 nitems * typeobj.field('tp_itemsize') +
Victor Stinner4e75ca82016-04-20 18:07:21 +0200482 (_sizeof_void_p() - 1)
483 ) & ~(_sizeof_void_p() - 1)
Victor Stinnerd2084162011-12-19 13:42:24 +0100484 ).cast(_PyObject_VAR_SIZE._type_size_t)
485_PyObject_VAR_SIZE._type_size_t = None
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000486
487class HeapTypeObjectPtr(PyObjectPtr):
488 _typename = 'PyObject'
489
490 def get_attr_dict(self):
491 '''
492 Get the PyDictObject ptr representing the attribute dictionary
493 (or None if there's a problem)
494 '''
495 try:
496 typeobj = self.type()
497 dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
498 if dictoffset != 0:
499 if dictoffset < 0:
500 type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
501 tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
502 if tsize < 0:
503 tsize = -tsize
504 size = _PyObject_VAR_SIZE(typeobj, tsize)
505 dictoffset += size
506 assert dictoffset > 0
Victor Stinner4e75ca82016-04-20 18:07:21 +0200507 assert dictoffset % _sizeof_void_p() == 0
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000508
Victor Stinner4e75ca82016-04-20 18:07:21 +0200509 dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000510 PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
511 dictptr = dictptr.cast(PyObjectPtrPtr)
512 return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
513 except RuntimeError:
514 # Corrupt data somewhere; fail safe
515 pass
516
517 # Not found, or some kind of error:
518 return None
519
520 def proxyval(self, visited):
521 '''
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100522 Support for classes.
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000523
524 Currently we just locate the dictionary using a transliteration to
525 python of _PyObject_GetDictPtr, ignoring descriptors
526 '''
527 # Guard against infinite loops:
528 if self.as_address() in visited:
529 return ProxyAlreadyVisited('<...>')
530 visited.add(self.as_address())
531
532 pyop_attr_dict = self.get_attr_dict()
533 if pyop_attr_dict:
534 attr_dict = pyop_attr_dict.proxyval(visited)
535 else:
536 attr_dict = {}
537 tp_name = self.safe_tp_name()
538
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100539 # Class:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000540 return InstanceProxy(tp_name, attr_dict, long(self._gdbval))
541
542 def write_repr(self, out, visited):
543 # Guard against infinite loops:
544 if self.as_address() in visited:
545 out.write('<...>')
546 return
547 visited.add(self.as_address())
548
549 pyop_attrdict = self.get_attr_dict()
550 _write_instance_repr(out, visited,
551 self.safe_tp_name(), pyop_attrdict, self.as_address())
552
553class ProxyException(Exception):
554 def __init__(self, tp_name, args):
555 self.tp_name = tp_name
556 self.args = args
557
558 def __repr__(self):
559 return '%s%r' % (self.tp_name, self.args)
560
561class PyBaseExceptionObjectPtr(PyObjectPtr):
562 """
563 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
564 within the process being debugged.
565 """
566 _typename = 'PyBaseExceptionObject'
567
568 def proxyval(self, visited):
569 # Guard against infinite loops:
570 if self.as_address() in visited:
571 return ProxyAlreadyVisited('(...)')
572 visited.add(self.as_address())
573 arg_proxy = self.pyop_field('args').proxyval(visited)
574 return ProxyException(self.safe_tp_name(),
575 arg_proxy)
576
577 def write_repr(self, out, visited):
578 # Guard against infinite loops:
579 if self.as_address() in visited:
580 out.write('(...)')
581 return
582 visited.add(self.as_address())
583
584 out.write(self.safe_tp_name())
585 self.write_field_repr('args', out, visited)
586
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000587class PyClassObjectPtr(PyObjectPtr):
588 """
589 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
590 instance within the process being debugged.
591 """
592 _typename = 'PyClassObject'
593
594
595class BuiltInFunctionProxy(object):
596 def __init__(self, ml_name):
597 self.ml_name = ml_name
598
599 def __repr__(self):
600 return "<built-in function %s>" % self.ml_name
601
602class BuiltInMethodProxy(object):
603 def __init__(self, ml_name, pyop_m_self):
604 self.ml_name = ml_name
605 self.pyop_m_self = pyop_m_self
606
607 def __repr__(self):
608 return ('<built-in method %s of %s object at remote 0x%x>'
609 % (self.ml_name,
610 self.pyop_m_self.safe_tp_name(),
611 self.pyop_m_self.as_address())
612 )
613
614class PyCFunctionObjectPtr(PyObjectPtr):
615 """
616 Class wrapping a gdb.Value that's a PyCFunctionObject*
617 (see Include/methodobject.h and Objects/methodobject.c)
618 """
619 _typename = 'PyCFunctionObject'
620
621 def proxyval(self, visited):
622 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
Victor Stinnerd22fc0b2018-06-14 22:34:52 +0200623 try:
624 ml_name = m_ml['ml_name'].string()
625 except UnicodeDecodeError:
626 ml_name = '<ml_name:UnicodeDecodeError>'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000627
628 pyop_m_self = self.pyop_field('m_self')
629 if pyop_m_self.is_null():
630 return BuiltInFunctionProxy(ml_name)
631 else:
632 return BuiltInMethodProxy(ml_name, pyop_m_self)
633
634
635class PyCodeObjectPtr(PyObjectPtr):
636 """
637 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
638 within the process being debugged.
639 """
640 _typename = 'PyCodeObject'
641
642 def addr2line(self, addrq):
643 '''
644 Get the line number for a given bytecode offset
645
646 Analogous to PyCode_Addr2Line; translated from pseudocode in
647 Objects/lnotab_notes.txt
648 '''
649 co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
650
651 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
652 # not 0, as lnotab_notes.txt has it:
653 lineno = int_from_int(self.field('co_firstlineno'))
654
655 addr = 0
656 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
657 addr += ord(addr_incr)
658 if addr > addrq:
659 return lineno
660 lineno += ord(line_incr)
661 return lineno
662
663
664class PyDictObjectPtr(PyObjectPtr):
665 """
666 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
667 within the process being debugged.
668 """
669 _typename = 'PyDictObject'
670
671 def iteritems(self):
672 '''
673 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
Ezio Melotti7c4a7e62013-08-26 01:32:56 +0300674 analogous to dict.iteritems()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000675 '''
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400676 keys = self.field('ma_keys')
677 values = self.field('ma_values')
INADA Naokid7d2bc82016-11-22 19:40:58 +0900678 entries, nentries = self._get_entries(keys)
679 for i in safe_range(nentries):
680 ep = entries[i]
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400681 if long(values):
682 pyop_value = PyObjectPtr.from_pyobject_ptr(values[i])
683 else:
684 pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000685 if not pyop_value.is_null():
686 pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
687 yield (pyop_key, pyop_value)
688
689 def proxyval(self, visited):
690 # Guard against infinite loops:
691 if self.as_address() in visited:
692 return ProxyAlreadyVisited('{...}')
693 visited.add(self.as_address())
694
695 result = {}
696 for pyop_key, pyop_value in self.iteritems():
697 proxy_key = pyop_key.proxyval(visited)
698 proxy_value = pyop_value.proxyval(visited)
699 result[proxy_key] = proxy_value
700 return result
701
702 def write_repr(self, out, visited):
703 # Guard against infinite loops:
704 if self.as_address() in visited:
705 out.write('{...}')
706 return
707 visited.add(self.as_address())
708
709 out.write('{')
710 first = True
711 for pyop_key, pyop_value in self.iteritems():
712 if not first:
713 out.write(', ')
714 first = False
715 pyop_key.write_repr(out, visited)
716 out.write(': ')
717 pyop_value.write_repr(out, visited)
718 out.write('}')
719
INADA Naokid7d2bc82016-11-22 19:40:58 +0900720 def _get_entries(self, keys):
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100721 dk_nentries = int(keys['dk_nentries'])
INADA Naokid7d2bc82016-11-22 19:40:58 +0900722 dk_size = int(keys['dk_size'])
723 try:
724 # <= Python 3.5
725 return keys['dk_entries'], dk_size
Lev Abalkin661ca882017-03-01 13:16:23 -0500726 except RuntimeError:
INADA Naokid7d2bc82016-11-22 19:40:58 +0900727 # >= Python 3.6
728 pass
729
730 if dk_size <= 0xFF:
731 offset = dk_size
732 elif dk_size <= 0xFFFF:
733 offset = 2 * dk_size
734 elif dk_size <= 0xFFFFFFFF:
735 offset = 4 * dk_size
736 else:
737 offset = 8 * dk_size
738
Gregory P. Smith53f67d42018-04-20 11:32:08 -0700739 ent_addr = keys['dk_indices'].address
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100740 ent_addr = ent_addr.cast(_type_unsigned_char_ptr()) + offset
INADA Naokid7d2bc82016-11-22 19:40:58 +0900741 ent_ptr_t = gdb.lookup_type('PyDictKeyEntry').pointer()
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100742 ent_addr = ent_addr.cast(ent_ptr_t)
743
744 return ent_addr, dk_nentries
INADA Naokid7d2bc82016-11-22 19:40:58 +0900745
746
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000747class PyListObjectPtr(PyObjectPtr):
748 _typename = 'PyListObject'
749
750 def __getitem__(self, i):
751 # Get the gdb.Value for the (PyObject*) with the given index:
752 field_ob_item = self.field('ob_item')
753 return field_ob_item[i]
754
755 def proxyval(self, visited):
756 # Guard against infinite loops:
757 if self.as_address() in visited:
758 return ProxyAlreadyVisited('[...]')
759 visited.add(self.as_address())
760
761 result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
762 for i in safe_range(int_from_int(self.field('ob_size')))]
763 return result
764
765 def write_repr(self, out, visited):
766 # Guard against infinite loops:
767 if self.as_address() in visited:
768 out.write('[...]')
769 return
770 visited.add(self.as_address())
771
772 out.write('[')
773 for i in safe_range(int_from_int(self.field('ob_size'))):
774 if i > 0:
775 out.write(', ')
776 element = PyObjectPtr.from_pyobject_ptr(self[i])
777 element.write_repr(out, visited)
778 out.write(']')
779
780class PyLongObjectPtr(PyObjectPtr):
781 _typename = 'PyLongObject'
782
783 def proxyval(self, visited):
784 '''
785 Python's Include/longobjrep.h has this declaration:
786 struct _longobject {
787 PyObject_VAR_HEAD
788 digit ob_digit[1];
789 };
790
791 with this description:
792 The absolute value of a number is equal to
793 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
794 Negative numbers are represented with ob_size < 0;
795 zero is represented by ob_size == 0.
796
797 where SHIFT can be either:
798 #define PyLong_SHIFT 30
799 #define PyLong_SHIFT 15
800 '''
801 ob_size = long(self.field('ob_size'))
802 if ob_size == 0:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100803 return 0
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000804
805 ob_digit = self.field('ob_digit')
806
807 if gdb.lookup_type('digit').sizeof == 2:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100808 SHIFT = 15
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000809 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100810 SHIFT = 30
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000811
812 digits = [long(ob_digit[i]) * 2**(SHIFT*i)
813 for i in safe_range(abs(ob_size))]
814 result = sum(digits)
815 if ob_size < 0:
816 result = -result
817 return result
818
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000819 def write_repr(self, out, visited):
820 # Write this out as a Python 3 int literal, i.e. without the "L" suffix
821 proxy = self.proxyval(visited)
822 out.write("%s" % proxy)
823
824
825class PyBoolObjectPtr(PyLongObjectPtr):
826 """
827 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
828 <bool> instances (Py_True/Py_False) within the process being debugged.
829 """
830 def proxyval(self, visited):
831 if PyLongObjectPtr.proxyval(self, visited):
832 return True
833 else:
834 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000835
836class PyNoneStructPtr(PyObjectPtr):
837 """
838 Class wrapping a gdb.Value that's a PyObject* pointing to the
839 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
840 """
841 _typename = 'PyObject'
842
843 def proxyval(self, visited):
844 return None
845
846
847class PyFrameObjectPtr(PyObjectPtr):
848 _typename = 'PyFrameObject'
849
Victor Stinnerd2084162011-12-19 13:42:24 +0100850 def __init__(self, gdbval, cast_to=None):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000851 PyObjectPtr.__init__(self, gdbval, cast_to)
852
853 if not self.is_optimized_out():
854 self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
855 self.co_name = self.co.pyop_field('co_name')
856 self.co_filename = self.co.pyop_field('co_filename')
857
858 self.f_lineno = int_from_int(self.field('f_lineno'))
859 self.f_lasti = int_from_int(self.field('f_lasti'))
860 self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
861 self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
862
863 def iter_locals(self):
864 '''
865 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
866 the local variables of this frame
867 '''
868 if self.is_optimized_out():
869 return
870
871 f_localsplus = self.field('f_localsplus')
872 for i in safe_range(self.co_nlocals):
873 pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
874 if not pyop_value.is_null():
875 pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
876 yield (pyop_name, pyop_value)
877
878 def iter_globals(self):
879 '''
880 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
881 the global variables of this frame
882 '''
883 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100884 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000885
886 pyop_globals = self.pyop_field('f_globals')
887 return pyop_globals.iteritems()
888
889 def iter_builtins(self):
890 '''
891 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
892 the builtin variables
893 '''
894 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100895 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000896
897 pyop_builtins = self.pyop_field('f_builtins')
898 return pyop_builtins.iteritems()
899
900 def get_var_by_name(self, name):
901 '''
902 Look for the named local variable, returning a (PyObjectPtr, scope) pair
903 where scope is a string 'local', 'global', 'builtin'
904
905 If not found, return (None, None)
906 '''
907 for pyop_name, pyop_value in self.iter_locals():
908 if name == pyop_name.proxyval(set()):
909 return pyop_value, 'local'
910 for pyop_name, pyop_value in self.iter_globals():
911 if name == pyop_name.proxyval(set()):
912 return pyop_value, 'global'
913 for pyop_name, pyop_value in self.iter_builtins():
914 if name == pyop_name.proxyval(set()):
915 return pyop_value, 'builtin'
916 return None, None
917
918 def filename(self):
919 '''Get the path of the current Python source file, as a string'''
920 if self.is_optimized_out():
921 return '(frame information optimized out)'
922 return self.co_filename.proxyval(set())
923
924 def current_line_num(self):
925 '''Get current line number as an integer (1-based)
926
927 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
928
929 See Objects/lnotab_notes.txt
930 '''
931 if self.is_optimized_out():
932 return None
933 f_trace = self.field('f_trace')
934 if long(f_trace) != 0:
935 # we have a non-NULL f_trace:
936 return self.f_lineno
937 else:
938 #try:
939 return self.co.addr2line(self.f_lasti)
940 #except ValueError:
941 # return self.f_lineno
942
943 def current_line(self):
944 '''Get the text of the current source line as a string, with a trailing
945 newline character'''
946 if self.is_optimized_out():
947 return '(frame information optimized out)'
Victor Stinner6ffbee72010-10-17 19:35:30 +0000948 filename = self.filename()
Victor Stinnerd57c5c82011-07-01 12:57:44 +0200949 try:
950 f = open(os_fsencode(filename), 'r')
951 except IOError:
952 return None
953 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000954 all_lines = f.readlines()
955 # Convert from 1-based current_line_num to 0-based list offset:
956 return all_lines[self.current_line_num()-1]
957
958 def write_repr(self, out, visited):
959 if self.is_optimized_out():
960 out.write('(frame information optimized out)')
961 return
962 out.write('Frame 0x%x, for file %s, line %i, in %s ('
963 % (self.as_address(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000964 self.co_filename.proxyval(visited),
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000965 self.current_line_num(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000966 self.co_name.proxyval(visited)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000967 first = True
968 for pyop_name, pyop_value in self.iter_locals():
969 if not first:
970 out.write(', ')
971 first = False
972
973 out.write(pyop_name.proxyval(visited))
974 out.write('=')
975 pyop_value.write_repr(out, visited)
976
977 out.write(')')
978
Victor Stinnere670c882011-05-13 17:40:15 +0200979 def print_traceback(self):
980 if self.is_optimized_out():
981 sys.stdout.write(' (frame information optimized out)\n')
Victor Stinnerd2084162011-12-19 13:42:24 +0100982 return
Victor Stinnere670c882011-05-13 17:40:15 +0200983 visited = set()
984 sys.stdout.write(' File "%s", line %i, in %s\n'
985 % (self.co_filename.proxyval(visited),
986 self.current_line_num(),
987 self.co_name.proxyval(visited)))
988
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000989class PySetObjectPtr(PyObjectPtr):
990 _typename = 'PySetObject'
991
Antoine Pitrou9d952542013-08-24 21:07:07 +0200992 @classmethod
993 def _dummy_key(self):
994 return gdb.lookup_global_symbol('_PySet_Dummy').value()
995
996 def __iter__(self):
997 dummy_ptr = self._dummy_key()
998 table = self.field('table')
999 for i in safe_range(self.field('mask') + 1):
1000 setentry = table[i]
1001 key = setentry['key']
1002 if key != 0 and key != dummy_ptr:
1003 yield PyObjectPtr.from_pyobject_ptr(key)
1004
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001005 def proxyval(self, visited):
1006 # Guard against infinite loops:
1007 if self.as_address() in visited:
1008 return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
1009 visited.add(self.as_address())
1010
Antoine Pitrou9d952542013-08-24 21:07:07 +02001011 members = (key.proxyval(visited) for key in self)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001012 if self.safe_tp_name() == 'frozenset':
1013 return frozenset(members)
1014 else:
1015 return set(members)
1016
1017 def write_repr(self, out, visited):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001018 # Emulate Python 3's set_repr
1019 tp_name = self.safe_tp_name()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001020
1021 # Guard against infinite loops:
1022 if self.as_address() in visited:
1023 out.write('(...)')
1024 return
1025 visited.add(self.as_address())
1026
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001027 # Python 3's set_repr special-cases the empty set:
1028 if not self.field('used'):
1029 out.write(tp_name)
1030 out.write('()')
1031 return
1032
1033 # Python 3 uses {} for set literals:
1034 if tp_name != 'set':
1035 out.write(tp_name)
1036 out.write('(')
1037
1038 out.write('{')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001039 first = True
Antoine Pitrou9d952542013-08-24 21:07:07 +02001040 for key in self:
1041 if not first:
1042 out.write(', ')
1043 first = False
1044 key.write_repr(out, visited)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001045 out.write('}')
1046
1047 if tp_name != 'set':
1048 out.write(')')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001049
1050
Victor Stinner67df3a42010-04-21 13:53:05 +00001051class PyBytesObjectPtr(PyObjectPtr):
1052 _typename = 'PyBytesObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001053
1054 def __str__(self):
1055 field_ob_size = self.field('ob_size')
1056 field_ob_sval = self.field('ob_sval')
Victor Stinner4e75ca82016-04-20 18:07:21 +02001057 char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001058 return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1059
1060 def proxyval(self, visited):
1061 return str(self)
1062
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001063 def write_repr(self, out, visited):
1064 # Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1065
1066 # Get a PyStringObject* within the Python 2 gdb process:
1067 proxy = self.proxyval(visited)
1068
1069 # Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1070 # to Python 2 code:
1071 quote = "'"
1072 if "'" in proxy and not '"' in proxy:
1073 quote = '"'
1074 out.write('b')
1075 out.write(quote)
1076 for byte in proxy:
1077 if byte == quote or byte == '\\':
1078 out.write('\\')
1079 out.write(byte)
1080 elif byte == '\t':
1081 out.write('\\t')
1082 elif byte == '\n':
1083 out.write('\\n')
1084 elif byte == '\r':
1085 out.write('\\r')
1086 elif byte < ' ' or ord(byte) >= 0x7f:
1087 out.write('\\x')
1088 out.write(hexdigits[(ord(byte) & 0xf0) >> 4])
1089 out.write(hexdigits[ord(byte) & 0xf])
1090 else:
1091 out.write(byte)
1092 out.write(quote)
1093
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001094class PyTupleObjectPtr(PyObjectPtr):
1095 _typename = 'PyTupleObject'
1096
1097 def __getitem__(self, i):
1098 # Get the gdb.Value for the (PyObject*) with the given index:
1099 field_ob_item = self.field('ob_item')
1100 return field_ob_item[i]
1101
1102 def proxyval(self, visited):
1103 # Guard against infinite loops:
1104 if self.as_address() in visited:
1105 return ProxyAlreadyVisited('(...)')
1106 visited.add(self.as_address())
1107
Jon Dufresne39726282017-05-18 07:35:54 -07001108 result = tuple(PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1109 for i in safe_range(int_from_int(self.field('ob_size'))))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001110 return result
1111
1112 def write_repr(self, out, visited):
1113 # Guard against infinite loops:
1114 if self.as_address() in visited:
1115 out.write('(...)')
1116 return
1117 visited.add(self.as_address())
1118
1119 out.write('(')
1120 for i in safe_range(int_from_int(self.field('ob_size'))):
1121 if i > 0:
1122 out.write(', ')
1123 element = PyObjectPtr.from_pyobject_ptr(self[i])
1124 element.write_repr(out, visited)
1125 if self.field('ob_size') == 1:
1126 out.write(',)')
1127 else:
1128 out.write(')')
1129
1130class PyTypeObjectPtr(PyObjectPtr):
1131 _typename = 'PyTypeObject'
1132
1133
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001134def _unichr_is_printable(char):
1135 # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1136 if char == u" ":
1137 return True
1138 import unicodedata
Antoine Pitroub41e1282010-09-08 20:57:48 +00001139 return unicodedata.category(char) not in ("C", "Z")
1140
1141if sys.maxunicode >= 0x10000:
1142 _unichr = unichr
1143else:
1144 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1145 def _unichr(x):
1146 if x < 0x10000:
1147 return unichr(x)
1148 x -= 0x10000
1149 ch1 = 0xD800 | (x >> 10)
1150 ch2 = 0xDC00 | (x & 0x3FF)
1151 return unichr(ch1) + unichr(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001152
1153
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001154class PyUnicodeObjectPtr(PyObjectPtr):
1155 _typename = 'PyUnicodeObject'
1156
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001157 def char_width(self):
1158 _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1159 return _type_Py_UNICODE.sizeof
1160
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001161 def proxyval(self, visited):
Victor Stinner0c4fbff2011-12-08 00:08:22 +01001162 global _is_pep393
1163 if _is_pep393 is None:
1164 fields = gdb.lookup_type('PyUnicodeObject').target().fields()
1165 _is_pep393 = 'data' in [f.name for f in fields]
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001166 if _is_pep393:
1167 # Python 3.3 and newer
1168 may_have_surrogates = False
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001169 compact = self.field('_base')
1170 ascii = compact['_base']
1171 state = ascii['state']
Victor Stinnera3b334d2011-10-03 13:53:37 +02001172 is_compact_ascii = (int(state['ascii']) and int(state['compact']))
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001173 if not int(state['ready']):
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001174 # string is not ready
Victor Stinnerf16a3502011-11-04 22:34:01 +01001175 field_length = long(compact['wstr_length'])
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001176 may_have_surrogates = True
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001177 field_str = ascii['wstr']
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001178 else:
Victor Stinnerf16a3502011-11-04 22:34:01 +01001179 field_length = long(ascii['length'])
Victor Stinnera3b334d2011-10-03 13:53:37 +02001180 if is_compact_ascii:
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001181 field_str = ascii.address + 1
1182 elif int(state['compact']):
1183 field_str = compact.address + 1
1184 else:
1185 field_str = self.field('data')['any']
1186 repr_kind = int(state['kind'])
1187 if repr_kind == 1:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001188 field_str = field_str.cast(_type_unsigned_char_ptr())
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001189 elif repr_kind == 2:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001190 field_str = field_str.cast(_type_unsigned_short_ptr())
Antoine Pitrou3c0c5f22011-10-08 19:33:24 +02001191 elif repr_kind == 4:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001192 field_str = field_str.cast(_type_unsigned_int_ptr())
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001193 else:
1194 # Python 3.2 and earlier
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001195 field_length = long(self.field('length'))
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001196 field_str = self.field('str')
1197 may_have_surrogates = self.char_width() == 2
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001198
1199 # Gather a list of ints from the Py_UNICODE array; these are either
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001200 # UCS-1, UCS-2 or UCS-4 code points:
1201 if not may_have_surrogates:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001202 Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1203 else:
1204 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1205 # inferior process: we must join surrogate pairs.
1206 Py_UNICODEs = []
1207 i = 0
Antoine Pitroub1856d72010-09-08 21:07:40 +00001208 limit = safety_limit(field_length)
1209 while i < limit:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001210 ucs = int(field_str[i])
1211 i += 1
1212 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1213 Py_UNICODEs.append(ucs)
1214 continue
1215 # This could be a surrogate pair.
1216 ucs2 = int(field_str[i])
1217 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1218 continue
1219 code = (ucs & 0x03FF) << 10
1220 code |= ucs2 & 0x03FF
1221 code += 0x00010000
1222 Py_UNICODEs.append(code)
1223 i += 1
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001224
1225 # Convert the int code points to unicode characters, and generate a
Antoine Pitroub41e1282010-09-08 20:57:48 +00001226 # local unicode instance.
1227 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
Victor Stinnerd8a5cc92013-04-11 21:37:45 +02001228 result = u''.join([
1229 (_unichr(ucs) if ucs <= 0x10ffff else '\ufffd')
1230 for ucs in Py_UNICODEs])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001231 return result
1232
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001233 def write_repr(self, out, visited):
1234 # Write this out as a Python 3 str literal, i.e. without a "u" prefix
1235
1236 # Get a PyUnicodeObject* within the Python 2 gdb process:
1237 proxy = self.proxyval(visited)
1238
1239 # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1240 # to Python 2:
1241 if "'" in proxy and '"' not in proxy:
1242 quote = '"'
1243 else:
1244 quote = "'"
1245 out.write(quote)
1246
1247 i = 0
1248 while i < len(proxy):
1249 ch = proxy[i]
1250 i += 1
1251
1252 # Escape quotes and backslashes
1253 if ch == quote or ch == '\\':
1254 out.write('\\')
1255 out.write(ch)
1256
1257 # Map special whitespace to '\t', \n', '\r'
1258 elif ch == '\t':
1259 out.write('\\t')
1260 elif ch == '\n':
1261 out.write('\\n')
1262 elif ch == '\r':
1263 out.write('\\r')
1264
1265 # Map non-printable US ASCII to '\xhh' */
1266 elif ch < ' ' or ch == 0x7F:
1267 out.write('\\x')
1268 out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
1269 out.write(hexdigits[ord(ch) & 0x000F])
1270
1271 # Copy ASCII characters as-is
1272 elif ord(ch) < 0x7F:
1273 out.write(ch)
1274
1275 # Non-ASCII characters
1276 else:
Victor Stinner150016f2010-05-19 23:04:56 +00001277 ucs = ch
Antoine Pitroub41e1282010-09-08 20:57:48 +00001278 ch2 = None
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001279 if sys.maxunicode < 0x10000:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001280 # If sizeof(Py_UNICODE) is 2 here (in gdb), join
1281 # surrogate pairs before calling _unichr_is_printable.
Victor Stinner150016f2010-05-19 23:04:56 +00001282 if (i < len(proxy)
1283 and 0xD800 <= ord(ch) < 0xDC00 \
1284 and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001285 ch2 = proxy[i]
Antoine Pitroub41e1282010-09-08 20:57:48 +00001286 ucs = ch + ch2
Victor Stinner150016f2010-05-19 23:04:56 +00001287 i += 1
Victor Stinner150016f2010-05-19 23:04:56 +00001288
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001289 # Unfortuately, Python 2's unicode type doesn't seem
1290 # to expose the "isprintable" method
Victor Stinner150016f2010-05-19 23:04:56 +00001291 printable = _unichr_is_printable(ucs)
1292 if printable:
1293 try:
1294 ucs.encode(ENCODING)
1295 except UnicodeEncodeError:
1296 printable = False
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001297
1298 # Map Unicode whitespace and control characters
1299 # (categories Z* and C* except ASCII space)
Victor Stinner150016f2010-05-19 23:04:56 +00001300 if not printable:
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001301 if ch2 is not None:
1302 # Match Python 3's representation of non-printable
1303 # wide characters.
1304 code = (ord(ch) & 0x03FF) << 10
1305 code |= ord(ch2) & 0x03FF
1306 code += 0x00010000
1307 else:
1308 code = ord(ucs)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001309
1310 # Map 8-bit characters to '\\xhh'
Victor Stinner150016f2010-05-19 23:04:56 +00001311 if code <= 0xff:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001312 out.write('\\x')
Victor Stinner150016f2010-05-19 23:04:56 +00001313 out.write(hexdigits[(code >> 4) & 0x000F])
1314 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001315 # Map 21-bit characters to '\U00xxxxxx'
Victor Stinner150016f2010-05-19 23:04:56 +00001316 elif code >= 0x10000:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001317 out.write('\\U')
Victor Stinner150016f2010-05-19 23:04:56 +00001318 out.write(hexdigits[(code >> 28) & 0x0000000F])
1319 out.write(hexdigits[(code >> 24) & 0x0000000F])
1320 out.write(hexdigits[(code >> 20) & 0x0000000F])
1321 out.write(hexdigits[(code >> 16) & 0x0000000F])
1322 out.write(hexdigits[(code >> 12) & 0x0000000F])
1323 out.write(hexdigits[(code >> 8) & 0x0000000F])
1324 out.write(hexdigits[(code >> 4) & 0x0000000F])
1325 out.write(hexdigits[code & 0x0000000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001326 # Map 16-bit characters to '\uxxxx'
1327 else:
1328 out.write('\\u')
Victor Stinner150016f2010-05-19 23:04:56 +00001329 out.write(hexdigits[(code >> 12) & 0x000F])
1330 out.write(hexdigits[(code >> 8) & 0x000F])
1331 out.write(hexdigits[(code >> 4) & 0x000F])
1332 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001333 else:
1334 # Copy characters as-is
1335 out.write(ch)
Antoine Pitroub41e1282010-09-08 20:57:48 +00001336 if ch2 is not None:
Victor Stinner150016f2010-05-19 23:04:56 +00001337 out.write(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001338
1339 out.write(quote)
1340
1341
Victor Stinner61108332017-02-01 16:29:54 +01001342class wrapperobject(PyObjectPtr):
1343 _typename = 'wrapperobject'
1344
1345 def safe_name(self):
1346 try:
1347 name = self.field('descr')['d_base']['name'].string()
1348 return repr(name)
Victor Stinnerd22fc0b2018-06-14 22:34:52 +02001349 except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
Victor Stinner61108332017-02-01 16:29:54 +01001350 return '<unknown name>'
1351
1352 def safe_tp_name(self):
1353 try:
1354 return self.field('self')['ob_type']['tp_name'].string()
Victor Stinnerd22fc0b2018-06-14 22:34:52 +02001355 except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
Victor Stinner61108332017-02-01 16:29:54 +01001356 return '<unknown tp_name>'
1357
1358 def safe_self_addresss(self):
1359 try:
1360 address = long(self.field('self'))
1361 return '%#x' % address
1362 except (NullPyObjectPtr, RuntimeError):
1363 return '<failed to get self address>'
1364
1365 def proxyval(self, visited):
1366 name = self.safe_name()
1367 tp_name = self.safe_tp_name()
1368 self_address = self.safe_self_addresss()
1369 return ("<method-wrapper %s of %s object at %s>"
1370 % (name, tp_name, self_address))
1371
1372 def write_repr(self, out, visited):
1373 proxy = self.proxyval(visited)
1374 out.write(proxy)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001375
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001376
1377def int_from_int(gdbval):
1378 return int(str(gdbval))
1379
1380
1381def stringify(val):
1382 # TODO: repr() puts everything on one line; pformat can be nicer, but
1383 # can lead to v.long results; this function isolates the choice
1384 if True:
1385 return repr(val)
1386 else:
1387 from pprint import pformat
1388 return pformat(val)
1389
1390
1391class PyObjectPtrPrinter:
1392 "Prints a (PyObject*)"
1393
1394 def __init__ (self, gdbval):
1395 self.gdbval = gdbval
1396
1397 def to_string (self):
1398 pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1399 if True:
1400 return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1401 else:
1402 # Generate full proxy value then stringify it.
1403 # Doing so could be expensive
1404 proxyval = pyop.proxyval(set())
1405 return stringify(proxyval)
1406
1407def pretty_printer_lookup(gdbval):
1408 type = gdbval.type.unqualified()
Victor Stinner61108332017-02-01 16:29:54 +01001409 if type.code != gdb.TYPE_CODE_PTR:
1410 return None
1411
1412 type = type.target().unqualified()
1413 t = str(type)
1414 if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
1415 return PyObjectPtrPrinter(gdbval)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001416
1417"""
1418During development, I've been manually invoking the code in this way:
1419(gdb) python
1420
1421import sys
1422sys.path.append('/home/david/coding/python-gdb')
1423import libpython
1424end
1425
1426then reloading it after each edit like this:
1427(gdb) python reload(libpython)
1428
1429The following code should ensure that the prettyprinter is registered
1430if the code is autoloaded by gdb when visiting libpython.so, provided
1431that this python file is installed to the same path as the library (or its
1432.debug file) plus a "-gdb.py" suffix, e.g:
1433 /usr/lib/libpython2.6.so.1.0-gdb.py
1434 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1435"""
1436def register (obj):
Benjamin Petersonb29614e2012-10-09 11:16:03 -04001437 if obj is None:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001438 obj = gdb
1439
1440 # Wire up the pretty-printer
1441 obj.pretty_printers.append(pretty_printer_lookup)
1442
1443register (gdb.current_objfile ())
1444
1445
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001446
1447# Unfortunately, the exact API exposed by the gdb module varies somewhat
1448# from build to build
1449# See http://bugs.python.org/issue8279?#msg102276
1450
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001451class Frame(object):
1452 '''
1453 Wrapper for gdb.Frame, adding various methods
1454 '''
1455 def __init__(self, gdbframe):
1456 self._gdbframe = gdbframe
1457
1458 def older(self):
1459 older = self._gdbframe.older()
1460 if older:
1461 return Frame(older)
1462 else:
1463 return None
1464
1465 def newer(self):
1466 newer = self._gdbframe.newer()
1467 if newer:
1468 return Frame(newer)
1469 else:
1470 return None
1471
1472 def select(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001473 '''If supported, select this frame and return True; return False if unsupported
1474
1475 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1476 onwards, but absent on Ubuntu buildbot'''
1477 if not hasattr(self._gdbframe, 'select'):
1478 print ('Unable to select frame: '
1479 'this build of gdb does not expose a gdb.Frame.select method')
1480 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001481 self._gdbframe.select()
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001482 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001483
1484 def get_index(self):
1485 '''Calculate index of frame, starting at 0 for the newest frame within
1486 this thread'''
1487 index = 0
1488 # Go down until you reach the newest frame:
1489 iter_frame = self
1490 while iter_frame.newer():
1491 index += 1
1492 iter_frame = iter_frame.newer()
1493 return index
1494
David Malcolm8d37ffa2012-06-27 14:15:34 -04001495 # We divide frames into:
1496 # - "python frames":
1497 # - "bytecode frames" i.e. PyEval_EvalFrameEx
1498 # - "other python frames": things that are of interest from a python
1499 # POV, but aren't bytecode (e.g. GC, GIL)
1500 # - everything else
1501
1502 def is_python_frame(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001503 '''Is this a _PyEval_EvalFrameDefault frame, or some other important
David Malcolm8d37ffa2012-06-27 14:15:34 -04001504 frame? (see is_other_python_frame for what "important" means in this
1505 context)'''
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001506 if self.is_evalframe():
David Malcolm8d37ffa2012-06-27 14:15:34 -04001507 return True
1508 if self.is_other_python_frame():
1509 return True
1510 return False
1511
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001512 def is_evalframe(self):
1513 '''Is this a _PyEval_EvalFrameDefault frame?'''
1514 if self._gdbframe.name() == EVALFRAME:
Victor Stinner50eb60e2010-04-20 22:32:07 +00001515 '''
1516 I believe we also need to filter on the inline
1517 struct frame_id.inline_depth, only regarding frames with
1518 an inline depth of 0 as actually being this function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001519
Victor Stinner50eb60e2010-04-20 22:32:07 +00001520 So we reject those with type gdb.INLINE_FRAME
1521 '''
1522 if self._gdbframe.type() == gdb.NORMAL_FRAME:
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001523 # We have a _PyEval_EvalFrameDefault frame:
Victor Stinner50eb60e2010-04-20 22:32:07 +00001524 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001525
1526 return False
1527
David Malcolm8d37ffa2012-06-27 14:15:34 -04001528 def is_other_python_frame(self):
1529 '''Is this frame worth displaying in python backtraces?
1530 Examples:
1531 - waiting on the GIL
1532 - garbage-collecting
1533 - within a CFunction
1534 If it is, return a descriptive string
1535 For other frames, return False
1536 '''
1537 if self.is_waiting_for_gil():
1538 return 'Waiting for the GIL'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001539
1540 if self.is_gc_collect():
David Malcolm8d37ffa2012-06-27 14:15:34 -04001541 return 'Garbage-collecting'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001542
1543 # Detect invocations of PyCFunction instances:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001544 frame = self._gdbframe
1545 caller = frame.name()
Victor Stinnereae64fd2016-11-22 22:53:18 +01001546 if not caller:
1547 return False
1548
Victor Stinnerfa025f12017-01-18 17:20:01 +01001549 if caller in ('_PyCFunction_FastCallDict',
1550 '_PyCFunction_FastCallKeywords'):
INADA Naoki5566bbb2017-02-03 07:43:03 +09001551 arg_name = 'func'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001552 # Within that frame:
1553 # "func" is the local containing the PyObject* of the
1554 # PyCFunctionObject instance
1555 # "f" is the same value, but cast to (PyCFunctionObject*)
1556 # "self" is the (PyObject*) of the 'self'
1557 try:
1558 # Use the prettyprinter for the func:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001559 func = frame.read_var(arg_name)
Victor Stinnereae64fd2016-11-22 22:53:18 +01001560 return str(func)
Victor Stinner019d33b2018-06-14 16:28:07 +02001561 except ValueError:
1562 return ('PyCFunction invocation (unable to read %s: '
1563 'missing debuginfos?)' % arg_name)
Victor Stinnereae64fd2016-11-22 22:53:18 +01001564 except RuntimeError:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001565 return 'PyCFunction invocation (unable to read %s)' % arg_name
David Malcolm8d37ffa2012-06-27 14:15:34 -04001566
Victor Stinner61108332017-02-01 16:29:54 +01001567 if caller == 'wrapper_call':
Victor Stinner019d33b2018-06-14 16:28:07 +02001568 arg_name = 'wp'
Victor Stinner61108332017-02-01 16:29:54 +01001569 try:
Victor Stinner019d33b2018-06-14 16:28:07 +02001570 func = frame.read_var(arg_name)
Victor Stinner61108332017-02-01 16:29:54 +01001571 return str(func)
Victor Stinner019d33b2018-06-14 16:28:07 +02001572 except ValueError:
1573 return ('<wrapper_call invocation (unable to read %s: '
1574 'missing debuginfos?)>' % arg_name)
Victor Stinner61108332017-02-01 16:29:54 +01001575 except RuntimeError:
Victor Stinner019d33b2018-06-14 16:28:07 +02001576 return '<wrapper_call invocation (unable to read %s)>' % arg_name
Victor Stinner61108332017-02-01 16:29:54 +01001577
David Malcolm8d37ffa2012-06-27 14:15:34 -04001578 # This frame isn't worth reporting:
1579 return False
1580
1581 def is_waiting_for_gil(self):
1582 '''Is this frame waiting on the GIL?'''
1583 # This assumes the _POSIX_THREADS version of Python/ceval_gil.h:
1584 name = self._gdbframe.name()
1585 if name:
David Malcolmd08b2102013-05-06 14:47:15 -04001586 return 'pthread_cond_timedwait' in name
David Malcolm8d37ffa2012-06-27 14:15:34 -04001587
1588 def is_gc_collect(self):
Ezio Melotti3f5db392013-01-27 06:20:14 +02001589 '''Is this frame "collect" within the garbage-collector?'''
David Malcolm8d37ffa2012-06-27 14:15:34 -04001590 return self._gdbframe.name() == 'collect'
1591
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001592 def get_pyop(self):
1593 try:
1594 f = self._gdbframe.read_var('f')
Victor Stinnerd2084162011-12-19 13:42:24 +01001595 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1596 if not frame.is_optimized_out():
1597 return frame
1598 # gdb is unable to get the "f" argument of PyEval_EvalFrameEx()
1599 # because it was "optimized out". Try to get "f" from the frame
1600 # of the caller, PyEval_EvalCodeEx().
1601 orig_frame = frame
1602 caller = self._gdbframe.older()
1603 if caller:
1604 f = caller.read_var('f')
1605 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1606 if not frame.is_optimized_out():
1607 return frame
1608 return orig_frame
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001609 except ValueError:
1610 return None
1611
1612 @classmethod
1613 def get_selected_frame(cls):
1614 _gdbframe = gdb.selected_frame()
1615 if _gdbframe:
1616 return Frame(_gdbframe)
1617 return None
1618
1619 @classmethod
1620 def get_selected_python_frame(cls):
David Malcolm8d37ffa2012-06-27 14:15:34 -04001621 '''Try to obtain the Frame for the python-related code in the selected
1622 frame, or None'''
Victor Stinner610f5d72016-12-16 10:00:39 +01001623 try:
1624 frame = cls.get_selected_frame()
1625 except gdb.error:
1626 # No frame: Python didn't start yet
1627 return None
David Malcolm8d37ffa2012-06-27 14:15:34 -04001628
1629 while frame:
1630 if frame.is_python_frame():
1631 return frame
1632 frame = frame.older()
1633
1634 # Not found:
1635 return None
1636
1637 @classmethod
1638 def get_selected_bytecode_frame(cls):
1639 '''Try to obtain the Frame for the python bytecode interpreter in the
1640 selected GDB frame, or None'''
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001641 frame = cls.get_selected_frame()
1642
1643 while frame:
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001644 if frame.is_evalframe():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001645 return frame
1646 frame = frame.older()
1647
1648 # Not found:
1649 return None
1650
1651 def print_summary(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001652 if self.is_evalframe():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001653 pyop = self.get_pyop()
1654 if pyop:
Victor Stinner0e5a41b2010-08-17 22:49:25 +00001655 line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1656 write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
Victor Stinnerd2084162011-12-19 13:42:24 +01001657 if not pyop.is_optimized_out():
1658 line = pyop.current_line()
1659 if line is not None:
1660 sys.stdout.write(' %s\n' % line.strip())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001661 else:
1662 sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1663 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001664 info = self.is_other_python_frame()
1665 if info:
1666 sys.stdout.write('#%i %s\n' % (self.get_index(), info))
1667 else:
1668 sys.stdout.write('#%i\n' % self.get_index())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001669
Victor Stinnere670c882011-05-13 17:40:15 +02001670 def print_traceback(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001671 if self.is_evalframe():
Victor Stinnere670c882011-05-13 17:40:15 +02001672 pyop = self.get_pyop()
1673 if pyop:
1674 pyop.print_traceback()
Victor Stinnerd2084162011-12-19 13:42:24 +01001675 if not pyop.is_optimized_out():
1676 line = pyop.current_line()
1677 if line is not None:
1678 sys.stdout.write(' %s\n' % line.strip())
Victor Stinnere670c882011-05-13 17:40:15 +02001679 else:
1680 sys.stdout.write(' (unable to read python frame information)\n')
1681 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001682 info = self.is_other_python_frame()
1683 if info:
1684 sys.stdout.write(' %s\n' % info)
1685 else:
1686 sys.stdout.write(' (not a python frame)\n')
Victor Stinnere670c882011-05-13 17:40:15 +02001687
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001688class PyList(gdb.Command):
1689 '''List the current Python source code, if any
1690
1691 Use
1692 py-list START
1693 to list at a different line number within the python source.
1694
1695 Use
1696 py-list START, END
1697 to list a specific range of lines within the python source.
1698 '''
1699
1700 def __init__(self):
1701 gdb.Command.__init__ (self,
1702 "py-list",
1703 gdb.COMMAND_FILES,
1704 gdb.COMPLETE_NONE)
1705
1706
1707 def invoke(self, args, from_tty):
1708 import re
1709
1710 start = None
1711 end = None
1712
1713 m = re.match(r'\s*(\d+)\s*', args)
1714 if m:
1715 start = int(m.group(0))
1716 end = start + 10
1717
1718 m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1719 if m:
1720 start, end = map(int, m.groups())
1721
David Malcolm8d37ffa2012-06-27 14:15:34 -04001722 # py-list requires an actual PyEval_EvalFrameEx frame:
1723 frame = Frame.get_selected_bytecode_frame()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001724 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001725 print('Unable to locate gdb frame for python bytecode interpreter')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001726 return
1727
1728 pyop = frame.get_pyop()
Victor Stinnerd2084162011-12-19 13:42:24 +01001729 if not pyop or pyop.is_optimized_out():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001730 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001731 return
1732
1733 filename = pyop.filename()
1734 lineno = pyop.current_line_num()
1735
1736 if start is None:
1737 start = lineno - 5
1738 end = lineno + 5
1739
1740 if start<1:
1741 start = 1
1742
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001743 try:
1744 f = open(os_fsencode(filename), 'r')
1745 except IOError as err:
1746 sys.stdout.write('Unable to open %s: %s\n'
1747 % (filename, err))
1748 return
1749 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001750 all_lines = f.readlines()
1751 # start and end are 1-based, all_lines is 0-based;
1752 # so [start-1:end] as a python slice gives us [start, end] as a
1753 # closed interval
1754 for i, line in enumerate(all_lines[start-1:end]):
1755 linestr = str(i+start)
1756 # Highlight current line:
1757 if i + start == lineno:
1758 linestr = '>' + linestr
1759 sys.stdout.write('%4s %s' % (linestr, line))
1760
1761
1762# ...and register the command:
1763PyList()
1764
1765def move_in_stack(move_up):
1766 '''Move up or down the stack (for the py-up/py-down command)'''
1767 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001768 if not frame:
1769 print('Unable to locate python frame')
1770 return
1771
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001772 while frame:
1773 if move_up:
1774 iter_frame = frame.older()
1775 else:
1776 iter_frame = frame.newer()
1777
1778 if not iter_frame:
1779 break
1780
David Malcolm8d37ffa2012-06-27 14:15:34 -04001781 if iter_frame.is_python_frame():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001782 # Result:
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001783 if iter_frame.select():
1784 iter_frame.print_summary()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001785 return
1786
1787 frame = iter_frame
1788
1789 if move_up:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001790 print('Unable to find an older python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001791 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001792 print('Unable to find a newer python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001793
1794class PyUp(gdb.Command):
1795 'Select and print the python stack frame that called this one (if any)'
1796 def __init__(self):
1797 gdb.Command.__init__ (self,
1798 "py-up",
1799 gdb.COMMAND_STACK,
1800 gdb.COMPLETE_NONE)
1801
1802
1803 def invoke(self, args, from_tty):
1804 move_in_stack(move_up=True)
1805
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001806class PyDown(gdb.Command):
1807 'Select and print the python stack frame called by this one (if any)'
1808 def __init__(self):
1809 gdb.Command.__init__ (self,
1810 "py-down",
1811 gdb.COMMAND_STACK,
1812 gdb.COMPLETE_NONE)
1813
1814
1815 def invoke(self, args, from_tty):
1816 move_in_stack(move_up=False)
1817
Victor Stinner50eb60e2010-04-20 22:32:07 +00001818# Not all builds of gdb have gdb.Frame.select
1819if hasattr(gdb.Frame, 'select'):
1820 PyUp()
1821 PyDown()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001822
Victor Stinnere670c882011-05-13 17:40:15 +02001823class PyBacktraceFull(gdb.Command):
1824 'Display the current python frame and all the frames within its call stack (if any)'
1825 def __init__(self):
1826 gdb.Command.__init__ (self,
1827 "py-bt-full",
1828 gdb.COMMAND_STACK,
1829 gdb.COMPLETE_NONE)
1830
1831
1832 def invoke(self, args, from_tty):
1833 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001834 if not frame:
1835 print('Unable to locate python frame')
1836 return
1837
Victor Stinnere670c882011-05-13 17:40:15 +02001838 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001839 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001840 frame.print_summary()
1841 frame = frame.older()
1842
1843PyBacktraceFull()
1844
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001845class PyBacktrace(gdb.Command):
1846 'Display the current python frame and all the frames within its call stack (if any)'
1847 def __init__(self):
1848 gdb.Command.__init__ (self,
1849 "py-bt",
1850 gdb.COMMAND_STACK,
1851 gdb.COMPLETE_NONE)
1852
1853
1854 def invoke(self, args, from_tty):
1855 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001856 if not frame:
1857 print('Unable to locate python frame')
1858 return
1859
1860 sys.stdout.write('Traceback (most recent call first):\n')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001861 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001862 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001863 frame.print_traceback()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001864 frame = frame.older()
1865
1866PyBacktrace()
1867
1868class PyPrint(gdb.Command):
1869 'Look up the given python variable name, and print it'
1870 def __init__(self):
1871 gdb.Command.__init__ (self,
1872 "py-print",
1873 gdb.COMMAND_DATA,
1874 gdb.COMPLETE_NONE)
1875
1876
1877 def invoke(self, args, from_tty):
1878 name = str(args)
1879
1880 frame = Frame.get_selected_python_frame()
1881 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001882 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001883 return
1884
1885 pyop_frame = frame.get_pyop()
1886 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001887 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001888 return
1889
1890 pyop_var, scope = pyop_frame.get_var_by_name(name)
1891
1892 if pyop_var:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001893 print('%s %r = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001894 % (scope,
1895 name,
1896 pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1897 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001898 print('%r not found' % name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001899
1900PyPrint()
1901
1902class PyLocals(gdb.Command):
1903 'Look up the given python variable name, and print it'
1904 def __init__(self):
1905 gdb.Command.__init__ (self,
1906 "py-locals",
1907 gdb.COMMAND_DATA,
1908 gdb.COMPLETE_NONE)
1909
1910
1911 def invoke(self, args, from_tty):
1912 name = str(args)
1913
1914 frame = Frame.get_selected_python_frame()
1915 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001916 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001917 return
1918
1919 pyop_frame = frame.get_pyop()
1920 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001921 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001922 return
1923
1924 for pyop_name, pyop_value in pyop_frame.iter_locals():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001925 print('%s = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001926 % (pyop_name.proxyval(set()),
1927 pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1928
1929PyLocals()