blob: 2ad22e2bbe80fa4680d7847f99d71fe567a9e476 [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
47from __future__ import print_function, with_statement
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:
59_type_char_ptr = gdb.lookup_type('char').pointer() # char*
60_type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char*
61_type_void_ptr = gdb.lookup_type('void').pointer() # void*
Martin v. Löwis24fa9832011-09-28 08:35:25 +020062_type_unsigned_short_ptr = gdb.lookup_type('unsigned short').pointer()
63_type_unsigned_int_ptr = gdb.lookup_type('unsigned int').pointer()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000064
Victor Stinner0c4fbff2011-12-08 00:08:22 +010065# value computed later, see PyUnicodeObjectPtr.proxy()
66_is_pep393 = None
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020067
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000068SIZEOF_VOID_P = _type_void_ptr.sizeof
69
70
Antoine Pitroue50240c2013-11-23 17:40:36 +010071Py_TPFLAGS_HEAPTYPE = (1 << 9)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000072
Antoine Pitroue50240c2013-11-23 17:40:36 +010073Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
74Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
75Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
76Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
77Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
78Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
79Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
80Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000081
82
83MAX_OUTPUT_LEN=1024
84
Martin v. Löwis5ae68102010-04-21 22:38:42 +000085hexdigits = "0123456789abcdef"
86
Victor Stinner150016f2010-05-19 23:04:56 +000087ENCODING = locale.getpreferredencoding()
Martin v. Löwis5ae68102010-04-21 22:38:42 +000088
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000089class NullPyObjectPtr(RuntimeError):
90 pass
91
92
93def safety_limit(val):
94 # Given a integer value from the process being debugged, limit it to some
95 # safety threshold so that arbitrary breakage within said process doesn't
96 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
97 return min(val, 1000)
98
99
100def safe_range(val):
101 # As per range, but don't trust the value too much: cap it to a safety
102 # threshold in case the data was corrupted
Antoine Pitroue50240c2013-11-23 17:40:36 +0100103 return xrange(safety_limit(int(val)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000104
Antoine Pitroue50240c2013-11-23 17:40:36 +0100105if sys.version_info[0] >= 3:
106 def write_unicode(file, text):
107 file.write(text)
108else:
109 def write_unicode(file, text):
110 # Write a byte or unicode string to file. Unicode strings are encoded to
111 # ENCODING encoding with 'backslashreplace' error handler to avoid
112 # UnicodeEncodeError.
113 if isinstance(text, unicode):
114 text = text.encode(ENCODING, 'backslashreplace')
115 file.write(text)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000116
Antoine Pitroue50240c2013-11-23 17:40:36 +0100117try:
118 os_fsencode = os.fsencode
Antoine Pitrou23828f62013-11-23 18:20:42 +0100119except AttributeError:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100120 def os_fsencode(filename):
121 if not isinstance(filename, unicode):
122 return filename
123 encoding = sys.getfilesystemencoding()
124 if encoding == 'mbcs':
125 # mbcs doesn't support surrogateescape
126 return filename.encode(encoding)
127 encoded = []
128 for char in filename:
129 # surrogateescape error handler
130 if 0xDC80 <= ord(char) <= 0xDCFF:
131 byte = chr(ord(char) - 0xDC00)
132 else:
133 byte = char.encode(encoding)
134 encoded.append(byte)
135 return ''.join(encoded)
Victor Stinner6ffbee72010-10-17 19:35:30 +0000136
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000137class StringTruncated(RuntimeError):
138 pass
139
140class TruncatedStringIO(object):
Serhiy Storchaka50254c52013-08-29 11:35:43 +0300141 '''Similar to io.StringIO, but can truncate the output by raising a
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000142 StringTruncated exception'''
143 def __init__(self, maxlen=None):
144 self._val = ''
145 self.maxlen = maxlen
146
147 def write(self, data):
148 if self.maxlen:
149 if len(data) + len(self._val) > self.maxlen:
150 # Truncation:
151 self._val += data[0:self.maxlen - len(self._val)]
152 raise StringTruncated()
153
154 self._val += data
155
156 def getvalue(self):
157 return self._val
158
159class PyObjectPtr(object):
160 """
161 Class wrapping a gdb.Value that's a either a (PyObject*) within the
Victor Stinner67df3a42010-04-21 13:53:05 +0000162 inferior process, or some subclass pointer e.g. (PyBytesObject*)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000163
164 There will be a subclass for every refined PyObject type that we care
165 about.
166
167 Note that at every stage the underlying pointer could be NULL, point
168 to corrupt data, etc; this is the debugger, after all.
169 """
170 _typename = 'PyObject'
171
172 def __init__(self, gdbval, cast_to=None):
173 if cast_to:
174 self._gdbval = gdbval.cast(cast_to)
175 else:
176 self._gdbval = gdbval
177
178 def field(self, name):
179 '''
180 Get the gdb.Value for the given field within the PyObject, coping with
181 some python 2 versus python 3 differences.
182
183 Various libpython types are defined using the "PyObject_HEAD" and
184 "PyObject_VAR_HEAD" macros.
185
186 In Python 2, this these are defined so that "ob_type" and (for a var
187 object) "ob_size" are fields of the type in question.
188
189 In Python 3, this is defined as an embedded PyVarObject type thus:
190 PyVarObject ob_base;
191 so that the "ob_size" field is located insize the "ob_base" field, and
192 the "ob_type" is most easily accessed by casting back to a (PyObject*).
193 '''
194 if self.is_null():
195 raise NullPyObjectPtr(self)
196
197 if name == 'ob_type':
198 pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
199 return pyo_ptr.dereference()[name]
200
201 if name == 'ob_size':
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000202 pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
203 return pyo_ptr.dereference()[name]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000204
205 # General case: look it up inside the object:
206 return self._gdbval.dereference()[name]
207
208 def pyop_field(self, name):
209 '''
210 Get a PyObjectPtr for the given PyObject* field within this PyObject,
211 coping with some python 2 versus python 3 differences.
212 '''
213 return PyObjectPtr.from_pyobject_ptr(self.field(name))
214
215 def write_field_repr(self, name, out, visited):
216 '''
217 Extract the PyObject* field named "name", and write its representation
218 to file-like object "out"
219 '''
220 field_obj = self.pyop_field(name)
221 field_obj.write_repr(out, visited)
222
223 def get_truncated_repr(self, maxlen):
224 '''
225 Get a repr-like string for the data, but truncate it at "maxlen" bytes
226 (ending the object graph traversal as soon as you do)
227 '''
228 out = TruncatedStringIO(maxlen)
229 try:
230 self.write_repr(out, set())
231 except StringTruncated:
232 # Truncation occurred:
233 return out.getvalue() + '...(truncated)'
234
235 # No truncation occurred:
236 return out.getvalue()
237
238 def type(self):
239 return PyTypeObjectPtr(self.field('ob_type'))
240
241 def is_null(self):
242 return 0 == long(self._gdbval)
243
244 def is_optimized_out(self):
245 '''
246 Is the value of the underlying PyObject* visible to the debugger?
247
248 This can vary with the precise version of the compiler used to build
249 Python, and the precise version of gdb.
250
251 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
252 PyEval_EvalFrameEx's "f"
253 '''
254 return self._gdbval.is_optimized_out
255
256 def safe_tp_name(self):
257 try:
258 return self.type().field('tp_name').string()
259 except NullPyObjectPtr:
260 # NULL tp_name?
261 return 'unknown'
262 except RuntimeError:
263 # Can't even read the object at all?
264 return 'unknown'
265
266 def proxyval(self, visited):
267 '''
268 Scrape a value from the inferior process, and try to represent it
269 within the gdb process, whilst (hopefully) avoiding crashes when
270 the remote data is corrupt.
271
272 Derived classes will override this.
273
274 For example, a PyIntObject* with ob_ival 42 in the inferior process
275 should result in an int(42) in this process.
276
277 visited: a set of all gdb.Value pyobject pointers already visited
278 whilst generating this value (to guard against infinite recursion when
279 visiting object graphs with loops). Analogous to Py_ReprEnter and
280 Py_ReprLeave
281 '''
282
283 class FakeRepr(object):
284 """
285 Class representing a non-descript PyObject* value in the inferior
286 process for when we don't have a custom scraper, intended to have
287 a sane repr().
288 """
289
290 def __init__(self, tp_name, address):
291 self.tp_name = tp_name
292 self.address = address
293
294 def __repr__(self):
295 # For the NULL pointer, we have no way of knowing a type, so
296 # special-case it as per
297 # http://bugs.python.org/issue8032#msg100882
298 if self.address == 0:
299 return '0x0'
300 return '<%s at remote 0x%x>' % (self.tp_name, self.address)
301
302 return FakeRepr(self.safe_tp_name(),
303 long(self._gdbval))
304
305 def write_repr(self, out, visited):
306 '''
307 Write a string representation of the value scraped from the inferior
308 process to "out", a file-like object.
309 '''
310 # Default implementation: generate a proxy value and write its repr
311 # However, this could involve a lot of work for complicated objects,
312 # so for derived classes we specialize this
313 return out.write(repr(self.proxyval(visited)))
314
315 @classmethod
316 def subclass_from_type(cls, t):
317 '''
318 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
319 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
320 to use
321
322 Ideally, we would look up the symbols for the global types, but that
323 isn't working yet:
324 (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
325 Traceback (most recent call last):
326 File "<string>", line 1, in <module>
327 NotImplementedError: Symbol type not yet supported in Python scripts.
328 Error while executing Python code.
329
330 For now, we use tp_flags, after doing some string comparisons on the
331 tp_name for some special-cases that don't seem to be visible through
332 flags
333 '''
334 try:
335 tp_name = t.field('tp_name').string()
336 tp_flags = int(t.field('tp_flags'))
337 except RuntimeError:
338 # Handle any kind of error e.g. NULL ptrs by simply using the base
339 # class
340 return cls
341
Antoine Pitroue50240c2013-11-23 17:40:36 +0100342 #print('tp_flags = 0x%08x' % tp_flags)
343 #print('tp_name = %r' % tp_name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000344
345 name_map = {'bool': PyBoolObjectPtr,
346 'classobj': PyClassObjectPtr,
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000347 'NoneType': PyNoneStructPtr,
348 'frame': PyFrameObjectPtr,
349 'set' : PySetObjectPtr,
350 'frozenset' : PySetObjectPtr,
351 'builtin_function_or_method' : PyCFunctionObjectPtr,
352 }
353 if tp_name in name_map:
354 return name_map[tp_name]
355
356 if tp_flags & Py_TPFLAGS_HEAPTYPE:
357 return HeapTypeObjectPtr
358
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000359 if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
360 return PyLongObjectPtr
361 if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
362 return PyListObjectPtr
363 if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
364 return PyTupleObjectPtr
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000365 if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
Victor Stinner67df3a42010-04-21 13:53:05 +0000366 return PyBytesObjectPtr
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000367 if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
368 return PyUnicodeObjectPtr
369 if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
370 return PyDictObjectPtr
371 if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
372 return PyBaseExceptionObjectPtr
373 #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
374 # return PyTypeObjectPtr
375
376 # Use the base class:
377 return cls
378
379 @classmethod
380 def from_pyobject_ptr(cls, gdbval):
381 '''
382 Try to locate the appropriate derived class dynamically, and cast
383 the pointer accordingly.
384 '''
385 try:
386 p = PyObjectPtr(gdbval)
387 cls = cls.subclass_from_type(p.type())
388 return cls(gdbval, cast_to=cls.get_gdb_type())
389 except RuntimeError:
390 # Handle any kind of error e.g. NULL ptrs by simply using the base
391 # class
392 pass
393 return cls(gdbval)
394
395 @classmethod
396 def get_gdb_type(cls):
397 return gdb.lookup_type(cls._typename).pointer()
398
399 def as_address(self):
400 return long(self._gdbval)
401
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000402class PyVarObjectPtr(PyObjectPtr):
403 _typename = 'PyVarObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000404
405class ProxyAlreadyVisited(object):
406 '''
407 Placeholder proxy to use when protecting against infinite recursion due to
408 loops in the object graph.
409
410 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
411 '''
412 def __init__(self, rep):
413 self._rep = rep
414
415 def __repr__(self):
416 return self._rep
417
418
419def _write_instance_repr(out, visited, name, pyop_attrdict, address):
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100420 '''Shared code for use by all classes:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000421 write a representation to file-like object "out"'''
422 out.write('<')
423 out.write(name)
424
425 # Write dictionary of instance attributes:
426 if isinstance(pyop_attrdict, PyDictObjectPtr):
427 out.write('(')
428 first = True
429 for pyop_arg, pyop_val in pyop_attrdict.iteritems():
430 if not first:
431 out.write(', ')
432 first = False
433 out.write(pyop_arg.proxyval(visited))
434 out.write('=')
435 pyop_val.write_repr(out, visited)
436 out.write(')')
437 out.write(' at remote 0x%x>' % address)
438
439
440class InstanceProxy(object):
441
442 def __init__(self, cl_name, attrdict, address):
443 self.cl_name = cl_name
444 self.attrdict = attrdict
445 self.address = address
446
447 def __repr__(self):
448 if isinstance(self.attrdict, dict):
449 kwargs = ', '.join(["%s=%r" % (arg, val)
450 for arg, val in self.attrdict.iteritems()])
451 return '<%s(%s) at remote 0x%x>' % (self.cl_name,
452 kwargs, self.address)
453 else:
454 return '<%s at remote 0x%x>' % (self.cl_name,
455 self.address)
456
457def _PyObject_VAR_SIZE(typeobj, nitems):
Victor Stinnerd2084162011-12-19 13:42:24 +0100458 if _PyObject_VAR_SIZE._type_size_t is None:
459 _PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t')
460
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000461 return ( ( typeobj.field('tp_basicsize') +
462 nitems * typeobj.field('tp_itemsize') +
463 (SIZEOF_VOID_P - 1)
464 ) & ~(SIZEOF_VOID_P - 1)
Victor Stinnerd2084162011-12-19 13:42:24 +0100465 ).cast(_PyObject_VAR_SIZE._type_size_t)
466_PyObject_VAR_SIZE._type_size_t = None
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000467
468class HeapTypeObjectPtr(PyObjectPtr):
469 _typename = 'PyObject'
470
471 def get_attr_dict(self):
472 '''
473 Get the PyDictObject ptr representing the attribute dictionary
474 (or None if there's a problem)
475 '''
476 try:
477 typeobj = self.type()
478 dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
479 if dictoffset != 0:
480 if dictoffset < 0:
481 type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
482 tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
483 if tsize < 0:
484 tsize = -tsize
485 size = _PyObject_VAR_SIZE(typeobj, tsize)
486 dictoffset += size
487 assert dictoffset > 0
488 assert dictoffset % SIZEOF_VOID_P == 0
489
490 dictptr = self._gdbval.cast(_type_char_ptr) + dictoffset
491 PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
492 dictptr = dictptr.cast(PyObjectPtrPtr)
493 return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
494 except RuntimeError:
495 # Corrupt data somewhere; fail safe
496 pass
497
498 # Not found, or some kind of error:
499 return None
500
501 def proxyval(self, visited):
502 '''
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100503 Support for classes.
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000504
505 Currently we just locate the dictionary using a transliteration to
506 python of _PyObject_GetDictPtr, ignoring descriptors
507 '''
508 # Guard against infinite loops:
509 if self.as_address() in visited:
510 return ProxyAlreadyVisited('<...>')
511 visited.add(self.as_address())
512
513 pyop_attr_dict = self.get_attr_dict()
514 if pyop_attr_dict:
515 attr_dict = pyop_attr_dict.proxyval(visited)
516 else:
517 attr_dict = {}
518 tp_name = self.safe_tp_name()
519
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100520 # Class:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000521 return InstanceProxy(tp_name, attr_dict, long(self._gdbval))
522
523 def write_repr(self, out, visited):
524 # Guard against infinite loops:
525 if self.as_address() in visited:
526 out.write('<...>')
527 return
528 visited.add(self.as_address())
529
530 pyop_attrdict = self.get_attr_dict()
531 _write_instance_repr(out, visited,
532 self.safe_tp_name(), pyop_attrdict, self.as_address())
533
534class ProxyException(Exception):
535 def __init__(self, tp_name, args):
536 self.tp_name = tp_name
537 self.args = args
538
539 def __repr__(self):
540 return '%s%r' % (self.tp_name, self.args)
541
542class PyBaseExceptionObjectPtr(PyObjectPtr):
543 """
544 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
545 within the process being debugged.
546 """
547 _typename = 'PyBaseExceptionObject'
548
549 def proxyval(self, visited):
550 # Guard against infinite loops:
551 if self.as_address() in visited:
552 return ProxyAlreadyVisited('(...)')
553 visited.add(self.as_address())
554 arg_proxy = self.pyop_field('args').proxyval(visited)
555 return ProxyException(self.safe_tp_name(),
556 arg_proxy)
557
558 def write_repr(self, out, visited):
559 # Guard against infinite loops:
560 if self.as_address() in visited:
561 out.write('(...)')
562 return
563 visited.add(self.as_address())
564
565 out.write(self.safe_tp_name())
566 self.write_field_repr('args', out, visited)
567
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000568class PyClassObjectPtr(PyObjectPtr):
569 """
570 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
571 instance within the process being debugged.
572 """
573 _typename = 'PyClassObject'
574
575
576class BuiltInFunctionProxy(object):
577 def __init__(self, ml_name):
578 self.ml_name = ml_name
579
580 def __repr__(self):
581 return "<built-in function %s>" % self.ml_name
582
583class BuiltInMethodProxy(object):
584 def __init__(self, ml_name, pyop_m_self):
585 self.ml_name = ml_name
586 self.pyop_m_self = pyop_m_self
587
588 def __repr__(self):
589 return ('<built-in method %s of %s object at remote 0x%x>'
590 % (self.ml_name,
591 self.pyop_m_self.safe_tp_name(),
592 self.pyop_m_self.as_address())
593 )
594
595class PyCFunctionObjectPtr(PyObjectPtr):
596 """
597 Class wrapping a gdb.Value that's a PyCFunctionObject*
598 (see Include/methodobject.h and Objects/methodobject.c)
599 """
600 _typename = 'PyCFunctionObject'
601
602 def proxyval(self, visited):
603 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
604 ml_name = m_ml['ml_name'].string()
605
606 pyop_m_self = self.pyop_field('m_self')
607 if pyop_m_self.is_null():
608 return BuiltInFunctionProxy(ml_name)
609 else:
610 return BuiltInMethodProxy(ml_name, pyop_m_self)
611
612
613class PyCodeObjectPtr(PyObjectPtr):
614 """
615 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
616 within the process being debugged.
617 """
618 _typename = 'PyCodeObject'
619
620 def addr2line(self, addrq):
621 '''
622 Get the line number for a given bytecode offset
623
624 Analogous to PyCode_Addr2Line; translated from pseudocode in
625 Objects/lnotab_notes.txt
626 '''
627 co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
628
629 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
630 # not 0, as lnotab_notes.txt has it:
631 lineno = int_from_int(self.field('co_firstlineno'))
632
633 addr = 0
634 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
635 addr += ord(addr_incr)
636 if addr > addrq:
637 return lineno
638 lineno += ord(line_incr)
639 return lineno
640
641
642class PyDictObjectPtr(PyObjectPtr):
643 """
644 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
645 within the process being debugged.
646 """
647 _typename = 'PyDictObject'
648
649 def iteritems(self):
650 '''
651 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
Ezio Melotti7c4a7e62013-08-26 01:32:56 +0300652 analogous to dict.iteritems()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000653 '''
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400654 keys = self.field('ma_keys')
655 values = self.field('ma_values')
656 for i in safe_range(keys['dk_size']):
657 ep = keys['dk_entries'].address + i
658 if long(values):
659 pyop_value = PyObjectPtr.from_pyobject_ptr(values[i])
660 else:
661 pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000662 if not pyop_value.is_null():
663 pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
664 yield (pyop_key, pyop_value)
665
666 def proxyval(self, visited):
667 # Guard against infinite loops:
668 if self.as_address() in visited:
669 return ProxyAlreadyVisited('{...}')
670 visited.add(self.as_address())
671
672 result = {}
673 for pyop_key, pyop_value in self.iteritems():
674 proxy_key = pyop_key.proxyval(visited)
675 proxy_value = pyop_value.proxyval(visited)
676 result[proxy_key] = proxy_value
677 return result
678
679 def write_repr(self, out, visited):
680 # Guard against infinite loops:
681 if self.as_address() in visited:
682 out.write('{...}')
683 return
684 visited.add(self.as_address())
685
686 out.write('{')
687 first = True
688 for pyop_key, pyop_value in self.iteritems():
689 if not first:
690 out.write(', ')
691 first = False
692 pyop_key.write_repr(out, visited)
693 out.write(': ')
694 pyop_value.write_repr(out, visited)
695 out.write('}')
696
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000697class PyListObjectPtr(PyObjectPtr):
698 _typename = 'PyListObject'
699
700 def __getitem__(self, i):
701 # Get the gdb.Value for the (PyObject*) with the given index:
702 field_ob_item = self.field('ob_item')
703 return field_ob_item[i]
704
705 def proxyval(self, visited):
706 # Guard against infinite loops:
707 if self.as_address() in visited:
708 return ProxyAlreadyVisited('[...]')
709 visited.add(self.as_address())
710
711 result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
712 for i in safe_range(int_from_int(self.field('ob_size')))]
713 return result
714
715 def write_repr(self, out, visited):
716 # Guard against infinite loops:
717 if self.as_address() in visited:
718 out.write('[...]')
719 return
720 visited.add(self.as_address())
721
722 out.write('[')
723 for i in safe_range(int_from_int(self.field('ob_size'))):
724 if i > 0:
725 out.write(', ')
726 element = PyObjectPtr.from_pyobject_ptr(self[i])
727 element.write_repr(out, visited)
728 out.write(']')
729
730class PyLongObjectPtr(PyObjectPtr):
731 _typename = 'PyLongObject'
732
733 def proxyval(self, visited):
734 '''
735 Python's Include/longobjrep.h has this declaration:
736 struct _longobject {
737 PyObject_VAR_HEAD
738 digit ob_digit[1];
739 };
740
741 with this description:
742 The absolute value of a number is equal to
743 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
744 Negative numbers are represented with ob_size < 0;
745 zero is represented by ob_size == 0.
746
747 where SHIFT can be either:
748 #define PyLong_SHIFT 30
749 #define PyLong_SHIFT 15
750 '''
751 ob_size = long(self.field('ob_size'))
752 if ob_size == 0:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100753 return 0
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000754
755 ob_digit = self.field('ob_digit')
756
757 if gdb.lookup_type('digit').sizeof == 2:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100758 SHIFT = 15
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000759 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100760 SHIFT = 30
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000761
762 digits = [long(ob_digit[i]) * 2**(SHIFT*i)
763 for i in safe_range(abs(ob_size))]
764 result = sum(digits)
765 if ob_size < 0:
766 result = -result
767 return result
768
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000769 def write_repr(self, out, visited):
770 # Write this out as a Python 3 int literal, i.e. without the "L" suffix
771 proxy = self.proxyval(visited)
772 out.write("%s" % proxy)
773
774
775class PyBoolObjectPtr(PyLongObjectPtr):
776 """
777 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
778 <bool> instances (Py_True/Py_False) within the process being debugged.
779 """
780 def proxyval(self, visited):
781 if PyLongObjectPtr.proxyval(self, visited):
782 return True
783 else:
784 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000785
786class PyNoneStructPtr(PyObjectPtr):
787 """
788 Class wrapping a gdb.Value that's a PyObject* pointing to the
789 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
790 """
791 _typename = 'PyObject'
792
793 def proxyval(self, visited):
794 return None
795
796
797class PyFrameObjectPtr(PyObjectPtr):
798 _typename = 'PyFrameObject'
799
Victor Stinnerd2084162011-12-19 13:42:24 +0100800 def __init__(self, gdbval, cast_to=None):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000801 PyObjectPtr.__init__(self, gdbval, cast_to)
802
803 if not self.is_optimized_out():
804 self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
805 self.co_name = self.co.pyop_field('co_name')
806 self.co_filename = self.co.pyop_field('co_filename')
807
808 self.f_lineno = int_from_int(self.field('f_lineno'))
809 self.f_lasti = int_from_int(self.field('f_lasti'))
810 self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
811 self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
812
813 def iter_locals(self):
814 '''
815 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
816 the local variables of this frame
817 '''
818 if self.is_optimized_out():
819 return
820
821 f_localsplus = self.field('f_localsplus')
822 for i in safe_range(self.co_nlocals):
823 pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
824 if not pyop_value.is_null():
825 pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
826 yield (pyop_name, pyop_value)
827
828 def iter_globals(self):
829 '''
830 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
831 the global variables of this frame
832 '''
833 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100834 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000835
836 pyop_globals = self.pyop_field('f_globals')
837 return pyop_globals.iteritems()
838
839 def iter_builtins(self):
840 '''
841 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
842 the builtin variables
843 '''
844 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100845 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000846
847 pyop_builtins = self.pyop_field('f_builtins')
848 return pyop_builtins.iteritems()
849
850 def get_var_by_name(self, name):
851 '''
852 Look for the named local variable, returning a (PyObjectPtr, scope) pair
853 where scope is a string 'local', 'global', 'builtin'
854
855 If not found, return (None, None)
856 '''
857 for pyop_name, pyop_value in self.iter_locals():
858 if name == pyop_name.proxyval(set()):
859 return pyop_value, 'local'
860 for pyop_name, pyop_value in self.iter_globals():
861 if name == pyop_name.proxyval(set()):
862 return pyop_value, 'global'
863 for pyop_name, pyop_value in self.iter_builtins():
864 if name == pyop_name.proxyval(set()):
865 return pyop_value, 'builtin'
866 return None, None
867
868 def filename(self):
869 '''Get the path of the current Python source file, as a string'''
870 if self.is_optimized_out():
871 return '(frame information optimized out)'
872 return self.co_filename.proxyval(set())
873
874 def current_line_num(self):
875 '''Get current line number as an integer (1-based)
876
877 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
878
879 See Objects/lnotab_notes.txt
880 '''
881 if self.is_optimized_out():
882 return None
883 f_trace = self.field('f_trace')
884 if long(f_trace) != 0:
885 # we have a non-NULL f_trace:
886 return self.f_lineno
887 else:
888 #try:
889 return self.co.addr2line(self.f_lasti)
890 #except ValueError:
891 # return self.f_lineno
892
893 def current_line(self):
894 '''Get the text of the current source line as a string, with a trailing
895 newline character'''
896 if self.is_optimized_out():
897 return '(frame information optimized out)'
Victor Stinner6ffbee72010-10-17 19:35:30 +0000898 filename = self.filename()
Victor Stinnerd57c5c82011-07-01 12:57:44 +0200899 try:
900 f = open(os_fsencode(filename), 'r')
901 except IOError:
902 return None
903 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000904 all_lines = f.readlines()
905 # Convert from 1-based current_line_num to 0-based list offset:
906 return all_lines[self.current_line_num()-1]
907
908 def write_repr(self, out, visited):
909 if self.is_optimized_out():
910 out.write('(frame information optimized out)')
911 return
912 out.write('Frame 0x%x, for file %s, line %i, in %s ('
913 % (self.as_address(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000914 self.co_filename.proxyval(visited),
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000915 self.current_line_num(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000916 self.co_name.proxyval(visited)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000917 first = True
918 for pyop_name, pyop_value in self.iter_locals():
919 if not first:
920 out.write(', ')
921 first = False
922
923 out.write(pyop_name.proxyval(visited))
924 out.write('=')
925 pyop_value.write_repr(out, visited)
926
927 out.write(')')
928
Victor Stinnere670c882011-05-13 17:40:15 +0200929 def print_traceback(self):
930 if self.is_optimized_out():
931 sys.stdout.write(' (frame information optimized out)\n')
Victor Stinnerd2084162011-12-19 13:42:24 +0100932 return
Victor Stinnere670c882011-05-13 17:40:15 +0200933 visited = set()
934 sys.stdout.write(' File "%s", line %i, in %s\n'
935 % (self.co_filename.proxyval(visited),
936 self.current_line_num(),
937 self.co_name.proxyval(visited)))
938
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000939class PySetObjectPtr(PyObjectPtr):
940 _typename = 'PySetObject'
941
Antoine Pitrou9d952542013-08-24 21:07:07 +0200942 @classmethod
943 def _dummy_key(self):
944 return gdb.lookup_global_symbol('_PySet_Dummy').value()
945
946 def __iter__(self):
947 dummy_ptr = self._dummy_key()
948 table = self.field('table')
949 for i in safe_range(self.field('mask') + 1):
950 setentry = table[i]
951 key = setentry['key']
952 if key != 0 and key != dummy_ptr:
953 yield PyObjectPtr.from_pyobject_ptr(key)
954
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000955 def proxyval(self, visited):
956 # Guard against infinite loops:
957 if self.as_address() in visited:
958 return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
959 visited.add(self.as_address())
960
Antoine Pitrou9d952542013-08-24 21:07:07 +0200961 members = (key.proxyval(visited) for key in self)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000962 if self.safe_tp_name() == 'frozenset':
963 return frozenset(members)
964 else:
965 return set(members)
966
967 def write_repr(self, out, visited):
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000968 # Emulate Python 3's set_repr
969 tp_name = self.safe_tp_name()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000970
971 # Guard against infinite loops:
972 if self.as_address() in visited:
973 out.write('(...)')
974 return
975 visited.add(self.as_address())
976
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000977 # Python 3's set_repr special-cases the empty set:
978 if not self.field('used'):
979 out.write(tp_name)
980 out.write('()')
981 return
982
983 # Python 3 uses {} for set literals:
984 if tp_name != 'set':
985 out.write(tp_name)
986 out.write('(')
987
988 out.write('{')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000989 first = True
Antoine Pitrou9d952542013-08-24 21:07:07 +0200990 for key in self:
991 if not first:
992 out.write(', ')
993 first = False
994 key.write_repr(out, visited)
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000995 out.write('}')
996
997 if tp_name != 'set':
998 out.write(')')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000999
1000
Victor Stinner67df3a42010-04-21 13:53:05 +00001001class PyBytesObjectPtr(PyObjectPtr):
1002 _typename = 'PyBytesObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001003
1004 def __str__(self):
1005 field_ob_size = self.field('ob_size')
1006 field_ob_sval = self.field('ob_sval')
1007 char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr)
1008 return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1009
1010 def proxyval(self, visited):
1011 return str(self)
1012
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001013 def write_repr(self, out, visited):
1014 # Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1015
1016 # Get a PyStringObject* within the Python 2 gdb process:
1017 proxy = self.proxyval(visited)
1018
1019 # Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1020 # to Python 2 code:
1021 quote = "'"
1022 if "'" in proxy and not '"' in proxy:
1023 quote = '"'
1024 out.write('b')
1025 out.write(quote)
1026 for byte in proxy:
1027 if byte == quote or byte == '\\':
1028 out.write('\\')
1029 out.write(byte)
1030 elif byte == '\t':
1031 out.write('\\t')
1032 elif byte == '\n':
1033 out.write('\\n')
1034 elif byte == '\r':
1035 out.write('\\r')
1036 elif byte < ' ' or ord(byte) >= 0x7f:
1037 out.write('\\x')
1038 out.write(hexdigits[(ord(byte) & 0xf0) >> 4])
1039 out.write(hexdigits[ord(byte) & 0xf])
1040 else:
1041 out.write(byte)
1042 out.write(quote)
1043
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001044class PyTupleObjectPtr(PyObjectPtr):
1045 _typename = 'PyTupleObject'
1046
1047 def __getitem__(self, i):
1048 # Get the gdb.Value for the (PyObject*) with the given index:
1049 field_ob_item = self.field('ob_item')
1050 return field_ob_item[i]
1051
1052 def proxyval(self, visited):
1053 # Guard against infinite loops:
1054 if self.as_address() in visited:
1055 return ProxyAlreadyVisited('(...)')
1056 visited.add(self.as_address())
1057
1058 result = tuple([PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1059 for i in safe_range(int_from_int(self.field('ob_size')))])
1060 return result
1061
1062 def write_repr(self, out, visited):
1063 # Guard against infinite loops:
1064 if self.as_address() in visited:
1065 out.write('(...)')
1066 return
1067 visited.add(self.as_address())
1068
1069 out.write('(')
1070 for i in safe_range(int_from_int(self.field('ob_size'))):
1071 if i > 0:
1072 out.write(', ')
1073 element = PyObjectPtr.from_pyobject_ptr(self[i])
1074 element.write_repr(out, visited)
1075 if self.field('ob_size') == 1:
1076 out.write(',)')
1077 else:
1078 out.write(')')
1079
1080class PyTypeObjectPtr(PyObjectPtr):
1081 _typename = 'PyTypeObject'
1082
1083
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001084def _unichr_is_printable(char):
1085 # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1086 if char == u" ":
1087 return True
1088 import unicodedata
Antoine Pitroub41e1282010-09-08 20:57:48 +00001089 return unicodedata.category(char) not in ("C", "Z")
1090
1091if sys.maxunicode >= 0x10000:
1092 _unichr = unichr
1093else:
1094 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1095 def _unichr(x):
1096 if x < 0x10000:
1097 return unichr(x)
1098 x -= 0x10000
1099 ch1 = 0xD800 | (x >> 10)
1100 ch2 = 0xDC00 | (x & 0x3FF)
1101 return unichr(ch1) + unichr(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001102
1103
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001104class PyUnicodeObjectPtr(PyObjectPtr):
1105 _typename = 'PyUnicodeObject'
1106
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001107 def char_width(self):
1108 _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1109 return _type_Py_UNICODE.sizeof
1110
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001111 def proxyval(self, visited):
Victor Stinner0c4fbff2011-12-08 00:08:22 +01001112 global _is_pep393
1113 if _is_pep393 is None:
1114 fields = gdb.lookup_type('PyUnicodeObject').target().fields()
1115 _is_pep393 = 'data' in [f.name for f in fields]
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001116 if _is_pep393:
1117 # Python 3.3 and newer
1118 may_have_surrogates = False
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001119 compact = self.field('_base')
1120 ascii = compact['_base']
1121 state = ascii['state']
Victor Stinnera3b334d2011-10-03 13:53:37 +02001122 is_compact_ascii = (int(state['ascii']) and int(state['compact']))
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001123 if not int(state['ready']):
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001124 # string is not ready
Victor Stinnerf16a3502011-11-04 22:34:01 +01001125 field_length = long(compact['wstr_length'])
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001126 may_have_surrogates = True
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001127 field_str = ascii['wstr']
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001128 else:
Victor Stinnerf16a3502011-11-04 22:34:01 +01001129 field_length = long(ascii['length'])
Victor Stinnera3b334d2011-10-03 13:53:37 +02001130 if is_compact_ascii:
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001131 field_str = ascii.address + 1
1132 elif int(state['compact']):
1133 field_str = compact.address + 1
1134 else:
1135 field_str = self.field('data')['any']
1136 repr_kind = int(state['kind'])
1137 if repr_kind == 1:
1138 field_str = field_str.cast(_type_unsigned_char_ptr)
1139 elif repr_kind == 2:
1140 field_str = field_str.cast(_type_unsigned_short_ptr)
Antoine Pitrou3c0c5f22011-10-08 19:33:24 +02001141 elif repr_kind == 4:
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001142 field_str = field_str.cast(_type_unsigned_int_ptr)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001143 else:
1144 # Python 3.2 and earlier
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001145 field_length = long(self.field('length'))
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001146 field_str = self.field('str')
1147 may_have_surrogates = self.char_width() == 2
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001148
1149 # Gather a list of ints from the Py_UNICODE array; these are either
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001150 # UCS-1, UCS-2 or UCS-4 code points:
1151 if not may_have_surrogates:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001152 Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1153 else:
1154 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1155 # inferior process: we must join surrogate pairs.
1156 Py_UNICODEs = []
1157 i = 0
Antoine Pitroub1856d72010-09-08 21:07:40 +00001158 limit = safety_limit(field_length)
1159 while i < limit:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001160 ucs = int(field_str[i])
1161 i += 1
1162 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1163 Py_UNICODEs.append(ucs)
1164 continue
1165 # This could be a surrogate pair.
1166 ucs2 = int(field_str[i])
1167 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1168 continue
1169 code = (ucs & 0x03FF) << 10
1170 code |= ucs2 & 0x03FF
1171 code += 0x00010000
1172 Py_UNICODEs.append(code)
1173 i += 1
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001174
1175 # Convert the int code points to unicode characters, and generate a
Antoine Pitroub41e1282010-09-08 20:57:48 +00001176 # local unicode instance.
1177 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
Victor Stinnerd8a5cc92013-04-11 21:37:45 +02001178 result = u''.join([
1179 (_unichr(ucs) if ucs <= 0x10ffff else '\ufffd')
1180 for ucs in Py_UNICODEs])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001181 return result
1182
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001183 def write_repr(self, out, visited):
1184 # Write this out as a Python 3 str literal, i.e. without a "u" prefix
1185
1186 # Get a PyUnicodeObject* within the Python 2 gdb process:
1187 proxy = self.proxyval(visited)
1188
1189 # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1190 # to Python 2:
1191 if "'" in proxy and '"' not in proxy:
1192 quote = '"'
1193 else:
1194 quote = "'"
1195 out.write(quote)
1196
1197 i = 0
1198 while i < len(proxy):
1199 ch = proxy[i]
1200 i += 1
1201
1202 # Escape quotes and backslashes
1203 if ch == quote or ch == '\\':
1204 out.write('\\')
1205 out.write(ch)
1206
1207 # Map special whitespace to '\t', \n', '\r'
1208 elif ch == '\t':
1209 out.write('\\t')
1210 elif ch == '\n':
1211 out.write('\\n')
1212 elif ch == '\r':
1213 out.write('\\r')
1214
1215 # Map non-printable US ASCII to '\xhh' */
1216 elif ch < ' ' or ch == 0x7F:
1217 out.write('\\x')
1218 out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
1219 out.write(hexdigits[ord(ch) & 0x000F])
1220
1221 # Copy ASCII characters as-is
1222 elif ord(ch) < 0x7F:
1223 out.write(ch)
1224
1225 # Non-ASCII characters
1226 else:
Victor Stinner150016f2010-05-19 23:04:56 +00001227 ucs = ch
Antoine Pitroub41e1282010-09-08 20:57:48 +00001228 ch2 = None
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001229 if sys.maxunicode < 0x10000:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001230 # If sizeof(Py_UNICODE) is 2 here (in gdb), join
1231 # surrogate pairs before calling _unichr_is_printable.
Victor Stinner150016f2010-05-19 23:04:56 +00001232 if (i < len(proxy)
1233 and 0xD800 <= ord(ch) < 0xDC00 \
1234 and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001235 ch2 = proxy[i]
Antoine Pitroub41e1282010-09-08 20:57:48 +00001236 ucs = ch + ch2
Victor Stinner150016f2010-05-19 23:04:56 +00001237 i += 1
Victor Stinner150016f2010-05-19 23:04:56 +00001238
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001239 # Unfortuately, Python 2's unicode type doesn't seem
1240 # to expose the "isprintable" method
Victor Stinner150016f2010-05-19 23:04:56 +00001241 printable = _unichr_is_printable(ucs)
1242 if printable:
1243 try:
1244 ucs.encode(ENCODING)
1245 except UnicodeEncodeError:
1246 printable = False
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001247
1248 # Map Unicode whitespace and control characters
1249 # (categories Z* and C* except ASCII space)
Victor Stinner150016f2010-05-19 23:04:56 +00001250 if not printable:
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001251 if ch2 is not None:
1252 # Match Python 3's representation of non-printable
1253 # wide characters.
1254 code = (ord(ch) & 0x03FF) << 10
1255 code |= ord(ch2) & 0x03FF
1256 code += 0x00010000
1257 else:
1258 code = ord(ucs)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001259
1260 # Map 8-bit characters to '\\xhh'
Victor Stinner150016f2010-05-19 23:04:56 +00001261 if code <= 0xff:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001262 out.write('\\x')
Victor Stinner150016f2010-05-19 23:04:56 +00001263 out.write(hexdigits[(code >> 4) & 0x000F])
1264 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001265 # Map 21-bit characters to '\U00xxxxxx'
Victor Stinner150016f2010-05-19 23:04:56 +00001266 elif code >= 0x10000:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001267 out.write('\\U')
Victor Stinner150016f2010-05-19 23:04:56 +00001268 out.write(hexdigits[(code >> 28) & 0x0000000F])
1269 out.write(hexdigits[(code >> 24) & 0x0000000F])
1270 out.write(hexdigits[(code >> 20) & 0x0000000F])
1271 out.write(hexdigits[(code >> 16) & 0x0000000F])
1272 out.write(hexdigits[(code >> 12) & 0x0000000F])
1273 out.write(hexdigits[(code >> 8) & 0x0000000F])
1274 out.write(hexdigits[(code >> 4) & 0x0000000F])
1275 out.write(hexdigits[code & 0x0000000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001276 # Map 16-bit characters to '\uxxxx'
1277 else:
1278 out.write('\\u')
Victor Stinner150016f2010-05-19 23:04:56 +00001279 out.write(hexdigits[(code >> 12) & 0x000F])
1280 out.write(hexdigits[(code >> 8) & 0x000F])
1281 out.write(hexdigits[(code >> 4) & 0x000F])
1282 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001283 else:
1284 # Copy characters as-is
1285 out.write(ch)
Antoine Pitroub41e1282010-09-08 20:57:48 +00001286 if ch2 is not None:
Victor Stinner150016f2010-05-19 23:04:56 +00001287 out.write(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001288
1289 out.write(quote)
1290
1291
1292
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001293
1294def int_from_int(gdbval):
1295 return int(str(gdbval))
1296
1297
1298def stringify(val):
1299 # TODO: repr() puts everything on one line; pformat can be nicer, but
1300 # can lead to v.long results; this function isolates the choice
1301 if True:
1302 return repr(val)
1303 else:
1304 from pprint import pformat
1305 return pformat(val)
1306
1307
1308class PyObjectPtrPrinter:
1309 "Prints a (PyObject*)"
1310
1311 def __init__ (self, gdbval):
1312 self.gdbval = gdbval
1313
1314 def to_string (self):
1315 pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1316 if True:
1317 return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1318 else:
1319 # Generate full proxy value then stringify it.
1320 # Doing so could be expensive
1321 proxyval = pyop.proxyval(set())
1322 return stringify(proxyval)
1323
1324def pretty_printer_lookup(gdbval):
1325 type = gdbval.type.unqualified()
1326 if type.code == gdb.TYPE_CODE_PTR:
1327 type = type.target().unqualified()
1328 t = str(type)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001329 if t in ("PyObject", "PyFrameObject", "PyUnicodeObject"):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001330 return PyObjectPtrPrinter(gdbval)
1331
1332"""
1333During development, I've been manually invoking the code in this way:
1334(gdb) python
1335
1336import sys
1337sys.path.append('/home/david/coding/python-gdb')
1338import libpython
1339end
1340
1341then reloading it after each edit like this:
1342(gdb) python reload(libpython)
1343
1344The following code should ensure that the prettyprinter is registered
1345if the code is autoloaded by gdb when visiting libpython.so, provided
1346that this python file is installed to the same path as the library (or its
1347.debug file) plus a "-gdb.py" suffix, e.g:
1348 /usr/lib/libpython2.6.so.1.0-gdb.py
1349 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1350"""
1351def register (obj):
Benjamin Petersonb29614e2012-10-09 11:16:03 -04001352 if obj is None:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001353 obj = gdb
1354
1355 # Wire up the pretty-printer
1356 obj.pretty_printers.append(pretty_printer_lookup)
1357
1358register (gdb.current_objfile ())
1359
1360
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001361
1362# Unfortunately, the exact API exposed by the gdb module varies somewhat
1363# from build to build
1364# See http://bugs.python.org/issue8279?#msg102276
1365
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001366class Frame(object):
1367 '''
1368 Wrapper for gdb.Frame, adding various methods
1369 '''
1370 def __init__(self, gdbframe):
1371 self._gdbframe = gdbframe
1372
1373 def older(self):
1374 older = self._gdbframe.older()
1375 if older:
1376 return Frame(older)
1377 else:
1378 return None
1379
1380 def newer(self):
1381 newer = self._gdbframe.newer()
1382 if newer:
1383 return Frame(newer)
1384 else:
1385 return None
1386
1387 def select(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001388 '''If supported, select this frame and return True; return False if unsupported
1389
1390 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1391 onwards, but absent on Ubuntu buildbot'''
1392 if not hasattr(self._gdbframe, 'select'):
1393 print ('Unable to select frame: '
1394 'this build of gdb does not expose a gdb.Frame.select method')
1395 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001396 self._gdbframe.select()
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001397 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001398
1399 def get_index(self):
1400 '''Calculate index of frame, starting at 0 for the newest frame within
1401 this thread'''
1402 index = 0
1403 # Go down until you reach the newest frame:
1404 iter_frame = self
1405 while iter_frame.newer():
1406 index += 1
1407 iter_frame = iter_frame.newer()
1408 return index
1409
David Malcolm8d37ffa2012-06-27 14:15:34 -04001410 # We divide frames into:
1411 # - "python frames":
1412 # - "bytecode frames" i.e. PyEval_EvalFrameEx
1413 # - "other python frames": things that are of interest from a python
1414 # POV, but aren't bytecode (e.g. GC, GIL)
1415 # - everything else
1416
1417 def is_python_frame(self):
1418 '''Is this a PyEval_EvalFrameEx frame, or some other important
1419 frame? (see is_other_python_frame for what "important" means in this
1420 context)'''
1421 if self.is_evalframeex():
1422 return True
1423 if self.is_other_python_frame():
1424 return True
1425 return False
1426
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001427 def is_evalframeex(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001428 '''Is this a PyEval_EvalFrameEx frame?'''
Victor Stinner50eb60e2010-04-20 22:32:07 +00001429 if self._gdbframe.name() == 'PyEval_EvalFrameEx':
1430 '''
1431 I believe we also need to filter on the inline
1432 struct frame_id.inline_depth, only regarding frames with
1433 an inline depth of 0 as actually being this function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001434
Victor Stinner50eb60e2010-04-20 22:32:07 +00001435 So we reject those with type gdb.INLINE_FRAME
1436 '''
1437 if self._gdbframe.type() == gdb.NORMAL_FRAME:
1438 # We have a PyEval_EvalFrameEx frame:
1439 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001440
1441 return False
1442
David Malcolm8d37ffa2012-06-27 14:15:34 -04001443 def is_other_python_frame(self):
1444 '''Is this frame worth displaying in python backtraces?
1445 Examples:
1446 - waiting on the GIL
1447 - garbage-collecting
1448 - within a CFunction
1449 If it is, return a descriptive string
1450 For other frames, return False
1451 '''
1452 if self.is_waiting_for_gil():
1453 return 'Waiting for the GIL'
1454 elif self.is_gc_collect():
1455 return 'Garbage-collecting'
1456 else:
1457 # Detect invocations of PyCFunction instances:
1458 older = self.older()
1459 if older and older._gdbframe.name() == 'PyCFunction_Call':
1460 # Within that frame:
1461 # "func" is the local containing the PyObject* of the
1462 # PyCFunctionObject instance
1463 # "f" is the same value, but cast to (PyCFunctionObject*)
1464 # "self" is the (PyObject*) of the 'self'
1465 try:
1466 # Use the prettyprinter for the func:
1467 func = older._gdbframe.read_var('func')
1468 return str(func)
1469 except RuntimeError:
1470 return 'PyCFunction invocation (unable to read "func")'
1471
1472 # This frame isn't worth reporting:
1473 return False
1474
1475 def is_waiting_for_gil(self):
1476 '''Is this frame waiting on the GIL?'''
1477 # This assumes the _POSIX_THREADS version of Python/ceval_gil.h:
1478 name = self._gdbframe.name()
1479 if name:
David Malcolmd08b2102013-05-06 14:47:15 -04001480 return 'pthread_cond_timedwait' in name
David Malcolm8d37ffa2012-06-27 14:15:34 -04001481
1482 def is_gc_collect(self):
Ezio Melotti3f5db392013-01-27 06:20:14 +02001483 '''Is this frame "collect" within the garbage-collector?'''
David Malcolm8d37ffa2012-06-27 14:15:34 -04001484 return self._gdbframe.name() == 'collect'
1485
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001486 def get_pyop(self):
1487 try:
1488 f = self._gdbframe.read_var('f')
Victor Stinnerd2084162011-12-19 13:42:24 +01001489 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1490 if not frame.is_optimized_out():
1491 return frame
1492 # gdb is unable to get the "f" argument of PyEval_EvalFrameEx()
1493 # because it was "optimized out". Try to get "f" from the frame
1494 # of the caller, PyEval_EvalCodeEx().
1495 orig_frame = frame
1496 caller = self._gdbframe.older()
1497 if caller:
1498 f = caller.read_var('f')
1499 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1500 if not frame.is_optimized_out():
1501 return frame
1502 return orig_frame
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001503 except ValueError:
1504 return None
1505
1506 @classmethod
1507 def get_selected_frame(cls):
1508 _gdbframe = gdb.selected_frame()
1509 if _gdbframe:
1510 return Frame(_gdbframe)
1511 return None
1512
1513 @classmethod
1514 def get_selected_python_frame(cls):
David Malcolm8d37ffa2012-06-27 14:15:34 -04001515 '''Try to obtain the Frame for the python-related code in the selected
1516 frame, or None'''
1517 frame = cls.get_selected_frame()
1518
1519 while frame:
1520 if frame.is_python_frame():
1521 return frame
1522 frame = frame.older()
1523
1524 # Not found:
1525 return None
1526
1527 @classmethod
1528 def get_selected_bytecode_frame(cls):
1529 '''Try to obtain the Frame for the python bytecode interpreter in the
1530 selected GDB frame, or None'''
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001531 frame = cls.get_selected_frame()
1532
1533 while frame:
1534 if frame.is_evalframeex():
1535 return frame
1536 frame = frame.older()
1537
1538 # Not found:
1539 return None
1540
1541 def print_summary(self):
1542 if self.is_evalframeex():
1543 pyop = self.get_pyop()
1544 if pyop:
Victor Stinner0e5a41b2010-08-17 22:49:25 +00001545 line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1546 write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
Victor Stinnerd2084162011-12-19 13:42:24 +01001547 if not pyop.is_optimized_out():
1548 line = pyop.current_line()
1549 if line is not None:
1550 sys.stdout.write(' %s\n' % line.strip())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001551 else:
1552 sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1553 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001554 info = self.is_other_python_frame()
1555 if info:
1556 sys.stdout.write('#%i %s\n' % (self.get_index(), info))
1557 else:
1558 sys.stdout.write('#%i\n' % self.get_index())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001559
Victor Stinnere670c882011-05-13 17:40:15 +02001560 def print_traceback(self):
1561 if self.is_evalframeex():
1562 pyop = self.get_pyop()
1563 if pyop:
1564 pyop.print_traceback()
Victor Stinnerd2084162011-12-19 13:42:24 +01001565 if not pyop.is_optimized_out():
1566 line = pyop.current_line()
1567 if line is not None:
1568 sys.stdout.write(' %s\n' % line.strip())
Victor Stinnere670c882011-05-13 17:40:15 +02001569 else:
1570 sys.stdout.write(' (unable to read python frame information)\n')
1571 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001572 info = self.is_other_python_frame()
1573 if info:
1574 sys.stdout.write(' %s\n' % info)
1575 else:
1576 sys.stdout.write(' (not a python frame)\n')
Victor Stinnere670c882011-05-13 17:40:15 +02001577
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001578class PyList(gdb.Command):
1579 '''List the current Python source code, if any
1580
1581 Use
1582 py-list START
1583 to list at a different line number within the python source.
1584
1585 Use
1586 py-list START, END
1587 to list a specific range of lines within the python source.
1588 '''
1589
1590 def __init__(self):
1591 gdb.Command.__init__ (self,
1592 "py-list",
1593 gdb.COMMAND_FILES,
1594 gdb.COMPLETE_NONE)
1595
1596
1597 def invoke(self, args, from_tty):
1598 import re
1599
1600 start = None
1601 end = None
1602
1603 m = re.match(r'\s*(\d+)\s*', args)
1604 if m:
1605 start = int(m.group(0))
1606 end = start + 10
1607
1608 m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1609 if m:
1610 start, end = map(int, m.groups())
1611
David Malcolm8d37ffa2012-06-27 14:15:34 -04001612 # py-list requires an actual PyEval_EvalFrameEx frame:
1613 frame = Frame.get_selected_bytecode_frame()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001614 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001615 print('Unable to locate gdb frame for python bytecode interpreter')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001616 return
1617
1618 pyop = frame.get_pyop()
Victor Stinnerd2084162011-12-19 13:42:24 +01001619 if not pyop or pyop.is_optimized_out():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001620 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001621 return
1622
1623 filename = pyop.filename()
1624 lineno = pyop.current_line_num()
1625
1626 if start is None:
1627 start = lineno - 5
1628 end = lineno + 5
1629
1630 if start<1:
1631 start = 1
1632
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001633 try:
1634 f = open(os_fsencode(filename), 'r')
1635 except IOError as err:
1636 sys.stdout.write('Unable to open %s: %s\n'
1637 % (filename, err))
1638 return
1639 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001640 all_lines = f.readlines()
1641 # start and end are 1-based, all_lines is 0-based;
1642 # so [start-1:end] as a python slice gives us [start, end] as a
1643 # closed interval
1644 for i, line in enumerate(all_lines[start-1:end]):
1645 linestr = str(i+start)
1646 # Highlight current line:
1647 if i + start == lineno:
1648 linestr = '>' + linestr
1649 sys.stdout.write('%4s %s' % (linestr, line))
1650
1651
1652# ...and register the command:
1653PyList()
1654
1655def move_in_stack(move_up):
1656 '''Move up or down the stack (for the py-up/py-down command)'''
1657 frame = Frame.get_selected_python_frame()
1658 while frame:
1659 if move_up:
1660 iter_frame = frame.older()
1661 else:
1662 iter_frame = frame.newer()
1663
1664 if not iter_frame:
1665 break
1666
David Malcolm8d37ffa2012-06-27 14:15:34 -04001667 if iter_frame.is_python_frame():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001668 # Result:
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001669 if iter_frame.select():
1670 iter_frame.print_summary()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001671 return
1672
1673 frame = iter_frame
1674
1675 if move_up:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001676 print('Unable to find an older python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001677 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001678 print('Unable to find a newer python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001679
1680class PyUp(gdb.Command):
1681 'Select and print the python stack frame that called this one (if any)'
1682 def __init__(self):
1683 gdb.Command.__init__ (self,
1684 "py-up",
1685 gdb.COMMAND_STACK,
1686 gdb.COMPLETE_NONE)
1687
1688
1689 def invoke(self, args, from_tty):
1690 move_in_stack(move_up=True)
1691
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001692class PyDown(gdb.Command):
1693 'Select and print the python stack frame called by this one (if any)'
1694 def __init__(self):
1695 gdb.Command.__init__ (self,
1696 "py-down",
1697 gdb.COMMAND_STACK,
1698 gdb.COMPLETE_NONE)
1699
1700
1701 def invoke(self, args, from_tty):
1702 move_in_stack(move_up=False)
1703
Victor Stinner50eb60e2010-04-20 22:32:07 +00001704# Not all builds of gdb have gdb.Frame.select
1705if hasattr(gdb.Frame, 'select'):
1706 PyUp()
1707 PyDown()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001708
Victor Stinnere670c882011-05-13 17:40:15 +02001709class PyBacktraceFull(gdb.Command):
1710 'Display the current python frame and all the frames within its call stack (if any)'
1711 def __init__(self):
1712 gdb.Command.__init__ (self,
1713 "py-bt-full",
1714 gdb.COMMAND_STACK,
1715 gdb.COMPLETE_NONE)
1716
1717
1718 def invoke(self, args, from_tty):
1719 frame = Frame.get_selected_python_frame()
1720 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001721 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001722 frame.print_summary()
1723 frame = frame.older()
1724
1725PyBacktraceFull()
1726
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001727class PyBacktrace(gdb.Command):
1728 'Display the current python frame and all the frames within its call stack (if any)'
1729 def __init__(self):
1730 gdb.Command.__init__ (self,
1731 "py-bt",
1732 gdb.COMMAND_STACK,
1733 gdb.COMPLETE_NONE)
1734
1735
1736 def invoke(self, args, from_tty):
Victor Stinnere670c882011-05-13 17:40:15 +02001737 sys.stdout.write('Traceback (most recent call first):\n')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001738 frame = Frame.get_selected_python_frame()
1739 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001740 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001741 frame.print_traceback()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001742 frame = frame.older()
1743
1744PyBacktrace()
1745
1746class PyPrint(gdb.Command):
1747 'Look up the given python variable name, and print it'
1748 def __init__(self):
1749 gdb.Command.__init__ (self,
1750 "py-print",
1751 gdb.COMMAND_DATA,
1752 gdb.COMPLETE_NONE)
1753
1754
1755 def invoke(self, args, from_tty):
1756 name = str(args)
1757
1758 frame = Frame.get_selected_python_frame()
1759 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001760 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001761 return
1762
1763 pyop_frame = frame.get_pyop()
1764 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001765 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001766 return
1767
1768 pyop_var, scope = pyop_frame.get_var_by_name(name)
1769
1770 if pyop_var:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001771 print('%s %r = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001772 % (scope,
1773 name,
1774 pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1775 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001776 print('%r not found' % name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001777
1778PyPrint()
1779
1780class PyLocals(gdb.Command):
1781 'Look up the given python variable name, and print it'
1782 def __init__(self):
1783 gdb.Command.__init__ (self,
1784 "py-locals",
1785 gdb.COMMAND_DATA,
1786 gdb.COMPLETE_NONE)
1787
1788
1789 def invoke(self, args, from_tty):
1790 name = str(args)
1791
1792 frame = Frame.get_selected_python_frame()
1793 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001794 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001795 return
1796
1797 pyop_frame = frame.get_pyop()
1798 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001799 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001800 return
1801
1802 for pyop_name, pyop_value in pyop_frame.iter_locals():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001803 print('%s = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001804 % (pyop_name.proxyval(set()),
1805 pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1806
1807PyLocals()