blob: e218a31f59c177c9d41eb3f0a2e208b94edfb2fb [file] [log] [blame]
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +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*
22holding three PyObject* that turn out to be PyStringObject* instances, we can
23generate a proxy value within the gdb process that is a list of strings:
24 ["foo", "bar", "baz"]
25
26Doing so can be expensive for complicated graphs of objects, and could take
27some time, so we also have a "write_repr" method that writes a representation
28of the data to a file-like object. This allows us to stop the traversal by
29having the file-like object raise an exception if it gets too much data.
30
31With both "proxyval" and "write_repr" we keep track of the set of all addresses
32visited so far in the traversal, to avoid infinite recursion due to cycles in
33the graph of object references.
34
35We try to defer gdb.lookup_type() invocations for python types until as late as
36possible: for a dynamically linked python binary, when the process starts in
37the debugger, the libpython.so hasn't been dynamically loaded yet, so none of
38the type names are known to the debugger
39
40The module also extends gdb with some python-specific commands.
41'''
Antoine Pitrou358da5b2013-11-23 17:40:36 +010042
43# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
44# compatible (2.6+ and 3.0+). See #19308.
45
46from __future__ import print_function, with_statement
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000047import gdb
Victor Stinnercc1db4b2015-09-03 10:17:28 +020048import locale
Antoine Pitrou358da5b2013-11-23 17:40:36 +010049import os
Georg Brandleefec7b2010-07-14 08:55:55 +000050import sys
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000051
Antoine Pitrou358da5b2013-11-23 17:40:36 +010052if sys.version_info[0] >= 3:
53 unichr = chr
54 xrange = range
55 long = int
56
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000057# Look up the gdb.Type for some standard types:
Victor Stinnerf6f617c2016-04-20 18:23:13 +020058# Those need to be refreshed as types (pointer sizes) may change when
59# gdb loads different executables
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000060
Victor Stinnerf6f617c2016-04-20 18:23:13 +020061def _type_char_ptr():
62 return gdb.lookup_type('char').pointer() # char*
63
64
65def _type_unsigned_char_ptr():
66 return gdb.lookup_type('unsigned char').pointer() # unsigned char*
67
68
69def _sizeof_void_p():
70 return gdb.lookup_type('void').pointer().sizeof
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000071
72
Antoine Pitrou358da5b2013-11-23 17:40:36 +010073Py_TPFLAGS_HEAPTYPE = (1 << 9)
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000074
Antoine Pitrou358da5b2013-11-23 17:40:36 +010075Py_TPFLAGS_INT_SUBCLASS = (1 << 23)
76Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
77Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
78Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
79Py_TPFLAGS_STRING_SUBCLASS = (1 << 27)
80Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
81Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
82Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
83Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000084
85
86MAX_OUTPUT_LEN=1024
87
Victor Stinnercc1db4b2015-09-03 10:17:28 +020088ENCODING = locale.getpreferredencoding()
89
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000090class NullPyObjectPtr(RuntimeError):
91 pass
92
93
94def safety_limit(val):
Serhiy Storchaka9a118f12016-04-17 09:37:36 +030095 # Given an integer value from the process being debugged, limit it to some
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +000096 # safety threshold so that arbitrary breakage within said process doesn't
97 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
98 return min(val, 1000)
99
100
101def safe_range(val):
102 # As per range, but don't trust the value too much: cap it to a safety
103 # threshold in case the data was corrupted
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100104 return xrange(safety_limit(int(val)))
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000105
Victor Stinnercc1db4b2015-09-03 10:17:28 +0200106if sys.version_info[0] >= 3:
107 def write_unicode(file, text):
108 file.write(text)
109else:
110 def write_unicode(file, text):
111 # Write a byte or unicode string to file. Unicode strings are encoded to
112 # ENCODING encoding with 'backslashreplace' error handler to avoid
113 # UnicodeEncodeError.
114 if isinstance(text, unicode):
115 text = text.encode(ENCODING, 'backslashreplace')
116 file.write(text)
117
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000118
119class StringTruncated(RuntimeError):
120 pass
121
122class TruncatedStringIO(object):
123 '''Similar to cStringIO, but can truncate the output by raising a
124 StringTruncated exception'''
125 def __init__(self, maxlen=None):
126 self._val = ''
127 self.maxlen = maxlen
128
129 def write(self, data):
130 if self.maxlen:
131 if len(data) + len(self._val) > self.maxlen:
132 # Truncation:
133 self._val += data[0:self.maxlen - len(self._val)]
134 raise StringTruncated()
135
136 self._val += data
137
138 def getvalue(self):
139 return self._val
140
141class PyObjectPtr(object):
142 """
Serhiy Storchaka9a118f12016-04-17 09:37:36 +0300143 Class wrapping a gdb.Value that's either a (PyObject*) within the
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000144 inferior process, or some subclass pointer e.g. (PyStringObject*)
145
146 There will be a subclass for every refined PyObject type that we care
147 about.
148
149 Note that at every stage the underlying pointer could be NULL, point
150 to corrupt data, etc; this is the debugger, after all.
151 """
152 _typename = 'PyObject'
153
154 def __init__(self, gdbval, cast_to=None):
155 if cast_to:
156 self._gdbval = gdbval.cast(cast_to)
157 else:
158 self._gdbval = gdbval
159
160 def field(self, name):
161 '''
162 Get the gdb.Value for the given field within the PyObject, coping with
163 some python 2 versus python 3 differences.
164
165 Various libpython types are defined using the "PyObject_HEAD" and
166 "PyObject_VAR_HEAD" macros.
167
168 In Python 2, this these are defined so that "ob_type" and (for a var
169 object) "ob_size" are fields of the type in question.
170
171 In Python 3, this is defined as an embedded PyVarObject type thus:
172 PyVarObject ob_base;
173 so that the "ob_size" field is located insize the "ob_base" field, and
174 the "ob_type" is most easily accessed by casting back to a (PyObject*).
175 '''
176 if self.is_null():
177 raise NullPyObjectPtr(self)
178
179 if name == 'ob_type':
180 pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
181 return pyo_ptr.dereference()[name]
182
183 if name == 'ob_size':
184 try:
185 # Python 2:
186 return self._gdbval.dereference()[name]
187 except RuntimeError:
188 # Python 3:
189 return self._gdbval.dereference()['ob_base'][name]
190
191 # General case: look it up inside the object:
192 return self._gdbval.dereference()[name]
193
194 def pyop_field(self, name):
195 '''
196 Get a PyObjectPtr for the given PyObject* field within this PyObject,
197 coping with some python 2 versus python 3 differences.
198 '''
199 return PyObjectPtr.from_pyobject_ptr(self.field(name))
200
201 def write_field_repr(self, name, out, visited):
202 '''
203 Extract the PyObject* field named "name", and write its representation
204 to file-like object "out"
205 '''
206 field_obj = self.pyop_field(name)
207 field_obj.write_repr(out, visited)
208
209 def get_truncated_repr(self, maxlen):
210 '''
211 Get a repr-like string for the data, but truncate it at "maxlen" bytes
212 (ending the object graph traversal as soon as you do)
213 '''
214 out = TruncatedStringIO(maxlen)
215 try:
216 self.write_repr(out, set())
217 except StringTruncated:
218 # Truncation occurred:
219 return out.getvalue() + '...(truncated)'
220
221 # No truncation occurred:
222 return out.getvalue()
223
224 def type(self):
225 return PyTypeObjectPtr(self.field('ob_type'))
226
227 def is_null(self):
228 return 0 == long(self._gdbval)
229
230 def is_optimized_out(self):
231 '''
232 Is the value of the underlying PyObject* visible to the debugger?
233
234 This can vary with the precise version of the compiler used to build
235 Python, and the precise version of gdb.
236
237 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
238 PyEval_EvalFrameEx's "f"
239 '''
240 return self._gdbval.is_optimized_out
241
242 def safe_tp_name(self):
243 try:
244 return self.type().field('tp_name').string()
245 except NullPyObjectPtr:
246 # NULL tp_name?
247 return 'unknown'
248 except RuntimeError:
249 # Can't even read the object at all?
250 return 'unknown'
251
252 def proxyval(self, visited):
253 '''
254 Scrape a value from the inferior process, and try to represent it
255 within the gdb process, whilst (hopefully) avoiding crashes when
256 the remote data is corrupt.
257
258 Derived classes will override this.
259
260 For example, a PyIntObject* with ob_ival 42 in the inferior process
261 should result in an int(42) in this process.
262
263 visited: a set of all gdb.Value pyobject pointers already visited
264 whilst generating this value (to guard against infinite recursion when
265 visiting object graphs with loops). Analogous to Py_ReprEnter and
266 Py_ReprLeave
267 '''
268
269 class FakeRepr(object):
270 """
271 Class representing a non-descript PyObject* value in the inferior
272 process for when we don't have a custom scraper, intended to have
273 a sane repr().
274 """
275
276 def __init__(self, tp_name, address):
277 self.tp_name = tp_name
278 self.address = address
279
280 def __repr__(self):
281 # For the NULL pointer, we have no way of knowing a type, so
282 # special-case it as per
283 # http://bugs.python.org/issue8032#msg100882
284 if self.address == 0:
285 return '0x0'
286 return '<%s at remote 0x%x>' % (self.tp_name, self.address)
287
288 return FakeRepr(self.safe_tp_name(),
289 long(self._gdbval))
290
291 def write_repr(self, out, visited):
292 '''
293 Write a string representation of the value scraped from the inferior
294 process to "out", a file-like object.
295 '''
296 # Default implementation: generate a proxy value and write its repr
297 # However, this could involve a lot of work for complicated objects,
298 # so for derived classes we specialize this
299 return out.write(repr(self.proxyval(visited)))
300
301 @classmethod
302 def subclass_from_type(cls, t):
303 '''
304 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
305 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
306 to use
307
308 Ideally, we would look up the symbols for the global types, but that
309 isn't working yet:
310 (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
311 Traceback (most recent call last):
312 File "<string>", line 1, in <module>
313 NotImplementedError: Symbol type not yet supported in Python scripts.
314 Error while executing Python code.
315
316 For now, we use tp_flags, after doing some string comparisons on the
317 tp_name for some special-cases that don't seem to be visible through
318 flags
319 '''
320 try:
321 tp_name = t.field('tp_name').string()
322 tp_flags = int(t.field('tp_flags'))
323 except RuntimeError:
324 # Handle any kind of error e.g. NULL ptrs by simply using the base
325 # class
326 return cls
327
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100328 #print('tp_flags = 0x%08x' % tp_flags)
329 #print('tp_name = %r' % tp_name)
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000330
331 name_map = {'bool': PyBoolObjectPtr,
332 'classobj': PyClassObjectPtr,
333 'instance': PyInstanceObjectPtr,
334 'NoneType': PyNoneStructPtr,
335 'frame': PyFrameObjectPtr,
336 'set' : PySetObjectPtr,
337 'frozenset' : PySetObjectPtr,
338 'builtin_function_or_method' : PyCFunctionObjectPtr,
339 }
340 if tp_name in name_map:
341 return name_map[tp_name]
342
343 if tp_flags & Py_TPFLAGS_HEAPTYPE:
344 return HeapTypeObjectPtr
345
346 if tp_flags & Py_TPFLAGS_INT_SUBCLASS:
347 return PyIntObjectPtr
348 if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
349 return PyLongObjectPtr
350 if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
351 return PyListObjectPtr
352 if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
353 return PyTupleObjectPtr
354 if tp_flags & Py_TPFLAGS_STRING_SUBCLASS:
355 return PyStringObjectPtr
356 if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
357 return PyUnicodeObjectPtr
358 if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
359 return PyDictObjectPtr
360 if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
361 return PyBaseExceptionObjectPtr
362 #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
363 # return PyTypeObjectPtr
364
365 # Use the base class:
366 return cls
367
368 @classmethod
369 def from_pyobject_ptr(cls, gdbval):
370 '''
371 Try to locate the appropriate derived class dynamically, and cast
372 the pointer accordingly.
373 '''
374 try:
375 p = PyObjectPtr(gdbval)
376 cls = cls.subclass_from_type(p.type())
377 return cls(gdbval, cast_to=cls.get_gdb_type())
378 except RuntimeError:
379 # Handle any kind of error e.g. NULL ptrs by simply using the base
380 # class
381 pass
382 return cls(gdbval)
383
384 @classmethod
385 def get_gdb_type(cls):
386 return gdb.lookup_type(cls._typename).pointer()
387
388 def as_address(self):
389 return long(self._gdbval)
390
391
392class ProxyAlreadyVisited(object):
393 '''
394 Placeholder proxy to use when protecting against infinite recursion due to
395 loops in the object graph.
396
397 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
398 '''
399 def __init__(self, rep):
400 self._rep = rep
401
402 def __repr__(self):
403 return self._rep
404
405
406def _write_instance_repr(out, visited, name, pyop_attrdict, address):
407 '''Shared code for use by old-style and new-style classes:
408 write a representation to file-like object "out"'''
409 out.write('<')
410 out.write(name)
411
412 # Write dictionary of instance attributes:
413 if isinstance(pyop_attrdict, PyDictObjectPtr):
414 out.write('(')
415 first = True
416 for pyop_arg, pyop_val in pyop_attrdict.iteritems():
417 if not first:
418 out.write(', ')
419 first = False
420 out.write(pyop_arg.proxyval(visited))
421 out.write('=')
422 pyop_val.write_repr(out, visited)
423 out.write(')')
424 out.write(' at remote 0x%x>' % address)
425
426
427class InstanceProxy(object):
428
429 def __init__(self, cl_name, attrdict, address):
430 self.cl_name = cl_name
431 self.attrdict = attrdict
432 self.address = address
433
434 def __repr__(self):
435 if isinstance(self.attrdict, dict):
436 kwargs = ', '.join(["%s=%r" % (arg, val)
437 for arg, val in self.attrdict.iteritems()])
438 return '<%s(%s) at remote 0x%x>' % (self.cl_name,
439 kwargs, self.address)
440 else:
441 return '<%s at remote 0x%x>' % (self.cl_name,
442 self.address)
443
444def _PyObject_VAR_SIZE(typeobj, nitems):
Victor Stinner99cff3f2011-12-19 13:59:58 +0100445 if _PyObject_VAR_SIZE._type_size_t is None:
446 _PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t')
447
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000448 return ( ( typeobj.field('tp_basicsize') +
449 nitems * typeobj.field('tp_itemsize') +
Victor Stinnerf6f617c2016-04-20 18:23:13 +0200450 (_sizeof_void_p() - 1)
451 ) & ~(_sizeof_void_p() - 1)
Victor Stinner99cff3f2011-12-19 13:59:58 +0100452 ).cast(_PyObject_VAR_SIZE._type_size_t)
453_PyObject_VAR_SIZE._type_size_t = None
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000454
455class HeapTypeObjectPtr(PyObjectPtr):
456 _typename = 'PyObject'
457
458 def get_attr_dict(self):
459 '''
460 Get the PyDictObject ptr representing the attribute dictionary
461 (or None if there's a problem)
462 '''
463 try:
464 typeobj = self.type()
465 dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
466 if dictoffset != 0:
467 if dictoffset < 0:
468 type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
469 tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
470 if tsize < 0:
471 tsize = -tsize
472 size = _PyObject_VAR_SIZE(typeobj, tsize)
473 dictoffset += size
474 assert dictoffset > 0
Victor Stinnerf6f617c2016-04-20 18:23:13 +0200475 assert dictoffset % _sizeof_void_p() == 0
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000476
Victor Stinnerf6f617c2016-04-20 18:23:13 +0200477 dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000478 PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
479 dictptr = dictptr.cast(PyObjectPtrPtr)
480 return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
481 except RuntimeError:
482 # Corrupt data somewhere; fail safe
483 pass
484
485 # Not found, or some kind of error:
486 return None
487
488 def proxyval(self, visited):
489 '''
490 Support for new-style classes.
491
492 Currently we just locate the dictionary using a transliteration to
493 python of _PyObject_GetDictPtr, ignoring descriptors
494 '''
495 # Guard against infinite loops:
496 if self.as_address() in visited:
497 return ProxyAlreadyVisited('<...>')
498 visited.add(self.as_address())
499
500 pyop_attr_dict = self.get_attr_dict()
501 if pyop_attr_dict:
502 attr_dict = pyop_attr_dict.proxyval(visited)
503 else:
504 attr_dict = {}
505 tp_name = self.safe_tp_name()
506
507 # New-style class:
508 return InstanceProxy(tp_name, attr_dict, long(self._gdbval))
509
510 def write_repr(self, out, visited):
511 # Guard against infinite loops:
512 if self.as_address() in visited:
513 out.write('<...>')
514 return
515 visited.add(self.as_address())
516
517 pyop_attrdict = self.get_attr_dict()
518 _write_instance_repr(out, visited,
519 self.safe_tp_name(), pyop_attrdict, self.as_address())
520
521class ProxyException(Exception):
522 def __init__(self, tp_name, args):
523 self.tp_name = tp_name
524 self.args = args
525
526 def __repr__(self):
527 return '%s%r' % (self.tp_name, self.args)
528
529class PyBaseExceptionObjectPtr(PyObjectPtr):
530 """
531 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
532 within the process being debugged.
533 """
534 _typename = 'PyBaseExceptionObject'
535
536 def proxyval(self, visited):
537 # Guard against infinite loops:
538 if self.as_address() in visited:
539 return ProxyAlreadyVisited('(...)')
540 visited.add(self.as_address())
541 arg_proxy = self.pyop_field('args').proxyval(visited)
542 return ProxyException(self.safe_tp_name(),
543 arg_proxy)
544
545 def write_repr(self, out, visited):
546 # Guard against infinite loops:
547 if self.as_address() in visited:
548 out.write('(...)')
549 return
550 visited.add(self.as_address())
551
552 out.write(self.safe_tp_name())
553 self.write_field_repr('args', out, visited)
554
555class PyBoolObjectPtr(PyObjectPtr):
556 """
557 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
558 <bool> instances (Py_True/Py_False) within the process being debugged.
559 """
560 _typename = 'PyBoolObject'
561
562 def proxyval(self, visited):
563 if int_from_int(self.field('ob_ival')):
564 return True
565 else:
566 return False
567
568
569class PyClassObjectPtr(PyObjectPtr):
570 """
571 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
572 instance within the process being debugged.
573 """
574 _typename = 'PyClassObject'
575
576
577class BuiltInFunctionProxy(object):
578 def __init__(self, ml_name):
579 self.ml_name = ml_name
580
581 def __repr__(self):
582 return "<built-in function %s>" % self.ml_name
583
584class BuiltInMethodProxy(object):
585 def __init__(self, ml_name, pyop_m_self):
586 self.ml_name = ml_name
587 self.pyop_m_self = pyop_m_self
588
589 def __repr__(self):
590 return ('<built-in method %s of %s object at remote 0x%x>'
591 % (self.ml_name,
592 self.pyop_m_self.safe_tp_name(),
593 self.pyop_m_self.as_address())
594 )
595
596class PyCFunctionObjectPtr(PyObjectPtr):
597 """
598 Class wrapping a gdb.Value that's a PyCFunctionObject*
599 (see Include/methodobject.h and Objects/methodobject.c)
600 """
601 _typename = 'PyCFunctionObject'
602
603 def proxyval(self, visited):
604 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
605 ml_name = m_ml['ml_name'].string()
606
607 pyop_m_self = self.pyop_field('m_self')
608 if pyop_m_self.is_null():
609 return BuiltInFunctionProxy(ml_name)
610 else:
611 return BuiltInMethodProxy(ml_name, pyop_m_self)
612
613
614class PyCodeObjectPtr(PyObjectPtr):
615 """
616 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
617 within the process being debugged.
618 """
619 _typename = 'PyCodeObject'
620
621 def addr2line(self, addrq):
622 '''
623 Get the line number for a given bytecode offset
624
625 Analogous to PyCode_Addr2Line; translated from pseudocode in
626 Objects/lnotab_notes.txt
627 '''
628 co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
629
630 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
631 # not 0, as lnotab_notes.txt has it:
632 lineno = int_from_int(self.field('co_firstlineno'))
633
634 addr = 0
635 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
636 addr += ord(addr_incr)
637 if addr > addrq:
638 return lineno
639 lineno += ord(line_incr)
640 return lineno
641
642
643class PyDictObjectPtr(PyObjectPtr):
644 """
645 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
646 within the process being debugged.
647 """
648 _typename = 'PyDictObject'
649
650 def iteritems(self):
651 '''
652 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
Ezio Melotti6d0f0f22013-08-26 01:31:30 +0300653 analogous to dict.iteritems()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000654 '''
655 for i in safe_range(self.field('ma_mask') + 1):
656 ep = self.field('ma_table') + i
657 pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
658 if not pyop_value.is_null():
659 pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
660 yield (pyop_key, pyop_value)
661
662 def proxyval(self, visited):
663 # Guard against infinite loops:
664 if self.as_address() in visited:
665 return ProxyAlreadyVisited('{...}')
666 visited.add(self.as_address())
667
668 result = {}
669 for pyop_key, pyop_value in self.iteritems():
670 proxy_key = pyop_key.proxyval(visited)
671 proxy_value = pyop_value.proxyval(visited)
672 result[proxy_key] = proxy_value
673 return result
674
675 def write_repr(self, out, visited):
676 # Guard against infinite loops:
677 if self.as_address() in visited:
678 out.write('{...}')
679 return
680 visited.add(self.as_address())
681
682 out.write('{')
683 first = True
684 for pyop_key, pyop_value in self.iteritems():
685 if not first:
686 out.write(', ')
687 first = False
688 pyop_key.write_repr(out, visited)
689 out.write(': ')
690 pyop_value.write_repr(out, visited)
691 out.write('}')
692
693class PyInstanceObjectPtr(PyObjectPtr):
694 _typename = 'PyInstanceObject'
695
696 def proxyval(self, visited):
697 # Guard against infinite loops:
698 if self.as_address() in visited:
699 return ProxyAlreadyVisited('<...>')
700 visited.add(self.as_address())
701
702 # Get name of class:
703 in_class = self.pyop_field('in_class')
704 cl_name = in_class.pyop_field('cl_name').proxyval(visited)
705
706 # Get dictionary of instance attributes:
707 in_dict = self.pyop_field('in_dict').proxyval(visited)
708
709 # Old-style class:
710 return InstanceProxy(cl_name, in_dict, long(self._gdbval))
711
712 def write_repr(self, out, visited):
713 # Guard against infinite loops:
714 if self.as_address() in visited:
715 out.write('<...>')
716 return
717 visited.add(self.as_address())
718
719 # Old-style class:
720
721 # Get name of class:
722 in_class = self.pyop_field('in_class')
723 cl_name = in_class.pyop_field('cl_name').proxyval(visited)
724
725 # Get dictionary of instance attributes:
726 pyop_in_dict = self.pyop_field('in_dict')
727
728 _write_instance_repr(out, visited,
729 cl_name, pyop_in_dict, self.as_address())
730
731class PyIntObjectPtr(PyObjectPtr):
732 _typename = 'PyIntObject'
733
734 def proxyval(self, visited):
735 result = int_from_int(self.field('ob_ival'))
736 return result
737
738class PyListObjectPtr(PyObjectPtr):
739 _typename = 'PyListObject'
740
741 def __getitem__(self, i):
742 # Get the gdb.Value for the (PyObject*) with the given index:
743 field_ob_item = self.field('ob_item')
744 return field_ob_item[i]
745
746 def proxyval(self, visited):
747 # Guard against infinite loops:
748 if self.as_address() in visited:
749 return ProxyAlreadyVisited('[...]')
750 visited.add(self.as_address())
751
752 result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
753 for i in safe_range(int_from_int(self.field('ob_size')))]
754 return result
755
756 def write_repr(self, out, visited):
757 # Guard against infinite loops:
758 if self.as_address() in visited:
759 out.write('[...]')
760 return
761 visited.add(self.as_address())
762
763 out.write('[')
764 for i in safe_range(int_from_int(self.field('ob_size'))):
765 if i > 0:
766 out.write(', ')
767 element = PyObjectPtr.from_pyobject_ptr(self[i])
768 element.write_repr(out, visited)
769 out.write(']')
770
771class PyLongObjectPtr(PyObjectPtr):
772 _typename = 'PyLongObject'
773
774 def proxyval(self, visited):
775 '''
776 Python's Include/longobjrep.h has this declaration:
777 struct _longobject {
778 PyObject_VAR_HEAD
779 digit ob_digit[1];
780 };
781
782 with this description:
783 The absolute value of a number is equal to
784 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
785 Negative numbers are represented with ob_size < 0;
786 zero is represented by ob_size == 0.
787
788 where SHIFT can be either:
789 #define PyLong_SHIFT 30
790 #define PyLong_SHIFT 15
791 '''
792 ob_size = long(self.field('ob_size'))
793 if ob_size == 0:
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100794 return 0
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000795
796 ob_digit = self.field('ob_digit')
797
798 if gdb.lookup_type('digit').sizeof == 2:
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100799 SHIFT = 15
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000800 else:
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100801 SHIFT = 30
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000802
803 digits = [long(ob_digit[i]) * 2**(SHIFT*i)
804 for i in safe_range(abs(ob_size))]
805 result = sum(digits)
806 if ob_size < 0:
807 result = -result
808 return result
809
Antoine Pitrou358da5b2013-11-23 17:40:36 +0100810 def write_repr(self, out, visited):
811 # This ensures the trailing 'L' is printed when gdb is linked
812 # with a Python 3 interpreter.
813 out.write(repr(self.proxyval(visited)).rstrip('L'))
814 out.write('L')
815
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000816
817class PyNoneStructPtr(PyObjectPtr):
818 """
819 Class wrapping a gdb.Value that's a PyObject* pointing to the
820 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
821 """
822 _typename = 'PyObject'
823
824 def proxyval(self, visited):
825 return None
826
827
828class PyFrameObjectPtr(PyObjectPtr):
829 _typename = 'PyFrameObject'
830
Victor Stinner99cff3f2011-12-19 13:59:58 +0100831 def __init__(self, gdbval, cast_to=None):
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000832 PyObjectPtr.__init__(self, gdbval, cast_to)
833
834 if not self.is_optimized_out():
835 self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
836 self.co_name = self.co.pyop_field('co_name')
837 self.co_filename = self.co.pyop_field('co_filename')
838
839 self.f_lineno = int_from_int(self.field('f_lineno'))
840 self.f_lasti = int_from_int(self.field('f_lasti'))
841 self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
842 self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
843
844 def iter_locals(self):
845 '''
846 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
847 the local variables of this frame
848 '''
849 if self.is_optimized_out():
850 return
851
852 f_localsplus = self.field('f_localsplus')
853 for i in safe_range(self.co_nlocals):
854 pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
855 if not pyop_value.is_null():
856 pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
857 yield (pyop_name, pyop_value)
858
859 def iter_globals(self):
860 '''
861 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
862 the global variables of this frame
863 '''
864 if self.is_optimized_out():
Victor Stinner99cff3f2011-12-19 13:59:58 +0100865 return ()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000866
867 pyop_globals = self.pyop_field('f_globals')
868 return pyop_globals.iteritems()
869
870 def iter_builtins(self):
871 '''
872 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
873 the builtin variables
874 '''
875 if self.is_optimized_out():
Victor Stinner99cff3f2011-12-19 13:59:58 +0100876 return ()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000877
878 pyop_builtins = self.pyop_field('f_builtins')
879 return pyop_builtins.iteritems()
880
881 def get_var_by_name(self, name):
882 '''
883 Look for the named local variable, returning a (PyObjectPtr, scope) pair
884 where scope is a string 'local', 'global', 'builtin'
885
886 If not found, return (None, None)
887 '''
888 for pyop_name, pyop_value in self.iter_locals():
889 if name == pyop_name.proxyval(set()):
890 return pyop_value, 'local'
891 for pyop_name, pyop_value in self.iter_globals():
892 if name == pyop_name.proxyval(set()):
893 return pyop_value, 'global'
894 for pyop_name, pyop_value in self.iter_builtins():
895 if name == pyop_name.proxyval(set()):
896 return pyop_value, 'builtin'
897 return None, None
898
899 def filename(self):
900 '''Get the path of the current Python source file, as a string'''
901 if self.is_optimized_out():
902 return '(frame information optimized out)'
903 return self.co_filename.proxyval(set())
904
905 def current_line_num(self):
906 '''Get current line number as an integer (1-based)
907
908 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
909
910 See Objects/lnotab_notes.txt
911 '''
912 if self.is_optimized_out():
913 return None
914 f_trace = self.field('f_trace')
915 if long(f_trace) != 0:
916 # we have a non-NULL f_trace:
917 return self.f_lineno
918 else:
919 #try:
920 return self.co.addr2line(self.f_lasti)
921 #except ValueError:
922 # return self.f_lineno
923
924 def current_line(self):
925 '''Get the text of the current source line as a string, with a trailing
926 newline character'''
927 if self.is_optimized_out():
928 return '(frame information optimized out)'
Victor Stinnercc1db4b2015-09-03 10:17:28 +0200929 filename = self.filename()
930 try:
931 f = open(filename, 'r')
932 except IOError:
933 return None
934 with f:
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000935 all_lines = f.readlines()
936 # Convert from 1-based current_line_num to 0-based list offset:
937 return all_lines[self.current_line_num()-1]
938
939 def write_repr(self, out, visited):
940 if self.is_optimized_out():
941 out.write('(frame information optimized out)')
942 return
943 out.write('Frame 0x%x, for file %s, line %i, in %s ('
944 % (self.as_address(),
Victor Stinnercc1db4b2015-09-03 10:17:28 +0200945 self.co_filename.proxyval(visited),
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000946 self.current_line_num(),
Victor Stinnercc1db4b2015-09-03 10:17:28 +0200947 self.co_name.proxyval(visited)))
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000948 first = True
949 for pyop_name, pyop_value in self.iter_locals():
950 if not first:
951 out.write(', ')
952 first = False
953
954 out.write(pyop_name.proxyval(visited))
955 out.write('=')
956 pyop_value.write_repr(out, visited)
957
958 out.write(')')
959
Victor Stinnercc1db4b2015-09-03 10:17:28 +0200960 def print_traceback(self):
961 if self.is_optimized_out():
962 sys.stdout.write(' (frame information optimized out)\n')
963 return
964 visited = set()
965 sys.stdout.write(' File "%s", line %i, in %s\n'
966 % (self.co_filename.proxyval(visited),
967 self.current_line_num(),
968 self.co_name.proxyval(visited)))
969
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +0000970class PySetObjectPtr(PyObjectPtr):
971 _typename = 'PySetObject'
972
973 def proxyval(self, visited):
974 # Guard against infinite loops:
975 if self.as_address() in visited:
976 return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
977 visited.add(self.as_address())
978
979 members = []
980 table = self.field('table')
981 for i in safe_range(self.field('mask')+1):
982 setentry = table[i]
983 key = setentry['key']
984 if key != 0:
985 key_proxy = PyObjectPtr.from_pyobject_ptr(key).proxyval(visited)
986 if key_proxy != '<dummy key>':
987 members.append(key_proxy)
988 if self.safe_tp_name() == 'frozenset':
989 return frozenset(members)
990 else:
991 return set(members)
992
993 def write_repr(self, out, visited):
994 out.write(self.safe_tp_name())
995
996 # Guard against infinite loops:
997 if self.as_address() in visited:
998 out.write('(...)')
999 return
1000 visited.add(self.as_address())
1001
1002 out.write('([')
1003 first = True
1004 table = self.field('table')
1005 for i in safe_range(self.field('mask')+1):
1006 setentry = table[i]
1007 key = setentry['key']
1008 if key != 0:
1009 pyop_key = PyObjectPtr.from_pyobject_ptr(key)
1010 key_proxy = pyop_key.proxyval(visited) # FIXME!
1011 if key_proxy != '<dummy key>':
1012 if not first:
1013 out.write(', ')
1014 first = False
1015 pyop_key.write_repr(out, visited)
1016 out.write('])')
1017
1018
1019class PyStringObjectPtr(PyObjectPtr):
1020 _typename = 'PyStringObject'
1021
1022 def __str__(self):
1023 field_ob_size = self.field('ob_size')
1024 field_ob_sval = self.field('ob_sval')
Victor Stinnerf6f617c2016-04-20 18:23:13 +02001025 char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr())
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001026 # When gdb is linked with a Python 3 interpreter, this is really
1027 # a latin-1 mojibake decoding of the original string...
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001028 return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1029
1030 def proxyval(self, visited):
1031 return str(self)
1032
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001033 def write_repr(self, out, visited):
1034 val = repr(self.proxyval(visited))
1035 if sys.version_info[0] >= 3:
1036 val = val.encode('ascii', 'backslashreplace').decode('ascii')
1037 out.write(val)
1038
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001039class PyTupleObjectPtr(PyObjectPtr):
1040 _typename = 'PyTupleObject'
1041
1042 def __getitem__(self, i):
1043 # Get the gdb.Value for the (PyObject*) with the given index:
1044 field_ob_item = self.field('ob_item')
1045 return field_ob_item[i]
1046
1047 def proxyval(self, visited):
1048 # Guard against infinite loops:
1049 if self.as_address() in visited:
1050 return ProxyAlreadyVisited('(...)')
1051 visited.add(self.as_address())
1052
1053 result = tuple([PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1054 for i in safe_range(int_from_int(self.field('ob_size')))])
1055 return result
1056
1057 def write_repr(self, out, visited):
1058 # Guard against infinite loops:
1059 if self.as_address() in visited:
1060 out.write('(...)')
1061 return
1062 visited.add(self.as_address())
1063
1064 out.write('(')
1065 for i in safe_range(int_from_int(self.field('ob_size'))):
1066 if i > 0:
1067 out.write(', ')
1068 element = PyObjectPtr.from_pyobject_ptr(self[i])
1069 element.write_repr(out, visited)
1070 if self.field('ob_size') == 1:
1071 out.write(',)')
1072 else:
1073 out.write(')')
1074
1075class PyTypeObjectPtr(PyObjectPtr):
1076 _typename = 'PyTypeObject'
1077
1078
Antoine Pitrou2fba0b32010-09-08 21:12:36 +00001079if sys.maxunicode >= 0x10000:
1080 _unichr = unichr
1081else:
1082 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1083 def _unichr(x):
1084 if x < 0x10000:
1085 return unichr(x)
1086 x -= 0x10000
1087 ch1 = 0xD800 | (x >> 10)
1088 ch2 = 0xDC00 | (x & 0x3FF)
1089 return unichr(ch1) + unichr(ch2)
1090
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001091class PyUnicodeObjectPtr(PyObjectPtr):
1092 _typename = 'PyUnicodeObject'
1093
Victor Stinnerb1556c52010-05-20 11:29:45 +00001094 def char_width(self):
1095 _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1096 return _type_Py_UNICODE.sizeof
1097
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001098 def proxyval(self, visited):
1099 # From unicodeobject.h:
1100 # Py_ssize_t length; /* Length of raw Unicode data in buffer */
1101 # Py_UNICODE *str; /* Raw Unicode buffer */
1102 field_length = long(self.field('length'))
1103 field_str = self.field('str')
1104
1105 # Gather a list of ints from the Py_UNICODE array; these are either
1106 # UCS-2 or UCS-4 code points:
Antoine Pitrou2fba0b32010-09-08 21:12:36 +00001107 if self.char_width() > 2:
1108 Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1109 else:
1110 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1111 # inferior process: we must join surrogate pairs.
1112 Py_UNICODEs = []
1113 i = 0
1114 limit = safety_limit(field_length)
1115 while i < limit:
1116 ucs = int(field_str[i])
1117 i += 1
1118 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1119 Py_UNICODEs.append(ucs)
1120 continue
1121 # This could be a surrogate pair.
1122 ucs2 = int(field_str[i])
1123 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1124 continue
1125 code = (ucs & 0x03FF) << 10
1126 code |= ucs2 & 0x03FF
1127 code += 0x00010000
1128 Py_UNICODEs.append(code)
1129 i += 1
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001130
1131 # Convert the int code points to unicode characters, and generate a
Antoine Pitrou2fba0b32010-09-08 21:12:36 +00001132 # local unicode instance.
1133 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
1134 result = u''.join([_unichr(ucs) for ucs in Py_UNICODEs])
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001135 return result
1136
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001137 def write_repr(self, out, visited):
1138 val = repr(self.proxyval(visited))
1139 if sys.version_info[0] >= 3:
1140 val = val.encode('ascii', 'backslashreplace').decode('ascii')
1141 # This ensures the 'u' prefix is printed when gdb is linked
1142 # with a Python 3 interpreter.
1143 out.write('u')
1144 out.write(val.lstrip('u'))
1145
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001146
1147def int_from_int(gdbval):
1148 return int(str(gdbval))
1149
1150
1151def stringify(val):
1152 # TODO: repr() puts everything on one line; pformat can be nicer, but
1153 # can lead to v.long results; this function isolates the choice
1154 if True:
1155 return repr(val)
1156 else:
1157 from pprint import pformat
1158 return pformat(val)
1159
1160
1161class PyObjectPtrPrinter:
1162 "Prints a (PyObject*)"
1163
1164 def __init__ (self, gdbval):
1165 self.gdbval = gdbval
1166
1167 def to_string (self):
1168 pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1169 if True:
1170 return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1171 else:
1172 # Generate full proxy value then stringify it.
1173 # Doing so could be expensive
1174 proxyval = pyop.proxyval(set())
1175 return stringify(proxyval)
1176
1177def pretty_printer_lookup(gdbval):
1178 type = gdbval.type.unqualified()
1179 if type.code == gdb.TYPE_CODE_PTR:
1180 type = type.target().unqualified()
1181 t = str(type)
1182 if t in ("PyObject", "PyFrameObject"):
1183 return PyObjectPtrPrinter(gdbval)
1184
1185"""
1186During development, I've been manually invoking the code in this way:
1187(gdb) python
1188
1189import sys
1190sys.path.append('/home/david/coding/python-gdb')
1191import libpython
1192end
1193
1194then reloading it after each edit like this:
1195(gdb) python reload(libpython)
1196
1197The following code should ensure that the prettyprinter is registered
1198if the code is autoloaded by gdb when visiting libpython.so, provided
1199that this python file is installed to the same path as the library (or its
1200.debug file) plus a "-gdb.py" suffix, e.g:
1201 /usr/lib/libpython2.6.so.1.0-gdb.py
1202 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1203"""
1204def register (obj):
1205 if obj == None:
1206 obj = gdb
1207
1208 # Wire up the pretty-printer
1209 obj.pretty_printers.append(pretty_printer_lookup)
1210
1211register (gdb.current_objfile ())
1212
1213
Martin v. Löwis24f09fd2010-04-17 22:40:40 +00001214
1215# Unfortunately, the exact API exposed by the gdb module varies somewhat
1216# from build to build
1217# See http://bugs.python.org/issue8279?#msg102276
1218
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001219class Frame(object):
1220 '''
1221 Wrapper for gdb.Frame, adding various methods
1222 '''
1223 def __init__(self, gdbframe):
1224 self._gdbframe = gdbframe
1225
1226 def older(self):
1227 older = self._gdbframe.older()
1228 if older:
1229 return Frame(older)
1230 else:
1231 return None
1232
1233 def newer(self):
1234 newer = self._gdbframe.newer()
1235 if newer:
1236 return Frame(newer)
1237 else:
1238 return None
1239
1240 def select(self):
Martin v. Löwis24f09fd2010-04-17 22:40:40 +00001241 '''If supported, select this frame and return True; return False if unsupported
1242
1243 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1244 onwards, but absent on Ubuntu buildbot'''
1245 if not hasattr(self._gdbframe, 'select'):
1246 print ('Unable to select frame: '
1247 'this build of gdb does not expose a gdb.Frame.select method')
1248 return False
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001249 self._gdbframe.select()
Martin v. Löwis24f09fd2010-04-17 22:40:40 +00001250 return True
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001251
1252 def get_index(self):
1253 '''Calculate index of frame, starting at 0 for the newest frame within
1254 this thread'''
1255 index = 0
1256 # Go down until you reach the newest frame:
1257 iter_frame = self
1258 while iter_frame.newer():
1259 index += 1
1260 iter_frame = iter_frame.newer()
1261 return index
1262
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001263 # We divide frames into:
1264 # - "python frames":
1265 # - "bytecode frames" i.e. PyEval_EvalFrameEx
1266 # - "other python frames": things that are of interest from a python
1267 # POV, but aren't bytecode (e.g. GC, GIL)
1268 # - everything else
1269
1270 def is_python_frame(self):
1271 '''Is this a PyEval_EvalFrameEx frame, or some other important
1272 frame? (see is_other_python_frame for what "important" means in this
1273 context)'''
1274 if self.is_evalframeex():
1275 return True
1276 if self.is_other_python_frame():
1277 return True
1278 return False
1279
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001280 def is_evalframeex(self):
Martin v. Löwis24f09fd2010-04-17 22:40:40 +00001281 '''Is this a PyEval_EvalFrameEx frame?'''
Victor Stinnera92e81b2010-04-20 22:28:31 +00001282 if self._gdbframe.name() == 'PyEval_EvalFrameEx':
1283 '''
1284 I believe we also need to filter on the inline
1285 struct frame_id.inline_depth, only regarding frames with
1286 an inline depth of 0 as actually being this function
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001287
Victor Stinnera92e81b2010-04-20 22:28:31 +00001288 So we reject those with type gdb.INLINE_FRAME
1289 '''
1290 if self._gdbframe.type() == gdb.NORMAL_FRAME:
1291 # We have a PyEval_EvalFrameEx frame:
1292 return True
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001293
1294 return False
1295
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001296 def is_other_python_frame(self):
1297 '''Is this frame worth displaying in python backtraces?
1298 Examples:
1299 - waiting on the GIL
1300 - garbage-collecting
1301 - within a CFunction
1302 If it is, return a descriptive string
1303 For other frames, return False
1304 '''
1305 if self.is_waiting_for_gil():
1306 return 'Waiting for the GIL'
1307 elif self.is_gc_collect():
1308 return 'Garbage-collecting'
1309 else:
1310 # Detect invocations of PyCFunction instances:
1311 older = self.older()
1312 if older and older._gdbframe.name() == 'PyCFunction_Call':
1313 # Within that frame:
1314 # "func" is the local containing the PyObject* of the
1315 # PyCFunctionObject instance
1316 # "f" is the same value, but cast to (PyCFunctionObject*)
1317 # "self" is the (PyObject*) of the 'self'
1318 try:
1319 # Use the prettyprinter for the func:
1320 func = older._gdbframe.read_var('func')
1321 return str(func)
1322 except RuntimeError:
1323 return 'PyCFunction invocation (unable to read "func")'
1324
1325 # This frame isn't worth reporting:
1326 return False
1327
1328 def is_waiting_for_gil(self):
1329 '''Is this frame waiting on the GIL?'''
1330 # This assumes the _POSIX_THREADS version of Python/ceval_gil.h:
1331 name = self._gdbframe.name()
1332 if name:
1333 return ('PyThread_acquire_lock' in name
1334 and 'lock_PyThread_acquire_lock' not in name)
1335
1336 def is_gc_collect(self):
1337 '''Is this frame "collect" within the garbage-collector?'''
1338 return self._gdbframe.name() == 'collect'
1339
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001340 def get_pyop(self):
1341 try:
1342 f = self._gdbframe.read_var('f')
Victor Stinner99cff3f2011-12-19 13:59:58 +01001343 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1344 if not frame.is_optimized_out():
1345 return frame
1346 # gdb is unable to get the "f" argument of PyEval_EvalFrameEx()
1347 # because it was "optimized out". Try to get "f" from the frame
1348 # of the caller, PyEval_EvalCodeEx().
1349 orig_frame = frame
1350 caller = self._gdbframe.older()
1351 if caller:
1352 f = caller.read_var('f')
1353 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1354 if not frame.is_optimized_out():
1355 return frame
1356 return orig_frame
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001357 except ValueError:
1358 return None
1359
1360 @classmethod
1361 def get_selected_frame(cls):
1362 _gdbframe = gdb.selected_frame()
1363 if _gdbframe:
1364 return Frame(_gdbframe)
1365 return None
1366
1367 @classmethod
1368 def get_selected_python_frame(cls):
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001369 '''Try to obtain the Frame for the python-related code in the selected
1370 frame, or None'''
1371 frame = cls.get_selected_frame()
1372
1373 while frame:
1374 if frame.is_python_frame():
1375 return frame
1376 frame = frame.older()
1377
1378 # Not found:
1379 return None
1380
1381 @classmethod
1382 def get_selected_bytecode_frame(cls):
1383 '''Try to obtain the Frame for the python bytecode interpreter in the
1384 selected GDB frame, or None'''
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001385 frame = cls.get_selected_frame()
1386
1387 while frame:
1388 if frame.is_evalframeex():
1389 return frame
1390 frame = frame.older()
1391
1392 # Not found:
1393 return None
1394
1395 def print_summary(self):
1396 if self.is_evalframeex():
1397 pyop = self.get_pyop()
1398 if pyop:
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001399 line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1400 write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
Victor Stinner99cff3f2011-12-19 13:59:58 +01001401 if not pyop.is_optimized_out():
1402 line = pyop.current_line()
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001403 if line is not None:
1404 sys.stdout.write(' %s\n' % line.strip())
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001405 else:
1406 sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1407 else:
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001408 info = self.is_other_python_frame()
1409 if info:
1410 sys.stdout.write('#%i %s\n' % (self.get_index(), info))
1411 else:
1412 sys.stdout.write('#%i\n' % self.get_index())
1413
1414 def print_traceback(self):
1415 if self.is_evalframeex():
1416 pyop = self.get_pyop()
1417 if pyop:
1418 pyop.print_traceback()
1419 if not pyop.is_optimized_out():
1420 line = pyop.current_line()
1421 if line is not None:
1422 sys.stdout.write(' %s\n' % line.strip())
1423 else:
1424 sys.stdout.write(' (unable to read python frame information)\n')
1425 else:
1426 info = self.is_other_python_frame()
1427 if info:
1428 sys.stdout.write(' %s\n' % info)
1429 else:
1430 sys.stdout.write(' (not a python frame)\n')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001431
1432class PyList(gdb.Command):
1433 '''List the current Python source code, if any
1434
1435 Use
1436 py-list START
1437 to list at a different line number within the python source.
1438
1439 Use
1440 py-list START, END
1441 to list a specific range of lines within the python source.
1442 '''
1443
1444 def __init__(self):
1445 gdb.Command.__init__ (self,
1446 "py-list",
1447 gdb.COMMAND_FILES,
1448 gdb.COMPLETE_NONE)
1449
1450
1451 def invoke(self, args, from_tty):
1452 import re
1453
1454 start = None
1455 end = None
1456
1457 m = re.match(r'\s*(\d+)\s*', args)
1458 if m:
1459 start = int(m.group(0))
1460 end = start + 10
1461
1462 m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1463 if m:
1464 start, end = map(int, m.groups())
1465
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001466 # py-list requires an actual PyEval_EvalFrameEx frame:
1467 frame = Frame.get_selected_bytecode_frame()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001468 if not frame:
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001469 print('Unable to locate gdb frame for python bytecode interpreter')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001470 return
1471
1472 pyop = frame.get_pyop()
Victor Stinner99cff3f2011-12-19 13:59:58 +01001473 if not pyop or pyop.is_optimized_out():
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001474 print('Unable to read information on python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001475 return
1476
1477 filename = pyop.filename()
1478 lineno = pyop.current_line_num()
1479
1480 if start is None:
1481 start = lineno - 5
1482 end = lineno + 5
1483
1484 if start<1:
1485 start = 1
1486
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001487 try:
1488 f = open(filename, 'r')
1489 except IOError as err:
1490 sys.stdout.write('Unable to open %s: %s\n'
1491 % (filename, err))
1492 return
1493 with f:
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001494 all_lines = f.readlines()
1495 # start and end are 1-based, all_lines is 0-based;
1496 # so [start-1:end] as a python slice gives us [start, end] as a
1497 # closed interval
1498 for i, line in enumerate(all_lines[start-1:end]):
1499 linestr = str(i+start)
1500 # Highlight current line:
1501 if i + start == lineno:
1502 linestr = '>' + linestr
1503 sys.stdout.write('%4s %s' % (linestr, line))
1504
1505
1506# ...and register the command:
1507PyList()
1508
1509def move_in_stack(move_up):
1510 '''Move up or down the stack (for the py-up/py-down command)'''
1511 frame = Frame.get_selected_python_frame()
1512 while frame:
1513 if move_up:
1514 iter_frame = frame.older()
1515 else:
1516 iter_frame = frame.newer()
1517
1518 if not iter_frame:
1519 break
1520
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001521 if iter_frame.is_python_frame():
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001522 # Result:
Martin v. Löwis24f09fd2010-04-17 22:40:40 +00001523 if iter_frame.select():
1524 iter_frame.print_summary()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001525 return
1526
1527 frame = iter_frame
1528
1529 if move_up:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001530 print('Unable to find an older python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001531 else:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001532 print('Unable to find a newer python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001533
1534class PyUp(gdb.Command):
1535 'Select and print the python stack frame that called this one (if any)'
1536 def __init__(self):
1537 gdb.Command.__init__ (self,
1538 "py-up",
1539 gdb.COMMAND_STACK,
1540 gdb.COMPLETE_NONE)
1541
1542
1543 def invoke(self, args, from_tty):
1544 move_in_stack(move_up=True)
1545
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001546class PyDown(gdb.Command):
1547 'Select and print the python stack frame called by this one (if any)'
1548 def __init__(self):
1549 gdb.Command.__init__ (self,
1550 "py-down",
1551 gdb.COMMAND_STACK,
1552 gdb.COMPLETE_NONE)
1553
1554
1555 def invoke(self, args, from_tty):
1556 move_in_stack(move_up=False)
1557
Victor Stinnera92e81b2010-04-20 22:28:31 +00001558# Not all builds of gdb have gdb.Frame.select
1559if hasattr(gdb.Frame, 'select'):
1560 PyUp()
1561 PyDown()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001562
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001563class PyBacktraceFull(gdb.Command):
1564 'Display the current python frame and all the frames within its call stack (if any)'
1565 def __init__(self):
1566 gdb.Command.__init__ (self,
1567 "py-bt-full",
1568 gdb.COMMAND_STACK,
1569 gdb.COMPLETE_NONE)
1570
1571
1572 def invoke(self, args, from_tty):
1573 frame = Frame.get_selected_python_frame()
1574 while frame:
1575 if frame.is_python_frame():
1576 frame.print_summary()
1577 frame = frame.older()
1578
1579PyBacktraceFull()
1580
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001581class PyBacktrace(gdb.Command):
1582 'Display the current python frame and all the frames within its call stack (if any)'
1583 def __init__(self):
1584 gdb.Command.__init__ (self,
1585 "py-bt",
1586 gdb.COMMAND_STACK,
1587 gdb.COMPLETE_NONE)
1588
1589
1590 def invoke(self, args, from_tty):
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001591 sys.stdout.write('Traceback (most recent call first):\n')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001592 frame = Frame.get_selected_python_frame()
1593 while frame:
Victor Stinnercc1db4b2015-09-03 10:17:28 +02001594 if frame.is_python_frame():
1595 frame.print_traceback()
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001596 frame = frame.older()
1597
1598PyBacktrace()
1599
1600class PyPrint(gdb.Command):
1601 'Look up the given python variable name, and print it'
1602 def __init__(self):
1603 gdb.Command.__init__ (self,
1604 "py-print",
1605 gdb.COMMAND_DATA,
1606 gdb.COMPLETE_NONE)
1607
1608
1609 def invoke(self, args, from_tty):
1610 name = str(args)
1611
1612 frame = Frame.get_selected_python_frame()
1613 if not frame:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001614 print('Unable to locate python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001615 return
1616
1617 pyop_frame = frame.get_pyop()
1618 if not pyop_frame:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001619 print('Unable to read information on python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001620 return
1621
1622 pyop_var, scope = pyop_frame.get_var_by_name(name)
1623
1624 if pyop_var:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001625 print('%s %r = %s'
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001626 % (scope,
1627 name,
1628 pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1629 else:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001630 print('%r not found' % name)
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001631
1632PyPrint()
1633
1634class PyLocals(gdb.Command):
1635 'Look up the given python variable name, and print it'
1636 def __init__(self):
1637 gdb.Command.__init__ (self,
1638 "py-locals",
1639 gdb.COMMAND_DATA,
1640 gdb.COMPLETE_NONE)
1641
1642
1643 def invoke(self, args, from_tty):
1644 name = str(args)
1645
1646 frame = Frame.get_selected_python_frame()
1647 if not frame:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001648 print('Unable to locate python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001649 return
1650
1651 pyop_frame = frame.get_pyop()
1652 if not pyop_frame:
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001653 print('Unable to read information on python frame')
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001654 return
1655
1656 for pyop_name, pyop_value in pyop_frame.iter_locals():
Antoine Pitrou358da5b2013-11-23 17:40:36 +01001657 print('%s = %s'
Martin v. Löwisbf0dfb32010-04-01 07:40:51 +00001658 % (pyop_name.proxyval(set()),
1659 pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1660
1661PyLocals()