3 # NOTE: this file is taken from the Python source distribution
4 # It can be found under Tools/gdb/libpython.py. It is shipped with Cython
5 # because it's not installed as a python module, and because changes are only
6 # merged into new python versions (v3.2+).
9 From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
10 to be extended with Python code e.g. for library-specific data visualizations,
11 such as for the C++ STL types. Documentation on this API can be seen at:
12 http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
15 This python module deals with the case when the process being debugged (the
16 "inferior process" in gdb parlance) is itself python, or more specifically,
17 linked against libpython. In this situation, almost every item of data is a
18 (PyObject*), and having the debugger merely print their addresses is not very
21 This module embeds knowledge about the implementation details of libpython so
22 that we can emit useful visualizations e.g. a string, a list, a dict, a frame
23 giving file/line information and the state of local variables
25 In particular, given a gdb.Value corresponding to a PyObject* in the inferior
26 process, we can generate a "proxy value" within the gdb process. For example,
27 given a PyObject* in the inferior process that is in fact a PyListObject*
28 holding three PyObject* that turn out to be PyStringObject* instances, we can
29 generate a proxy value within the gdb process that is a list of strings:
32 Doing so can be expensive for complicated graphs of objects, and could take
33 some time, so we also have a "write_repr" method that writes a representation
34 of the data to a file-like object. This allows us to stop the traversal by
35 having the file-like object raise an exception if it gets too much data.
37 With both "proxyval" and "write_repr" we keep track of the set of all addresses
38 visited so far in the traversal, to avoid infinite recursion due to cycles in
39 the graph of object references.
41 We try to defer gdb.lookup_type() invocations for python types until as late as
42 possible: for a dynamically linked python binary, when the process starts in
43 the debugger, the libpython.so hasn't been dynamically loaded yet, so none of
44 the type names are known to the debugger
46 The module also extends gdb with some python-specific commands.
48 from __future__
import with_statement
63 if sys
.version_info
[0] < 3:
64 # I think this is the only way to fix this bug :'(
65 # http://sourceware.org/bugzilla/show_bug.cgi?id=12285
66 out
, err
= sys
.stdout
, sys
.stderr
67 reload(sys
).setdefaultencoding('UTF-8')
71 # Look up the gdb.Type for some standard types:
72 _type_char_ptr
= gdb
.lookup_type('char').pointer() # char*
73 _type_unsigned_char_ptr
= gdb
.lookup_type('unsigned char').pointer()
74 _type_void_ptr
= gdb
.lookup_type('void').pointer() # void*
76 SIZEOF_VOID_P
= _type_void_ptr
.sizeof
78 Py_TPFLAGS_HEAPTYPE
= (1L << 9)
80 Py_TPFLAGS_INT_SUBCLASS
= (1L << 23)
81 Py_TPFLAGS_LONG_SUBCLASS
= (1L << 24)
82 Py_TPFLAGS_LIST_SUBCLASS
= (1L << 25)
83 Py_TPFLAGS_TUPLE_SUBCLASS
= (1L << 26)
84 Py_TPFLAGS_STRING_SUBCLASS
= (1L << 27)
85 Py_TPFLAGS_BYTES_SUBCLASS
= (1L << 27)
86 Py_TPFLAGS_UNICODE_SUBCLASS
= (1L << 28)
87 Py_TPFLAGS_DICT_SUBCLASS
= (1L << 29)
88 Py_TPFLAGS_BASE_EXC_SUBCLASS
= (1L << 30)
89 Py_TPFLAGS_TYPE_SUBCLASS
= (1L << 31)
93 hexdigits
= "0123456789abcdef"
95 ENCODING
= locale
.getpreferredencoding()
97 class NullPyObjectPtr(RuntimeError):
101 def safety_limit(val
):
102 # Given a integer value from the process being debugged, limit it to some
103 # safety threshold so that arbitrary breakage within said process doesn't
104 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
105 return min(val
, 1000)
109 # As per range, but don't trust the value too much: cap it to a safety
110 # threshold in case the data was corrupted
111 return xrange(safety_limit(val
))
113 def write_unicode(file, text
):
114 # Write a byte or unicode string to file. Unicode strings are encoded to
115 # ENCODING encoding with 'backslashreplace' error handler to avoid
116 # UnicodeEncodeError.
117 if isinstance(text
, unicode):
118 text
= text
.encode(ENCODING
, 'backslashreplace')
121 def os_fsencode(filename
):
122 if not isinstance(filename
, unicode):
124 encoding
= sys
.getfilesystemencoding()
125 if encoding
== 'mbcs':
126 # mbcs doesn't support surrogateescape
127 return filename
.encode(encoding
)
129 for char
in filename
:
130 # surrogateescape error handler
131 if 0xDC80 <= ord(char
) <= 0xDCFF:
132 byte
= chr(ord(char
) - 0xDC00)
134 byte
= char
.encode(encoding
)
136 return ''.join(encoded
)
138 class StringTruncated(RuntimeError):
141 class TruncatedStringIO(object):
142 '''Similar to cStringIO, but can truncate the output by raising a
143 StringTruncated exception'''
144 def __init__(self
, maxlen
=None):
148 def write(self
, data
):
150 if len(data
) + len(self
._val
) > self
.maxlen
:
152 self
._val
+= data
[0:self
.maxlen
- len(self
._val
)]
153 raise StringTruncated()
161 # pretty printer lookup
162 all_pretty_typenames
= set()
164 class PrettyPrinterTrackerMeta(type):
166 def __init__(self
, name
, bases
, dict):
167 super(PrettyPrinterTrackerMeta
, self
).__init
__(name
, bases
, dict)
168 all_pretty_typenames
.add(self
._typename
)
171 class PyObjectPtr(object):
173 Class wrapping a gdb.Value that's a either a (PyObject*) within the
174 inferior process, or some subclass pointer e.g. (PyStringObject*)
176 There will be a subclass for every refined PyObject type that we care
179 Note that at every stage the underlying pointer could be NULL, point
180 to corrupt data, etc; this is the debugger, after all.
183 __metaclass__
= PrettyPrinterTrackerMeta
185 _typename
= 'PyObject'
187 def __init__(self
, gdbval
, cast_to
=None):
189 self
._gdbval
= gdbval
.cast(cast_to
)
191 self
._gdbval
= gdbval
193 def field(self
, name
):
195 Get the gdb.Value for the given field within the PyObject, coping with
196 some python 2 versus python 3 differences.
198 Various libpython types are defined using the "PyObject_HEAD" and
199 "PyObject_VAR_HEAD" macros.
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.
204 In Python 3, this is defined as an embedded PyVarObject type thus:
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*).
210 raise NullPyObjectPtr(self
)
212 if name
== 'ob_type':
213 pyo_ptr
= self
._gdbval
.cast(PyObjectPtr
.get_gdb_type())
214 return pyo_ptr
.dereference()[name
]
216 if name
== 'ob_size':
217 pyo_ptr
= self
._gdbval
.cast(PyVarObjectPtr
.get_gdb_type())
218 return pyo_ptr
.dereference()[name
]
220 # General case: look it up inside the object:
221 return self
._gdbval
.dereference()[name
]
223 def pyop_field(self
, name
):
225 Get a PyObjectPtr for the given PyObject* field within this PyObject,
226 coping with some python 2 versus python 3 differences.
228 return PyObjectPtr
.from_pyobject_ptr(self
.field(name
))
230 def write_field_repr(self
, name
, out
, visited
):
232 Extract the PyObject* field named "name", and write its representation
233 to file-like object "out"
235 field_obj
= self
.pyop_field(name
)
236 field_obj
.write_repr(out
, visited
)
238 def get_truncated_repr(self
, maxlen
):
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)
243 out
= TruncatedStringIO(maxlen
)
245 self
.write_repr(out
, set())
246 except StringTruncated
:
247 # Truncation occurred:
248 return out
.getvalue() + '...(truncated)'
250 # No truncation occurred:
251 return out
.getvalue()
254 return PyTypeObjectPtr(self
.field('ob_type'))
257 return 0 == long(self
._gdbval
)
259 def is_optimized_out(self
):
261 Is the value of the underlying PyObject* visible to the debugger?
263 This can vary with the precise version of the compiler used to build
264 Python, and the precise version of gdb.
266 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
267 PyEval_EvalFrameEx's "f"
269 return self
._gdbval
.is_optimized_out
271 def safe_tp_name(self
):
273 return self
.type().field('tp_name').string()
274 except NullPyObjectPtr
:
278 # Can't even read the object at all?
281 def proxyval(self
, visited
):
283 Scrape a value from the inferior process, and try to represent it
284 within the gdb process, whilst (hopefully) avoiding crashes when
285 the remote data is corrupt.
287 Derived classes will override this.
289 For example, a PyIntObject* with ob_ival 42 in the inferior process
290 should result in an int(42) in this process.
292 visited: a set of all gdb.Value pyobject pointers already visited
293 whilst generating this value (to guard against infinite recursion when
294 visiting object graphs with loops). Analogous to Py_ReprEnter and
298 class FakeRepr(object):
300 Class representing a non-descript PyObject* value in the inferior
301 process for when we don't have a custom scraper, intended to have
305 def __init__(self
, tp_name
, address
):
306 self
.tp_name
= tp_name
307 self
.address
= address
310 # For the NULL pointer, we have no way of knowing a type, so
311 # special-case it as per
312 # http://bugs.python.org/issue8032#msg100882
313 if self
.address
== 0:
315 return '<%s at remote 0x%x>' % (self
.tp_name
, self
.address
)
317 return FakeRepr(self
.safe_tp_name(),
320 def write_repr(self
, out
, visited
):
322 Write a string representation of the value scraped from the inferior
323 process to "out", a file-like object.
325 # Default implementation: generate a proxy value and write its repr
326 # However, this could involve a lot of work for complicated objects,
327 # so for derived classes we specialize this
328 return out
.write(repr(self
.proxyval(visited
)))
331 def subclass_from_type(cls
, t
):
333 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
334 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
337 Ideally, we would look up the symbols for the global types, but that
339 (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
340 Traceback (most recent call last):
341 File "<string>", line 1, in <module>
342 NotImplementedError: Symbol type not yet supported in Python scripts.
343 Error while executing Python code.
345 For now, we use tp_flags, after doing some string comparisons on the
346 tp_name for some special-cases that don't seem to be visible through
350 tp_name
= t
.field('tp_name').string()
351 tp_flags
= int(t
.field('tp_flags'))
353 # Handle any kind of error e.g. NULL ptrs by simply using the base
357 #print 'tp_flags = 0x%08x' % tp_flags
358 #print 'tp_name = %r' % tp_name
360 name_map
= {'bool': PyBoolObjectPtr
,
361 'classobj': PyClassObjectPtr
,
362 'instance': PyInstanceObjectPtr
,
363 'NoneType': PyNoneStructPtr
,
364 'frame': PyFrameObjectPtr
,
365 'set' : PySetObjectPtr
,
366 'frozenset' : PySetObjectPtr
,
367 'builtin_function_or_method' : PyCFunctionObjectPtr
,
369 if tp_name
in name_map
:
370 return name_map
[tp_name
]
372 if tp_flags
& (Py_TPFLAGS_HEAPTYPE|Py_TPFLAGS_TYPE_SUBCLASS
):
373 return PyTypeObjectPtr
375 if tp_flags
& Py_TPFLAGS_INT_SUBCLASS
:
376 return PyIntObjectPtr
377 if tp_flags
& Py_TPFLAGS_LONG_SUBCLASS
:
378 return PyLongObjectPtr
379 if tp_flags
& Py_TPFLAGS_LIST_SUBCLASS
:
380 return PyListObjectPtr
381 if tp_flags
& Py_TPFLAGS_TUPLE_SUBCLASS
:
382 return PyTupleObjectPtr
383 if tp_flags
& Py_TPFLAGS_STRING_SUBCLASS
:
385 gdb
.lookup_type('PyBytesObject')
386 return PyBytesObjectPtr
388 return PyStringObjectPtr
389 if tp_flags
& Py_TPFLAGS_UNICODE_SUBCLASS
:
390 return PyUnicodeObjectPtr
391 if tp_flags
& Py_TPFLAGS_DICT_SUBCLASS
:
392 return PyDictObjectPtr
393 if tp_flags
& Py_TPFLAGS_BASE_EXC_SUBCLASS
:
394 return PyBaseExceptionObjectPtr
396 # Use the base class:
400 def from_pyobject_ptr(cls
, gdbval
):
402 Try to locate the appropriate derived class dynamically, and cast
403 the pointer accordingly.
406 p
= PyObjectPtr(gdbval
)
407 cls
= cls
.subclass_from_type(p
.type())
408 return cls(gdbval
, cast_to
=cls
.get_gdb_type())
409 except RuntimeError, exc
:
410 # Handle any kind of error e.g. NULL ptrs by simply using the base
416 def get_gdb_type(cls
):
417 return gdb
.lookup_type(cls
._typename
).pointer()
419 def as_address(self
):
420 return long(self
._gdbval
)
423 class PyVarObjectPtr(PyObjectPtr
):
424 _typename
= 'PyVarObject'
426 class ProxyAlreadyVisited(object):
428 Placeholder proxy to use when protecting against infinite recursion due to
429 loops in the object graph.
431 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
433 def __init__(self
, rep
):
440 def _write_instance_repr(out
, visited
, name
, pyop_attrdict
, address
):
441 '''Shared code for use by old-style and new-style classes:
442 write a representation to file-like object "out"'''
446 # Write dictionary of instance attributes:
447 if isinstance(pyop_attrdict
, PyDictObjectPtr
):
450 for pyop_arg
, pyop_val
in pyop_attrdict
.iteritems():
454 out
.write(pyop_arg
.proxyval(visited
))
456 pyop_val
.write_repr(out
, visited
)
458 out
.write(' at remote 0x%x>' % address
)
461 class InstanceProxy(object):
463 def __init__(self
, cl_name
, attrdict
, address
):
464 self
.cl_name
= cl_name
465 self
.attrdict
= attrdict
466 self
.address
= address
469 if isinstance(self
.attrdict
, dict):
470 kwargs
= ', '.join(["%s=%r" % (arg
, val
)
471 for arg
, val
in self
.attrdict
.iteritems()])
472 return '<%s(%s) at remote 0x%x>' % (self
.cl_name
,
473 kwargs
, self
.address
)
475 return '<%s at remote 0x%x>' % (self
.cl_name
,
478 def _PyObject_VAR_SIZE(typeobj
, nitems
):
479 return ( ( typeobj
.field('tp_basicsize') +
480 nitems
* typeobj
.field('tp_itemsize') +
482 ) & ~
(SIZEOF_VOID_P
- 1)
483 ).cast(gdb
.lookup_type('size_t'))
485 class PyTypeObjectPtr(PyObjectPtr
):
486 _typename
= 'PyTypeObject'
488 def get_attr_dict(self
):
490 Get the PyDictObject ptr representing the attribute dictionary
491 (or None if there's a problem)
494 typeobj
= self
.type()
495 dictoffset
= int_from_int(typeobj
.field('tp_dictoffset'))
498 type_PyVarObject_ptr
= gdb
.lookup_type('PyVarObject').pointer()
499 tsize
= int_from_int(self
._gdbval
.cast(type_PyVarObject_ptr
)['ob_size'])
502 size
= _PyObject_VAR_SIZE(typeobj
, tsize
)
504 assert dictoffset
> 0
505 assert dictoffset
% SIZEOF_VOID_P
== 0
507 dictptr
= self
._gdbval
.cast(_type_char_ptr
) + dictoffset
508 PyObjectPtrPtr
= PyObjectPtr
.get_gdb_type().pointer()
509 dictptr
= dictptr
.cast(PyObjectPtrPtr
)
510 return PyObjectPtr
.from_pyobject_ptr(dictptr
.dereference())
512 # Corrupt data somewhere; fail safe
515 # Not found, or some kind of error:
518 def proxyval(self
, visited
):
520 Support for new-style classes.
522 Currently we just locate the dictionary using a transliteration to
523 python of _PyObject_GetDictPtr, ignoring descriptors
525 # Guard against infinite loops:
526 if self
.as_address() in visited
:
527 return ProxyAlreadyVisited('<...>')
528 visited
.add(self
.as_address())
530 pyop_attr_dict
= self
.get_attr_dict()
532 attr_dict
= pyop_attr_dict
.proxyval(visited
)
535 tp_name
= self
.safe_tp_name()
538 return InstanceProxy(tp_name
, attr_dict
, long(self
._gdbval
))
540 def write_repr(self
, out
, visited
):
541 # Guard against infinite loops:
542 if self
.as_address() in visited
:
545 visited
.add(self
.as_address())
548 tp_name
= self
.field('tp_name').string()
552 out
.write('<type %s at remote 0x%x>' % (tp_name
,
554 # pyop_attrdict = self.get_attr_dict()
555 # _write_instance_repr(out, visited,
556 # self.safe_tp_name(), pyop_attrdict, self.as_address())
558 class ProxyException(Exception):
559 def __init__(self
, tp_name
, args
):
560 self
.tp_name
= tp_name
564 return '%s%r' % (self
.tp_name
, self
.args
)
566 class PyBaseExceptionObjectPtr(PyObjectPtr
):
568 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
569 within the process being debugged.
571 _typename
= 'PyBaseExceptionObject'
573 def proxyval(self
, visited
):
574 # Guard against infinite loops:
575 if self
.as_address() in visited
:
576 return ProxyAlreadyVisited('(...)')
577 visited
.add(self
.as_address())
578 arg_proxy
= self
.pyop_field('args').proxyval(visited
)
579 return ProxyException(self
.safe_tp_name(),
582 def write_repr(self
, out
, visited
):
583 # Guard against infinite loops:
584 if self
.as_address() in visited
:
587 visited
.add(self
.as_address())
589 out
.write(self
.safe_tp_name())
590 self
.write_field_repr('args', out
, visited
)
593 class PyClassObjectPtr(PyObjectPtr
):
595 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
596 instance within the process being debugged.
598 _typename
= 'PyClassObject'
601 class BuiltInFunctionProxy(object):
602 def __init__(self
, ml_name
):
603 self
.ml_name
= ml_name
606 return "<built-in function %s>" % self
.ml_name
608 class BuiltInMethodProxy(object):
609 def __init__(self
, ml_name
, pyop_m_self
):
610 self
.ml_name
= ml_name
611 self
.pyop_m_self
= pyop_m_self
614 return ('<built-in method %s of %s object at remote 0x%x>'
616 self
.pyop_m_self
.safe_tp_name(),
617 self
.pyop_m_self
.as_address())
620 class PyCFunctionObjectPtr(PyObjectPtr
):
622 Class wrapping a gdb.Value that's a PyCFunctionObject*
623 (see Include/methodobject.h and Objects/methodobject.c)
625 _typename
= 'PyCFunctionObject'
627 def proxyval(self
, visited
):
628 m_ml
= self
.field('m_ml') # m_ml is a (PyMethodDef*)
629 ml_name
= m_ml
['ml_name'].string()
631 pyop_m_self
= self
.pyop_field('m_self')
632 if pyop_m_self
.is_null():
633 return BuiltInFunctionProxy(ml_name
)
635 return BuiltInMethodProxy(ml_name
, pyop_m_self
)
638 class PyCodeObjectPtr(PyObjectPtr
):
640 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
641 within the process being debugged.
643 _typename
= 'PyCodeObject'
645 def addr2line(self
, addrq
):
647 Get the line number for a given bytecode offset
649 Analogous to PyCode_Addr2Line; translated from pseudocode in
650 Objects/lnotab_notes.txt
652 co_lnotab
= self
.pyop_field('co_lnotab').proxyval(set())
654 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
655 # not 0, as lnotab_notes.txt has it:
656 lineno
= int_from_int(self
.field('co_firstlineno'))
659 for addr_incr
, line_incr
in zip(co_lnotab
[::2], co_lnotab
[1::2]):
660 addr
+= ord(addr_incr
)
663 lineno
+= ord(line_incr
)
667 class PyDictObjectPtr(PyObjectPtr
):
669 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
670 within the process being debugged.
672 _typename
= 'PyDictObject'
676 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
677 analagous to dict.iteritems()
679 for i
in safe_range(self
.field('ma_mask') + 1):
680 ep
= self
.field('ma_table') + i
681 pyop_value
= PyObjectPtr
.from_pyobject_ptr(ep
['me_value'])
682 if not pyop_value
.is_null():
683 pyop_key
= PyObjectPtr
.from_pyobject_ptr(ep
['me_key'])
684 yield (pyop_key
, pyop_value
)
686 def proxyval(self
, visited
):
687 # Guard against infinite loops:
688 if self
.as_address() in visited
:
689 return ProxyAlreadyVisited('{...}')
690 visited
.add(self
.as_address())
693 for pyop_key
, pyop_value
in self
.iteritems():
694 proxy_key
= pyop_key
.proxyval(visited
)
695 proxy_value
= pyop_value
.proxyval(visited
)
696 result
[proxy_key
] = proxy_value
699 def write_repr(self
, out
, visited
):
700 # Guard against infinite loops:
701 if self
.as_address() in visited
:
704 visited
.add(self
.as_address())
708 for pyop_key
, pyop_value
in self
.iteritems():
712 pyop_key
.write_repr(out
, visited
)
714 pyop_value
.write_repr(out
, visited
)
717 class PyInstanceObjectPtr(PyObjectPtr
):
718 _typename
= 'PyInstanceObject'
720 def proxyval(self
, visited
):
721 # Guard against infinite loops:
722 if self
.as_address() in visited
:
723 return ProxyAlreadyVisited('<...>')
724 visited
.add(self
.as_address())
727 in_class
= self
.pyop_field('in_class')
728 cl_name
= in_class
.pyop_field('cl_name').proxyval(visited
)
730 # Get dictionary of instance attributes:
731 in_dict
= self
.pyop_field('in_dict').proxyval(visited
)
734 return InstanceProxy(cl_name
, in_dict
, long(self
._gdbval
))
736 def write_repr(self
, out
, visited
):
737 # Guard against infinite loops:
738 if self
.as_address() in visited
:
741 visited
.add(self
.as_address())
746 in_class
= self
.pyop_field('in_class')
747 cl_name
= in_class
.pyop_field('cl_name').proxyval(visited
)
749 # Get dictionary of instance attributes:
750 pyop_in_dict
= self
.pyop_field('in_dict')
752 _write_instance_repr(out
, visited
,
753 cl_name
, pyop_in_dict
, self
.as_address())
755 class PyIntObjectPtr(PyObjectPtr
):
756 _typename
= 'PyIntObject'
758 def proxyval(self
, visited
):
759 result
= int_from_int(self
.field('ob_ival'))
762 class PyListObjectPtr(PyObjectPtr
):
763 _typename
= 'PyListObject'
765 def __getitem__(self
, i
):
766 # Get the gdb.Value for the (PyObject*) with the given index:
767 field_ob_item
= self
.field('ob_item')
768 return field_ob_item
[i
]
770 def proxyval(self
, visited
):
771 # Guard against infinite loops:
772 if self
.as_address() in visited
:
773 return ProxyAlreadyVisited('[...]')
774 visited
.add(self
.as_address())
776 result
= [PyObjectPtr
.from_pyobject_ptr(self
[i
]).proxyval(visited
)
777 for i
in safe_range(int_from_int(self
.field('ob_size')))]
780 def write_repr(self
, out
, visited
):
781 # Guard against infinite loops:
782 if self
.as_address() in visited
:
785 visited
.add(self
.as_address())
788 for i
in safe_range(int_from_int(self
.field('ob_size'))):
791 element
= PyObjectPtr
.from_pyobject_ptr(self
[i
])
792 element
.write_repr(out
, visited
)
795 class PyLongObjectPtr(PyObjectPtr
):
796 _typename
= 'PyLongObject'
798 def proxyval(self
, visited
):
800 Python's Include/longobjrep.h has this declaration:
806 with this description:
807 The absolute value of a number is equal to
808 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
809 Negative numbers are represented with ob_size < 0;
810 zero is represented by ob_size == 0.
812 where SHIFT can be either:
813 #define PyLong_SHIFT 30
814 #define PyLong_SHIFT 15
816 ob_size
= long(self
.field('ob_size'))
820 ob_digit
= self
.field('ob_digit')
822 if gdb
.lookup_type('digit').sizeof
== 2:
827 digits
= [long(ob_digit
[i
]) * 2**(SHIFT
*i
)
828 for i
in safe_range(abs(ob_size
))]
834 def write_repr(self
, out
, visited
):
835 # Write this out as a Python 3 int literal, i.e. without the "L" suffix
836 proxy
= self
.proxyval(visited
)
837 out
.write("%s" % proxy
)
840 class PyBoolObjectPtr(PyLongObjectPtr
):
842 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
843 <bool> instances (Py_True/Py_False) within the process being debugged.
845 _typename
= 'PyBoolObject'
847 def proxyval(self
, visited
):
848 castto
= gdb
.lookup_type('PyLongObject').pointer()
849 self
._gdbval
= self
._gdbval
.cast(castto
)
850 return bool(PyLongObjectPtr(self
._gdbval
).proxyval(visited
))
853 class PyNoneStructPtr(PyObjectPtr
):
855 Class wrapping a gdb.Value that's a PyObject* pointing to the
856 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
858 _typename
= 'PyObject'
860 def proxyval(self
, visited
):
864 class PyFrameObjectPtr(PyObjectPtr
):
865 _typename
= 'PyFrameObject'
867 def __init__(self
, gdbval
, cast_to
=None):
868 PyObjectPtr
.__init
__(self
, gdbval
, cast_to
)
870 if not self
.is_optimized_out():
871 self
.co
= PyCodeObjectPtr
.from_pyobject_ptr(self
.field('f_code'))
872 self
.co_name
= self
.co
.pyop_field('co_name')
873 self
.co_filename
= self
.co
.pyop_field('co_filename')
875 self
.f_lineno
= int_from_int(self
.field('f_lineno'))
876 self
.f_lasti
= int_from_int(self
.field('f_lasti'))
877 self
.co_nlocals
= int_from_int(self
.co
.field('co_nlocals'))
878 self
.co_varnames
= PyTupleObjectPtr
.from_pyobject_ptr(self
.co
.field('co_varnames'))
880 def iter_locals(self
):
882 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
883 the local variables of this frame
885 if self
.is_optimized_out():
888 f_localsplus
= self
.field('f_localsplus')
889 for i
in safe_range(self
.co_nlocals
):
890 pyop_value
= PyObjectPtr
.from_pyobject_ptr(f_localsplus
[i
])
891 if not pyop_value
.is_null():
892 pyop_name
= PyObjectPtr
.from_pyobject_ptr(self
.co_varnames
[i
])
893 yield (pyop_name
, pyop_value
)
895 def iter_globals(self
):
897 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
898 the global variables of this frame
900 if self
.is_optimized_out():
903 pyop_globals
= self
.pyop_field('f_globals')
904 return pyop_globals
.iteritems()
906 def iter_builtins(self
):
908 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
909 the builtin variables
911 if self
.is_optimized_out():
914 pyop_builtins
= self
.pyop_field('f_builtins')
915 return pyop_builtins
.iteritems()
917 def get_var_by_name(self
, name
):
919 Look for the named local variable, returning a (PyObjectPtr, scope) pair
920 where scope is a string 'local', 'global', 'builtin'
922 If not found, return (None, None)
924 for pyop_name
, pyop_value
in self
.iter_locals():
925 if name
== pyop_name
.proxyval(set()):
926 return pyop_value
, 'local'
927 for pyop_name
, pyop_value
in self
.iter_globals():
928 if name
== pyop_name
.proxyval(set()):
929 return pyop_value
, 'global'
930 for pyop_name
, pyop_value
in self
.iter_builtins():
931 if name
== pyop_name
.proxyval(set()):
932 return pyop_value
, 'builtin'
936 '''Get the path of the current Python source file, as a string'''
937 if self
.is_optimized_out():
938 return '(frame information optimized out)'
939 return self
.co_filename
.proxyval(set())
941 def current_line_num(self
):
942 '''Get current line number as an integer (1-based)
944 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
946 See Objects/lnotab_notes.txt
948 if self
.is_optimized_out():
950 f_trace
= self
.field('f_trace')
951 if long(f_trace
) != 0:
952 # we have a non-NULL f_trace:
956 return self
.co
.addr2line(self
.f_lasti
)
958 # return self.f_lineno
960 def current_line(self
):
961 '''Get the text of the current source line as a string, with a trailing
963 if self
.is_optimized_out():
964 return '(frame information optimized out)'
965 filename
= self
.filename()
966 with
open(os_fsencode(filename
), 'r') as f
:
967 all_lines
= f
.readlines()
968 # Convert from 1-based current_line_num to 0-based list offset:
969 return all_lines
[self
.current_line_num()-1]
971 def write_repr(self
, out
, visited
):
972 if self
.is_optimized_out():
973 out
.write('(frame information optimized out)')
975 out
.write('Frame 0x%x, for file %s, line %i, in %s ('
976 % (self
.as_address(),
977 self
.co_filename
.proxyval(visited
),
978 self
.current_line_num(),
979 self
.co_name
.proxyval(visited
)))
981 for pyop_name
, pyop_value
in self
.iter_locals():
986 out
.write(pyop_name
.proxyval(visited
))
988 pyop_value
.write_repr(out
, visited
)
992 class PySetObjectPtr(PyObjectPtr
):
993 _typename
= 'PySetObject'
995 def proxyval(self
, visited
):
996 # Guard against infinite loops:
997 if self
.as_address() in visited
:
998 return ProxyAlreadyVisited('%s(...)' % self
.safe_tp_name())
999 visited
.add(self
.as_address())
1002 table
= self
.field('table')
1003 for i
in safe_range(self
.field('mask')+1):
1005 key
= setentry
['key']
1007 key_proxy
= PyObjectPtr
.from_pyobject_ptr(key
).proxyval(visited
)
1008 if key_proxy
!= '<dummy key>':
1009 members
.append(key_proxy
)
1010 if self
.safe_tp_name() == 'frozenset':
1011 return frozenset(members
)
1015 def write_repr(self
, out
, visited
):
1016 # Emulate Python 3's set_repr
1017 tp_name
= self
.safe_tp_name()
1019 # Guard against infinite loops:
1020 if self
.as_address() in visited
:
1023 visited
.add(self
.as_address())
1025 # Python 3's set_repr special-cases the empty set:
1026 if not self
.field('used'):
1031 # Python 3 uses {} for set literals:
1032 if tp_name
!= 'set':
1038 table
= self
.field('table')
1039 for i
in safe_range(self
.field('mask')+1):
1041 key
= setentry
['key']
1043 pyop_key
= PyObjectPtr
.from_pyobject_ptr(key
)
1044 key_proxy
= pyop_key
.proxyval(visited
) # FIXME!
1045 if key_proxy
!= '<dummy key>':
1049 pyop_key
.write_repr(out
, visited
)
1052 if tp_name
!= 'set':
1056 class PyBytesObjectPtr(PyObjectPtr
):
1057 _typename
= 'PyBytesObject'
1060 field_ob_size
= self
.field('ob_size')
1061 field_ob_sval
= self
.field('ob_sval')
1062 return ''.join(struct
.pack('b', field_ob_sval
[i
])
1063 for i
in safe_range(field_ob_size
))
1065 def proxyval(self
, visited
):
1068 def write_repr(self
, out
, visited
, py3
=True):
1069 # Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1071 # Get a PyStringObject* within the Python 2 gdb process:
1072 proxy
= self
.proxyval(visited
)
1074 # Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1077 if "'" in proxy
and not '"' in proxy
:
1085 if byte
== quote
or byte
== '\\':
1094 elif byte
< ' ' or ord(byte
) >= 0x7f:
1096 out
.write(hexdigits
[(ord(byte
) & 0xf0) >> 4])
1097 out
.write(hexdigits
[ord(byte
) & 0xf])
1102 class PyStringObjectPtr(PyBytesObjectPtr
):
1103 _typename
= 'PyStringObject'
1105 def write_repr(self
, out
, visited
):
1106 return super(PyStringObjectPtr
, self
).write_repr(out
, visited
, py3
=False)
1108 class PyTupleObjectPtr(PyObjectPtr
):
1109 _typename
= 'PyTupleObject'
1111 def __getitem__(self
, i
):
1112 # Get the gdb.Value for the (PyObject*) with the given index:
1113 field_ob_item
= self
.field('ob_item')
1114 return field_ob_item
[i
]
1116 def proxyval(self
, visited
):
1117 # Guard against infinite loops:
1118 if self
.as_address() in visited
:
1119 return ProxyAlreadyVisited('(...)')
1120 visited
.add(self
.as_address())
1122 result
= tuple([PyObjectPtr
.from_pyobject_ptr(self
[i
]).proxyval(visited
)
1123 for i
in safe_range(int_from_int(self
.field('ob_size')))])
1126 def write_repr(self
, out
, visited
):
1127 # Guard against infinite loops:
1128 if self
.as_address() in visited
:
1131 visited
.add(self
.as_address())
1134 for i
in safe_range(int_from_int(self
.field('ob_size'))):
1137 element
= PyObjectPtr
.from_pyobject_ptr(self
[i
])
1138 element
.write_repr(out
, visited
)
1139 if self
.field('ob_size') == 1:
1145 def _unichr_is_printable(char
):
1146 # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1150 return unicodedata
.category(char
) not in ("C", "Z")
1152 if sys
.maxunicode
>= 0x10000:
1155 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1160 ch1
= 0xD800 |
(x
>> 10)
1161 ch2
= 0xDC00 |
(x
& 0x3FF)
1162 return unichr(ch1
) + unichr(ch2
)
1164 class PyUnicodeObjectPtr(PyObjectPtr
):
1165 _typename
= 'PyUnicodeObject'
1167 def char_width(self
):
1168 _type_Py_UNICODE
= gdb
.lookup_type('Py_UNICODE')
1169 return _type_Py_UNICODE
.sizeof
1171 def proxyval(self
, visited
):
1172 # From unicodeobject.h:
1173 # Py_ssize_t length; /* Length of raw Unicode data in buffer */
1174 # Py_UNICODE *str; /* Raw Unicode buffer */
1175 field_length
= long(self
.field('length'))
1176 field_str
= self
.field('str')
1178 # Gather a list of ints from the Py_UNICODE array; these are either
1179 # UCS-2 or UCS-4 code points:
1180 if self
.char_width() > 2:
1181 Py_UNICODEs
= [int(field_str
[i
]) for i
in safe_range(field_length
)]
1183 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1184 # inferior process: we must join surrogate pairs.
1187 limit
= safety_limit(field_length
)
1189 ucs
= int(field_str
[i
])
1191 if ucs
< 0xD800 or ucs
>= 0xDC00 or i
== field_length
:
1192 Py_UNICODEs
.append(ucs
)
1194 # This could be a surrogate pair.
1195 ucs2
= int(field_str
[i
])
1196 if ucs2
< 0xDC00 or ucs2
> 0xDFFF:
1198 code
= (ucs
& 0x03FF) << 10
1199 code |
= ucs2
& 0x03FF
1201 Py_UNICODEs
.append(code
)
1204 # Convert the int code points to unicode characters, and generate a
1205 # local unicode instance.
1206 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
1207 result
= u
''.join([_unichr(ucs
) for ucs
in Py_UNICODEs
])
1210 def write_repr(self
, out
, visited
):
1211 # Get a PyUnicodeObject* within the Python 2 gdb process:
1212 proxy
= self
.proxyval(visited
)
1214 # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1217 gdb
.parse_and_eval('PyString_Type')
1218 except RuntimeError:
1219 # Python 3, don't write 'u' as prefix
1222 # Python 2, write the 'u'
1225 if "'" in proxy
and '"' not in proxy
:
1232 while i
< len(proxy
):
1236 # Escape quotes and backslashes
1237 if ch
== quote
or ch
== '\\':
1241 # Map special whitespace to '\t', \n', '\r'
1249 # Map non-printable US ASCII to '\xhh' */
1250 elif ch
< ' ' or ch
== 0x7F:
1252 out
.write(hexdigits
[(ord(ch
) >> 4) & 0x000F])
1253 out
.write(hexdigits
[ord(ch
) & 0x000F])
1255 # Copy ASCII characters as-is
1256 elif ord(ch
) < 0x7F:
1259 # Non-ASCII characters
1263 if sys
.maxunicode
< 0x10000:
1264 # If sizeof(Py_UNICODE) is 2 here (in gdb), join
1265 # surrogate pairs before calling _unichr_is_printable.
1267 and 0xD800 <= ord(ch
) < 0xDC00 \
1268 and 0xDC00 <= ord(proxy
[i
]) <= 0xDFFF):
1273 # Unfortuately, Python 2's unicode type doesn't seem
1274 # to expose the "isprintable" method
1275 printable
= _unichr_is_printable(ucs
)
1278 ucs
.encode(ENCODING
)
1279 except UnicodeEncodeError:
1282 # Map Unicode whitespace and control characters
1283 # (categories Z* and C* except ASCII space)
1286 # Match Python 3's representation of non-printable
1288 code
= (ord(ch
) & 0x03FF) << 10
1289 code |
= ord(ch2
) & 0x03FF
1294 # Map 8-bit characters to '\\xhh'
1297 out
.write(hexdigits
[(code
>> 4) & 0x000F])
1298 out
.write(hexdigits
[code
& 0x000F])
1299 # Map 21-bit characters to '\U00xxxxxx'
1300 elif code
>= 0x10000:
1302 out
.write(hexdigits
[(code
>> 28) & 0x0000000F])
1303 out
.write(hexdigits
[(code
>> 24) & 0x0000000F])
1304 out
.write(hexdigits
[(code
>> 20) & 0x0000000F])
1305 out
.write(hexdigits
[(code
>> 16) & 0x0000000F])
1306 out
.write(hexdigits
[(code
>> 12) & 0x0000000F])
1307 out
.write(hexdigits
[(code
>> 8) & 0x0000000F])
1308 out
.write(hexdigits
[(code
>> 4) & 0x0000000F])
1309 out
.write(hexdigits
[code
& 0x0000000F])
1310 # Map 16-bit characters to '\uxxxx'
1313 out
.write(hexdigits
[(code
>> 12) & 0x000F])
1314 out
.write(hexdigits
[(code
>> 8) & 0x000F])
1315 out
.write(hexdigits
[(code
>> 4) & 0x000F])
1316 out
.write(hexdigits
[code
& 0x000F])
1318 # Copy characters as-is
1325 def __unicode__(self
):
1326 return self
.proxyval(set())
1329 # In Python 3, everything is unicode (including attributes of e.g.
1330 # code objects, such as function names). The Python 2 debugger code
1331 # uses PyUnicodePtr objects to format strings etc, whereas with a
1332 # Python 2 debuggee we'd get PyStringObjectPtr instances with __str__.
1333 # Be compatible with that.
1334 return unicode(self
).encode('UTF-8')
1336 def int_from_int(gdbval
):
1337 return int(str(gdbval
))
1341 # TODO: repr() puts everything on one line; pformat can be nicer, but
1342 # can lead to v.long results; this function isolates the choice
1346 from pprint
import pformat
1350 class PyObjectPtrPrinter
:
1351 "Prints a (PyObject*)"
1353 def __init__ (self
, gdbval
):
1354 self
.gdbval
= gdbval
1356 def to_string (self
):
1357 pyop
= PyObjectPtr
.from_pyobject_ptr(self
.gdbval
)
1359 return pyop
.get_truncated_repr(MAX_OUTPUT_LEN
)
1361 # Generate full proxy value then stringify it.
1362 # Doing so could be expensive
1363 proxyval
= pyop
.proxyval(set())
1364 return stringify(proxyval
)
1366 def pretty_printer_lookup(gdbval
):
1367 type = gdbval
.type.unqualified()
1368 if type.code
== gdb
.TYPE_CODE_PTR
:
1369 type = type.target().unqualified()
1370 if str(type) in all_pretty_typenames
:
1371 return PyObjectPtrPrinter(gdbval
)
1374 During development, I've been manually invoking the code in this way:
1378 sys.path.append('/home/david/coding/python-gdb')
1382 then reloading it after each edit like this:
1383 (gdb) python reload(libpython)
1385 The following code should ensure that the prettyprinter is registered
1386 if the code is autoloaded by gdb when visiting libpython.so, provided
1387 that this python file is installed to the same path as the library (or its
1388 .debug file) plus a "-gdb.py" suffix, e.g:
1389 /usr/lib/libpython2.6.so.1.0-gdb.py
1390 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1396 # Wire up the pretty-printer
1397 obj
.pretty_printers
.append(pretty_printer_lookup
)
1399 register (gdb
.current_objfile ())
1401 # Unfortunately, the exact API exposed by the gdb module varies somewhat
1402 # from build to build
1403 # See http://bugs.python.org/issue8279?#msg102276
1405 class Frame(object):
1407 Wrapper for gdb.Frame, adding various methods
1409 def __init__(self
, gdbframe
):
1410 self
._gdbframe
= gdbframe
1413 older
= self
._gdbframe
.older()
1420 newer
= self
._gdbframe
.newer()
1427 '''If supported, select this frame and return True; return False if unsupported
1429 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1430 onwards, but absent on Ubuntu buildbot'''
1431 if not hasattr(self
._gdbframe
, 'select'):
1432 print ('Unable to select frame: '
1433 'this build of gdb does not expose a gdb.Frame.select method')
1435 self
._gdbframe
.select()
1438 def get_index(self
):
1439 '''Calculate index of frame, starting at 0 for the newest frame within
1442 # Go down until you reach the newest frame:
1444 while iter_frame
.newer():
1446 iter_frame
= iter_frame
.newer()
1449 def is_evalframeex(self
):
1450 '''Is this a PyEval_EvalFrameEx frame?'''
1451 if self
._gdbframe
.name() == 'PyEval_EvalFrameEx':
1453 I believe we also need to filter on the inline
1454 struct frame_id.inline_depth, only regarding frames with
1455 an inline depth of 0 as actually being this function
1457 So we reject those with type gdb.INLINE_FRAME
1459 if self
._gdbframe
.type() == gdb
.NORMAL_FRAME
:
1460 # We have a PyEval_EvalFrameEx frame:
1465 def read_var(self
, varname
):
1467 read_var with respect to code blocks (gdbframe.read_var works with
1468 respect to the most recent block)
1470 Apparently this function doesn't work, though, as it seems to read
1471 variables in other frames also sometimes.
1473 block
= self
._gdbframe
.block()
1476 while block
and var
is None:
1478 var
= self
._gdbframe
.read_var(varname
, block
)
1482 block
= block
.superblock
1488 # self.read_var does not always work properly, so select our frame
1489 # and restore the previously selected frame
1490 selected_frame
= gdb
.selected_frame()
1491 self
._gdbframe
.select()
1492 f
= gdb
.parse_and_eval('f')
1493 selected_frame
.select()
1494 except RuntimeError:
1497 return PyFrameObjectPtr
.from_pyobject_ptr(f
)
1500 def get_selected_frame(cls
):
1501 _gdbframe
= gdb
.selected_frame()
1503 return Frame(_gdbframe
)
1507 def get_selected_python_frame(cls
):
1508 '''Try to obtain the Frame for the python code in the selected frame,
1510 frame
= cls
.get_selected_frame()
1513 if frame
.is_evalframeex():
1515 frame
= frame
.older()
1520 def print_summary(self
):
1521 if self
.is_evalframeex():
1522 pyop
= self
.get_pyop()
1524 line
= pyop
.get_truncated_repr(MAX_OUTPUT_LEN
)
1525 write_unicode(sys
.stdout
, '#%i %s\n' % (self
.get_index(), line
))
1526 sys
.stdout
.write(pyop
.current_line())
1528 sys
.stdout
.write('#%i (unable to read python frame information)\n' % self
.get_index())
1530 sys
.stdout
.write('#%i\n' % self
.get_index())
1532 class PyList(gdb
.Command
):
1533 '''List the current Python source code, if any
1537 to list at a different line number within the python source.
1541 to list a specific range of lines within the python source.
1545 gdb
.Command
.__init
__ (self
,
1551 def invoke(self
, args
, from_tty
):
1557 m
= re
.match(r
'\s*(\d+)\s*', args
)
1559 start
= int(m
.group(0))
1562 m
= re
.match(r
'\s*(\d+)\s*,\s*(\d+)\s*', args
)
1564 start
, end
= map(int, m
.groups())
1566 frame
= Frame
.get_selected_python_frame()
1568 print 'Unable to locate python frame'
1571 pyop
= frame
.get_pyop()
1573 print 'Unable to read information on python frame'
1576 filename
= pyop
.filename()
1577 lineno
= pyop
.current_line_num()
1586 with
open(os_fsencode(filename
), 'r') as f
:
1587 all_lines
= f
.readlines()
1588 # start and end are 1-based, all_lines is 0-based;
1589 # so [start-1:end] as a python slice gives us [start, end] as a
1591 for i
, line
in enumerate(all_lines
[start
-1:end
]):
1592 linestr
= str(i
+start
)
1593 # Highlight current line:
1594 if i
+ start
== lineno
:
1595 linestr
= '>' + linestr
1596 sys
.stdout
.write('%4s %s' % (linestr
, line
))
1599 # ...and register the command:
1602 def move_in_stack(move_up
):
1603 '''Move up or down the stack (for the py-up/py-down command)'''
1604 frame
= Frame
.get_selected_python_frame()
1607 iter_frame
= frame
.older()
1609 iter_frame
= frame
.newer()
1614 if iter_frame
.is_evalframeex():
1616 if iter_frame
.select():
1617 iter_frame
.print_summary()
1623 print 'Unable to find an older python frame'
1625 print 'Unable to find a newer python frame'
1627 class PyUp(gdb
.Command
):
1628 'Select and print the python stack frame that called this one (if any)'
1630 gdb
.Command
.__init
__ (self
,
1636 def invoke(self
, args
, from_tty
):
1637 move_in_stack(move_up
=True)
1639 class PyDown(gdb
.Command
):
1640 'Select and print the python stack frame called by this one (if any)'
1642 gdb
.Command
.__init
__ (self
,
1648 def invoke(self
, args
, from_tty
):
1649 move_in_stack(move_up
=False)
1651 # Not all builds of gdb have gdb.Frame.select
1652 if hasattr(gdb
.Frame
, 'select'):
1656 class PyBacktrace(gdb
.Command
):
1657 'Display the current python frame and all the frames within its call stack (if any)'
1659 gdb
.Command
.__init
__ (self
,
1665 def invoke(self
, args
, from_tty
):
1666 frame
= Frame
.get_selected_python_frame()
1668 if frame
.is_evalframeex():
1669 frame
.print_summary()
1670 frame
= frame
.older()
1674 class PyPrint(gdb
.Command
):
1675 'Look up the given python variable name, and print it'
1677 gdb
.Command
.__init
__ (self
,
1683 def invoke(self
, args
, from_tty
):
1686 frame
= Frame
.get_selected_python_frame()
1688 print 'Unable to locate python frame'
1691 pyop_frame
= frame
.get_pyop()
1693 print 'Unable to read information on python frame'
1696 pyop_var
, scope
= pyop_frame
.get_var_by_name(name
)
1702 pyop_var
.get_truncated_repr(MAX_OUTPUT_LEN
)))
1704 print '%r not found' % name
1708 class PyLocals(gdb
.Command
):
1709 'Look up the given python variable name, and print it'
1711 def invoke(self
, args
, from_tty
):
1714 frame
= Frame
.get_selected_python_frame()
1716 print 'Unable to locate python frame'
1719 pyop_frame
= frame
.get_pyop()
1721 print 'Unable to read information on python frame'
1724 namespace
= self
.get_namespace(pyop_frame
)
1725 namespace
= [(name
.proxyval(set()), val
) for name
, val
in namespace
]
1728 name
, val
= max(namespace
, key
=lambda (name
, val
): len(name
))
1729 max_name_length
= len(name
)
1731 for name
, pyop_value
in namespace
:
1732 value
= pyop_value
.get_truncated_repr(MAX_OUTPUT_LEN
)
1733 print ('%-*s = %s' % (max_name_length
, name
, value
))
1735 def get_namespace(self
, pyop_frame
):
1736 return pyop_frame
.iter_locals()
1739 class PyGlobals(PyLocals
):
1740 'List all the globals in the currently select Python frame'
1742 def get_namespace(self
, pyop_frame
):
1743 return pyop_frame
.iter_globals()
1746 PyLocals("py-locals", gdb
.COMMAND_DATA
, gdb
.COMPLETE_NONE
)
1747 PyGlobals("py-globals", gdb
.COMMAND_DATA
, gdb
.COMPLETE_NONE
)
1750 class PyNameEquals(gdb
.Function
):
1752 def _get_pycurframe_attr(self
, attr
):
1753 frame
= Frame(gdb
.selected_frame())
1754 if frame
.is_evalframeex():
1755 pyframe
= frame
.get_pyop()
1757 warnings
.warn("Use a Python debug build, Python breakpoints "
1758 "won't work otherwise.")
1761 return getattr(pyframe
, attr
).proxyval(set())
1765 def invoke(self
, funcname
):
1766 attr
= self
._get
_pycurframe
_attr
('co_name')
1767 return attr
is not None and attr
== funcname
.string()
1769 PyNameEquals("pyname_equals")
1772 class PyModEquals(PyNameEquals
):
1774 def invoke(self
, modname
):
1775 attr
= self
._get
_pycurframe
_attr
('co_filename')
1776 if attr
is not None:
1777 filename
, ext
= os
.path
.splitext(os
.path
.basename(attr
))
1778 return filename
== modname
.string()
1781 PyModEquals("pymod_equals")
1784 class PyBreak(gdb
.Command
):
1786 Set a Python breakpoint. Examples:
1788 Break on any function or method named 'func' in module 'modname'
1790 py-break modname.func
1792 Break on any function or method named 'func'
1797 def invoke(self
, funcname
, from_tty
):
1799 modname
, dot
, funcname
= funcname
.rpartition('.')
1800 cond
= '$pyname_equals("%s") && $pymod_equals("%s")' % (funcname
,
1803 cond
= '$pyname_equals("%s")' % funcname
1805 gdb
.execute('break PyEval_EvalFrameEx if ' + cond
)
1807 PyBreak("py-break", gdb
.COMMAND_RUNNING
, gdb
.COMPLETE_NONE
)
1810 class _LoggingState(object):
1812 State that helps to provide a reentrant gdb.execute() function.
1816 self
.fd
, self
.filename
= tempfile
.mkstemp()
1817 self
.file = os
.fdopen(self
.fd
, 'r+')
1818 _execute("set logging file %s" % self
.filename
)
1819 self
.file_position_stack
= []
1821 atexit
.register(os
.close
, self
.fd
)
1822 atexit
.register(os
.remove
, self
.filename
)
1824 def __enter__(self
):
1825 if not self
.file_position_stack
:
1826 _execute("set logging redirect on")
1827 _execute("set logging on")
1828 _execute("set pagination off")
1830 self
.file_position_stack
.append(os
.fstat(self
.fd
).st_size
)
1833 def getoutput(self
):
1835 self
.file.seek(self
.file_position_stack
[-1])
1836 result
= self
.file.read()
1839 def __exit__(self
, exc_type
, exc_val
, tb
):
1840 startpos
= self
.file_position_stack
.pop()
1841 self
.file.seek(startpos
)
1842 self
.file.truncate()
1843 if not self
.file_position_stack
:
1844 _execute("set logging off")
1845 _execute("set logging redirect off")
1846 _execute("set pagination on")
1849 def execute(command
, from_tty
=False, to_string
=False):
1851 Replace gdb.execute() with this function and have it accept a 'to_string'
1852 argument (new in 7.2). Have it properly capture stderr also. Ensure
1856 with _logging_state
as state
:
1857 _execute(command
, from_tty
)
1858 return state
.getoutput()
1860 _execute(command
, from_tty
)
1863 _execute
= gdb
.execute
1864 gdb
.execute
= execute
1865 _logging_state
= _LoggingState()
1868 def get_selected_inferior():
1870 Return the selected inferior in gdb.
1872 # Woooh, another bug in gdb! Is there an end in sight?
1873 # http://sourceware.org/bugzilla/show_bug.cgi?id=12212
1874 return gdb
.inferiors()[0]
1876 selected_thread
= gdb
.selected_thread()
1878 for inferior
in gdb
.inferiors():
1879 for thread
in inferior
.threads():
1880 if thread
== selected_thread
:
1883 def source_gdb_script(script_contents
, to_string
=False):
1885 Source a gdb script with script_contents passed as a string. This is useful
1886 to provide defines for py-step and py-next to make them repeatable (this is
1887 not possible with gdb.execute()). See
1888 http://sourceware.org/bugzilla/show_bug.cgi?id=12216
1890 fd
, filename
= tempfile
.mkstemp()
1891 f
= os
.fdopen(fd
, 'w')
1892 f
.write(script_contents
)
1894 gdb
.execute("source %s" % filename
, to_string
=to_string
)
1897 def register_defines():
1898 source_gdb_script(textwrap
.dedent("""\
1914 """) % (PyStep
.__doc
__, PyNext
.__doc
__))
1917 def stackdepth(frame
):
1918 "Tells the stackdepth of a gdb frame."
1921 frame
= frame
.older()
1926 class ExecutionControlCommandBase(gdb
.Command
):
1928 Superclass for language specific execution control. Language specific
1929 features should be implemented by lang_info using the LanguageInfo
1930 interface. 'name' is the name of the command.
1933 def __init__(self
, name
, lang_info
):
1934 super(ExecutionControlCommandBase
, self
).__init
__(
1935 name
, gdb
.COMMAND_RUNNING
, gdb
.COMPLETE_NONE
)
1936 self
.lang_info
= lang_info
1938 def install_breakpoints(self
):
1939 all_locations
= itertools
.chain(
1940 self
.lang_info
.static_break_functions(),
1941 self
.lang_info
.runtime_break_functions())
1943 for location
in all_locations
:
1944 result
= gdb
.execute('break %s' % location
, to_string
=True)
1945 yield re
.search(r
'Breakpoint (\d+)', result
).group(1)
1947 def delete_breakpoints(self
, breakpoint_list
):
1948 for bp
in breakpoint_list
:
1949 gdb
.execute("delete %s" % bp
)
1951 def filter_output(self
, result
):
1952 reflags
= re
.MULTILINE
1955 (r
'^Program received signal .*', reflags|re
.DOTALL
),
1956 (r
'.*[Ww]arning.*', 0),
1957 (r
'^Program exited .*', reflags
),
1961 # output when halting on a watchpoint
1962 (r
'^(Old|New) value = .*', reflags
),
1963 # output from the 'display' command
1964 (r
'^\d+: \w+ = .*', reflags
),
1967 def filter_output(regexes
):
1969 for regex
, flags
in regexes
:
1970 for match
in re
.finditer(regex
, result
, flags
):
1971 output
.append(match
.group(0))
1973 return '\n'.join(output
)
1975 # Filter the return value output of the 'finish' command
1976 match_finish
= re
.search(r
'^Value returned is \$\d+ = (.*)', result
,
1979 finish_output
= 'Value returned: %s\n' % match_finish
.group(1)
1983 return (filter_output(output_on_halt
),
1984 finish_output
+ filter_output(output_always
))
1988 return get_selected_inferior().pid
== 0
1990 def finish_executing(self
, result
):
1992 After doing some kind of code running in the inferior, print the line
1993 of source code or the result of the last executed gdb command (passed
1994 in as the `result` argument).
1996 output_on_halt
, output_always
= self
.filter_output(result
)
2000 print output_on_halt
2002 frame
= gdb
.selected_frame()
2003 source_line
= self
.lang_info
.get_source_line(frame
)
2004 if self
.lang_info
.is_relevant_function(frame
):
2005 raised_exception
= self
.lang_info
.exc_info(frame
)
2006 if raised_exception
:
2007 print raised_exception
2010 if output_always
.rstrip():
2011 print output_always
.rstrip()
2018 Execute until the function returns (or until something else makes it
2021 if gdb
.selected_frame().older() is not None:
2022 return gdb
.execute('finish', to_string
=True)
2024 # outermost frame, continue
2025 return gdb
.execute('cont', to_string
=True)
2027 def _finish_frame(self
):
2029 Execute until the function returns to a relevant caller.
2032 result
= self
._finish
()
2035 frame
= gdb
.selected_frame()
2036 except RuntimeError:
2039 hitbp
= re
.search(r
'Breakpoint (\d+)', result
)
2040 is_relevant
= self
.lang_info
.is_relevant_function(frame
)
2041 if hitbp
or is_relevant
or self
.stopped():
2046 def finish(self
, *args
):
2047 "Implements the finish command."
2048 result
= self
._finish
_frame
()
2049 self
.finish_executing(result
)
2051 def step(self
, stepinto
, stepover_command
='next'):
2053 Do a single step or step-over. Returns the result of the last gdb
2054 command that made execution stop.
2056 This implementation, for stepping, sets (conditional) breakpoints for
2057 all functions that are deemed relevant. It then does a step over until
2058 either something halts execution, or until the next line is reached.
2060 If, however, stepover_command is given, it should be a string gdb
2061 command that continues execution in some way. The idea is that the
2062 caller has set a (conditional) breakpoint or watchpoint that can work
2063 more efficiently than the step-over loop. For Python this means setting
2064 a watchpoint for f->f_lasti, which means we can then subsequently
2066 We want f->f_lasti instead of f->f_lineno, because the latter only
2067 works properly with local trace functions, see
2068 PyFrameObjectPtr.current_line_num and PyFrameObjectPtr.addr2line.
2071 breakpoint_list
= list(self
.install_breakpoints())
2073 beginframe
= gdb
.selected_frame()
2075 if self
.lang_info
.is_relevant_function(beginframe
):
2076 # If we start in a relevant frame, initialize stuff properly. If
2077 # we don't start in a relevant frame, the loop will halt
2078 # immediately. So don't call self.lang_info.lineno() as it may
2079 # raise for irrelevant frames.
2080 beginline
= self
.lang_info
.lineno(beginframe
)
2083 depth
= stackdepth(beginframe
)
2085 newframe
= beginframe
2088 if self
.lang_info
.is_relevant_function(newframe
):
2089 result
= gdb
.execute(stepover_command
, to_string
=True)
2091 result
= self
._finish
_frame
()
2096 newframe
= gdb
.selected_frame()
2097 is_relevant_function
= self
.lang_info
.is_relevant_function(newframe
)
2099 framename
= newframe
.name()
2100 except RuntimeError:
2103 m
= re
.search(r
'Breakpoint (\d+)', result
)
2105 if is_relevant_function
and m
.group(1) in breakpoint_list
:
2106 # although we hit a breakpoint, we still need to check
2107 # that the function, in case hit by a runtime breakpoint,
2108 # is in the right context
2111 if newframe
!= beginframe
:
2115 # see if we returned to the caller
2116 newdepth
= stackdepth(newframe
)
2117 is_relevant_function
= (newdepth
< depth
and
2118 is_relevant_function
)
2120 if is_relevant_function
:
2123 # newframe equals beginframe, check for a difference in the
2125 lineno
= self
.lang_info
.lineno(newframe
)
2126 if lineno
and lineno
!= beginline
:
2130 self
.delete_breakpoints(breakpoint_list
)
2132 self
.finish_executing(result
)
2134 def run(self
, args
, from_tty
):
2135 self
.finish_executing(gdb
.execute('run ' + args
, to_string
=True))
2137 def cont(self
, *args
):
2138 self
.finish_executing(gdb
.execute('cont', to_string
=True))
2141 class LanguageInfo(object):
2143 This class defines the interface that ExecutionControlCommandBase needs to
2144 provide language-specific execution control.
2146 Classes that implement this interface should implement:
2149 Tells the current line number (only called for a relevant frame).
2150 If lineno is a false value it is not checked for a difference.
2152 is_relevant_function(frame)
2153 tells whether we care about frame 'frame'
2155 get_source_line(frame)
2156 get the line of source code for the current line (only called for a
2157 relevant frame). If the source code cannot be retrieved this
2158 function should return None
2160 exc_info(frame) -- optional
2161 tells whether an exception was raised, if so, it should return a
2162 string representation of the exception value, None otherwise.
2164 static_break_functions()
2165 returns an iterable of function names that are considered relevant
2166 and should halt step-into execution. This is needed to provide a
2167 performing step-into
2169 runtime_break_functions() -- optional
2170 list of functions that we should break into depending on the
2174 def exc_info(self
, frame
):
2175 "See this class' docstring."
2177 def runtime_break_functions(self
):
2179 Implement this if the list of step-into functions depends on the
2184 class PythonInfo(LanguageInfo
):
2186 def pyframe(self
, frame
):
2187 pyframe
= Frame(frame
).get_pyop()
2191 raise gdb
.RuntimeError(
2192 "Unable to find the Python frame, run your code with a debug "
2193 "build (configure with --with-pydebug or compile with -g).")
2195 def lineno(self
, frame
):
2196 return self
.pyframe(frame
).current_line_num()
2198 def is_relevant_function(self
, frame
):
2199 return Frame(frame
).is_evalframeex()
2201 def get_source_line(self
, frame
):
2203 pyframe
= self
.pyframe(frame
)
2204 return '%4d %s' % (pyframe
.current_line_num(),
2205 pyframe
.current_line().rstrip())
2209 def exc_info(self
, frame
):
2211 tstate
= frame
.read_var('tstate').dereference()
2212 if gdb
.parse_and_eval('tstate->frame == f'):
2213 # tstate local variable initialized, check for an exception
2214 inf_type
= tstate
['curexc_type']
2215 inf_value
= tstate
['curexc_value']
2218 return 'An exception was raised: %s' % (inf_value
,)
2219 except (ValueError, RuntimeError), e
:
2220 # Could not read the variable tstate or it's memory, it's ok
2223 def static_break_functions(self
):
2224 yield 'PyEval_EvalFrameEx'
2227 class PythonStepperMixin(object):
2229 Make this a mixin so CyStep can also inherit from this and use a
2230 CythonCodeStepper at the same time.
2233 def python_step(self
, stepinto
):
2235 Set a watchpoint on the Python bytecode instruction pointer and try
2238 output
= gdb
.execute('watch f->f_lasti', to_string
=True)
2239 watchpoint
= int(re
.search(r
'[Ww]atchpoint (\d+):', output
).group(1))
2240 self
.step(stepinto
=stepinto
, stepover_command
='finish')
2241 gdb
.execute('delete %s' % watchpoint
)
2244 class PyStep(ExecutionControlCommandBase
, PythonStepperMixin
):
2245 "Step through Python code."
2249 def invoke(self
, args
, from_tty
):
2250 self
.python_step(stepinto
=self
.stepinto
)
2252 class PyNext(PyStep
):
2253 "Step-over Python code."
2257 class PyFinish(ExecutionControlCommandBase
):
2258 "Execute until function returns to a caller."
2260 invoke
= ExecutionControlCommandBase
.finish
2262 class PyRun(ExecutionControlCommandBase
):
2265 invoke
= ExecutionControlCommandBase
.run
2267 class PyCont(ExecutionControlCommandBase
):
2269 invoke
= ExecutionControlCommandBase
.cont
2272 def _pointervalue(gdbval
):
2274 Return the value of the pionter as a Python int.
2276 gdbval.type must be a pointer type
2278 # don't convert with int() as it will raise a RuntimeError
2279 if gdbval
.address
is not None:
2280 return long(gdbval
.address
)
2282 # the address attribute is None sometimes, in which case we can
2283 # still convert the pointer to an int
2286 def pointervalue(gdbval
):
2287 pointer
= _pointervalue(gdbval
)
2290 raise gdb
.GdbError("Negative pointer value, presumably a bug "
2291 "in gdb, aborting.")
2292 except RuntimeError:
2293 # work around yet another bug in gdb where you get random behaviour
2299 def get_inferior_unicode_postfix():
2301 gdb
.parse_and_eval('PyUnicode_FromEncodedObject')
2302 except RuntimeError:
2304 gdb
.parse_and_eval('PyUnicodeUCS2_FromEncodedObject')
2305 except RuntimeError:
2312 class PythonCodeExecutor(object):
2314 Py_single_input
= 256
2318 def malloc(self
, size
):
2319 chunk
= (gdb
.parse_and_eval("(void *) malloc((size_t) %d)" % size
))
2321 pointer
= pointervalue(chunk
)
2323 raise gdb
.GdbError("No memory could be allocated in the inferior.")
2327 def alloc_string(self
, string
):
2328 pointer
= self
.malloc(len(string
))
2329 get_selected_inferior().write_memory(pointer
, string
)
2333 def alloc_pystring(self
, string
):
2334 stringp
= self
.alloc_string(string
)
2335 PyString_FromStringAndSize
= 'PyString_FromStringAndSize'
2338 gdb
.parse_and_eval(PyString_FromStringAndSize
)
2339 except RuntimeError:
2341 PyString_FromStringAndSize
= ('PyUnicode%s_FromStringAndSize' %
2342 (get_inferior_unicode_postfix(),))
2345 result
= gdb
.parse_and_eval(
2346 '(PyObject *) %s((char *) %d, (size_t) %d)' % (
2347 PyString_FromStringAndSize
, stringp
, len(string
)))
2351 pointer
= pointervalue(result
)
2353 raise gdb
.GdbError("Unable to allocate Python string in "
2358 def free(self
, pointer
):
2359 gdb
.parse_and_eval("free((void *) %d)" % pointer
)
2361 def incref(self
, pointer
):
2362 "Increment the reference count of a Python object in the inferior."
2363 gdb
.parse_and_eval('Py_IncRef((PyObject *) %d)' % pointer
)
2365 def xdecref(self
, pointer
):
2366 "Decrement the reference count of a Python object in the inferior."
2367 # Py_DecRef is like Py_XDECREF, but a function. So we don't have
2368 # to check for NULL. This should also decref all our allocated
2370 gdb
.parse_and_eval('Py_DecRef((PyObject *) %d)' % pointer
)
2372 def evalcode(self
, code
, input_type
, global_dict
=None, local_dict
=None):
2374 Evaluate python code `code` given as a string in the inferior and
2375 return the result as a gdb.Value. Returns a new reference in the
2378 Of course, executing any code in the inferior may be dangerous and may
2379 leave the debuggee in an unsafe state or terminate it alltogether.
2382 raise gdb
.GdbError("String contains NUL byte.")
2386 pointer
= self
.alloc_string(code
)
2388 globalsp
= pointervalue(global_dict
)
2389 localsp
= pointervalue(local_dict
)
2391 if globalsp
== 0 or localsp
== 0:
2392 raise gdb
.GdbError("Unable to obtain or create locals or globals.")
2398 (PyObject *) %(globals)s,
2399 (PyObject *) %(locals)d)
2400 """ % dict(code
=pointer
, start
=input_type
,
2401 globals=globalsp
, locals=localsp
)
2403 with
FetchAndRestoreError():
2405 pyobject_return_value
= gdb
.parse_and_eval(code
)
2409 return pyobject_return_value
2411 class FetchAndRestoreError(PythonCodeExecutor
):
2413 Context manager that fetches the error indicator in the inferior and
2414 restores it on exit.
2418 self
.sizeof_PyObjectPtr
= gdb
.lookup_type('PyObject').pointer().sizeof
2419 self
.pointer
= self
.malloc(self
.sizeof_PyObjectPtr
* 3)
2422 value
= self
.pointer
+ self
.sizeof_PyObjectPtr
2423 traceback
= self
.pointer
+ self
.sizeof_PyObjectPtr
* 2
2425 self
.errstate
= type, value
, traceback
2427 def __enter__(self
):
2428 gdb
.parse_and_eval("PyErr_Fetch(%d, %d, %d)" % self
.errstate
)
2430 def __exit__(self
, *args
):
2431 if gdb
.parse_and_eval("(int) PyErr_Occurred()"):
2432 gdb
.parse_and_eval("PyErr_Print()")
2434 pyerr_restore
= ("PyErr_Restore("
2437 "(PyObject *) *%d)")
2440 gdb
.parse_and_eval(pyerr_restore
% self
.errstate
)
2442 self
.free(self
.pointer
)
2445 class FixGdbCommand(gdb
.Command
):
2447 def __init__(self
, command
, actual_command
):
2448 super(FixGdbCommand
, self
).__init
__(command
, gdb
.COMMAND_DATA
,
2450 self
.actual_command
= actual_command
2454 It seems that invoking either 'cy exec' and 'py-exec' work perfectly
2455 fine, but after this gdb's python API is entirely broken.
2456 Maybe some uncleared exception value is still set?
2457 sys.exc_clear() didn't help. A demonstration:
2459 (gdb) cy exec 'hello'
2461 (gdb) python gdb.execute('cont')
2462 RuntimeError: Cannot convert value to int.
2463 Error while executing Python code.
2464 (gdb) python gdb.execute('cont')
2467 Program exited normally.
2469 warnings
.filterwarnings('ignore', r
'.*', RuntimeWarning,
2470 re
.escape(__name__
))
2472 long(gdb
.parse_and_eval("(void *) 0")) == 0
2473 except RuntimeError:
2475 # warnings.resetwarnings()
2477 def invoke(self
, args
, from_tty
):
2480 gdb
.execute('%s %s' % (self
.actual_command
, args
))
2481 except RuntimeError, e
:
2482 raise gdb
.GdbError(str(e
))
2486 def _evalcode_python(executor
, code
, input_type
):
2488 Execute Python code in the most recent stack frame.
2490 global_dict
= gdb
.parse_and_eval('PyEval_GetGlobals()')
2491 local_dict
= gdb
.parse_and_eval('PyEval_GetLocals()')
2493 if (pointervalue(global_dict
) == 0 or pointervalue(local_dict
) == 0):
2494 raise gdb
.GdbError("Unable to find the locals or globals of the "
2495 "most recent Python function (relative to the "
2498 return executor
.evalcode(code
, input_type
, global_dict
, local_dict
)
2500 class PyExec(gdb
.Command
):
2502 def readcode(self
, expr
):
2504 return expr
, PythonCodeExecutor
.Py_single_input
2509 line
= raw_input('>')
2513 if line
.rstrip() == 'end':
2518 return '\n'.join(lines
), PythonCodeExecutor
.Py_file_input
2520 def invoke(self
, expr
, from_tty
):
2521 expr
, input_type
= self
.readcode(expr
)
2522 executor
= PythonCodeExecutor()
2523 executor
.xdecref(_evalcode_python(executor
, input_type
, global_dict
,
2527 gdb
.execute('set breakpoint pending on')
2529 if hasattr(gdb
, 'GdbError'):
2530 # Wrap py-step and py-next in gdb defines to make them repeatable.
2531 py_step
= PyStep('-py-step', PythonInfo())
2532 py_next
= PyNext('-py-next', PythonInfo())
2534 py_finish
= PyFinish('py-finish', PythonInfo())
2535 py_run
= PyRun('py-run', PythonInfo())
2536 py_cont
= PyCont('py-cont', PythonInfo())
2538 py_exec
= FixGdbCommand('py-exec', '-py-exec')
2539 _py_exec
= PyExec("-py-exec", gdb
.COMMAND_DATA
, gdb
.COMPLETE_NONE
)
2541 warnings
.warn("Use gdb 7.2 or higher to use the py-exec command.")