blob: 41cbba2f10f351cc2b31640a3ad93d3177bdffd5 [file] [log] [blame]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001#!/usr/bin/python
2'''
3From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
4to be extended with Python code e.g. for library-specific data visualizations,
5such as for the C++ STL types. Documentation on this API can be seen at:
6http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
7
8
9This python module deals with the case when the process being debugged (the
10"inferior process" in gdb parlance) is itself python, or more specifically,
11linked against libpython. In this situation, almost every item of data is a
12(PyObject*), and having the debugger merely print their addresses is not very
13enlightening.
14
15This module embeds knowledge about the implementation details of libpython so
16that we can emit useful visualizations e.g. a string, a list, a dict, a frame
17giving file/line information and the state of local variables
18
19In particular, given a gdb.Value corresponding to a PyObject* in the inferior
20process, we can generate a "proxy value" within the gdb process. For example,
21given a PyObject* in the inferior process that is in fact a PyListObject*
Victor Stinner67df3a42010-04-21 13:53:05 +000022holding three PyObject* that turn out to be PyBytesObject* instances, we can
Martin v. Löwis5ae68102010-04-21 22:38:42 +000023generate a proxy value within the gdb process that is a list of bytes
24instances:
25 [b"foo", b"bar", b"baz"]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000026
27Doing so can be expensive for complicated graphs of objects, and could take
28some time, so we also have a "write_repr" method that writes a representation
29of the data to a file-like object. This allows us to stop the traversal by
30having the file-like object raise an exception if it gets too much data.
31
32With both "proxyval" and "write_repr" we keep track of the set of all addresses
33visited so far in the traversal, to avoid infinite recursion due to cycles in
34the graph of object references.
35
36We try to defer gdb.lookup_type() invocations for python types until as late as
37possible: for a dynamically linked python binary, when the process starts in
38the debugger, the libpython.so hasn't been dynamically loaded yet, so none of
39the type names are known to the debugger
40
41The module also extends gdb with some python-specific commands.
42'''
Antoine Pitroue50240c2013-11-23 17:40:36 +010043
44# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
45# compatible (2.6+ and 3.0+). See #19308.
46
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)a68c1bc2016-09-08 13:47:41 -070047from __future__ import print_function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000048import gdb
Antoine Pitroue50240c2013-11-23 17:40:36 +010049import os
Victor Stinner150016f2010-05-19 23:04:56 +000050import locale
Georg Brandlb639c142010-07-14 08:54:40 +000051import sys
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000052
Antoine Pitroue50240c2013-11-23 17:40:36 +010053if sys.version_info[0] >= 3:
54 unichr = chr
55 xrange = range
56 long = int
57
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000058# Look up the gdb.Type for some standard types:
Victor Stinner4e75ca82016-04-20 18:07:21 +020059# Those need to be refreshed as types (pointer sizes) may change when
60# gdb loads different executables
61
Victor Stinner4e75ca82016-04-20 18:07:21 +020062def _type_char_ptr():
63 return gdb.lookup_type('char').pointer() # char*
64
65
66def _type_unsigned_char_ptr():
67 return gdb.lookup_type('unsigned char').pointer() # unsigned char*
68
69
Victor Stinner4e75ca82016-04-20 18:07:21 +020070def _type_unsigned_short_ptr():
71 return gdb.lookup_type('unsigned short').pointer()
72
73
74def _type_unsigned_int_ptr():
75 return gdb.lookup_type('unsigned int').pointer()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000076
Victor Stinner19620c52016-04-20 18:26:12 +020077
78def _sizeof_void_p():
79 return gdb.lookup_type('void').pointer().sizeof
80
81
Victor Stinner0c4fbff2011-12-08 00:08:22 +010082# value computed later, see PyUnicodeObjectPtr.proxy()
83_is_pep393 = None
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020084
Antoine Pitroue50240c2013-11-23 17:40:36 +010085Py_TPFLAGS_HEAPTYPE = (1 << 9)
Antoine Pitroue50240c2013-11-23 17:40:36 +010086Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
87Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
88Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
89Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
90Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
91Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
92Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
93Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000094
95
96MAX_OUTPUT_LEN=1024
97
Martin v. Löwis5ae68102010-04-21 22:38:42 +000098hexdigits = "0123456789abcdef"
99
Victor Stinner150016f2010-05-19 23:04:56 +0000100ENCODING = locale.getpreferredencoding()
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000101
Łukasz Langa5fe59f82017-08-21 16:40:29 -0700102EVALFRAME = '_PyEval_EvalFrameDefault'
103
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000104class NullPyObjectPtr(RuntimeError):
105 pass
106
107
108def safety_limit(val):
Martin Panter7462b6492015-11-02 03:37:02 +0000109 # Given an integer value from the process being debugged, limit it to some
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000110 # safety threshold so that arbitrary breakage within said process doesn't
111 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
112 return min(val, 1000)
113
114
115def safe_range(val):
116 # As per range, but don't trust the value too much: cap it to a safety
117 # threshold in case the data was corrupted
Antoine Pitroue50240c2013-11-23 17:40:36 +0100118 return xrange(safety_limit(int(val)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000119
Antoine Pitroue50240c2013-11-23 17:40:36 +0100120if sys.version_info[0] >= 3:
121 def write_unicode(file, text):
122 file.write(text)
123else:
124 def write_unicode(file, text):
125 # Write a byte or unicode string to file. Unicode strings are encoded to
126 # ENCODING encoding with 'backslashreplace' error handler to avoid
127 # UnicodeEncodeError.
128 if isinstance(text, unicode):
129 text = text.encode(ENCODING, 'backslashreplace')
130 file.write(text)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000131
Antoine Pitroue50240c2013-11-23 17:40:36 +0100132try:
133 os_fsencode = os.fsencode
Antoine Pitrou23828f62013-11-23 18:20:42 +0100134except AttributeError:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100135 def os_fsencode(filename):
136 if not isinstance(filename, unicode):
137 return filename
138 encoding = sys.getfilesystemencoding()
139 if encoding == 'mbcs':
140 # mbcs doesn't support surrogateescape
141 return filename.encode(encoding)
142 encoded = []
143 for char in filename:
144 # surrogateescape error handler
145 if 0xDC80 <= ord(char) <= 0xDCFF:
146 byte = chr(ord(char) - 0xDC00)
147 else:
148 byte = char.encode(encoding)
149 encoded.append(byte)
150 return ''.join(encoded)
Victor Stinner6ffbee72010-10-17 19:35:30 +0000151
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000152class StringTruncated(RuntimeError):
153 pass
154
155class TruncatedStringIO(object):
Serhiy Storchaka50254c52013-08-29 11:35:43 +0300156 '''Similar to io.StringIO, but can truncate the output by raising a
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000157 StringTruncated exception'''
158 def __init__(self, maxlen=None):
159 self._val = ''
160 self.maxlen = maxlen
161
162 def write(self, data):
163 if self.maxlen:
164 if len(data) + len(self._val) > self.maxlen:
165 # Truncation:
166 self._val += data[0:self.maxlen - len(self._val)]
167 raise StringTruncated()
168
169 self._val += data
170
171 def getvalue(self):
172 return self._val
173
174class PyObjectPtr(object):
175 """
Martin Panter7462b6492015-11-02 03:37:02 +0000176 Class wrapping a gdb.Value that's either a (PyObject*) within the
Victor Stinner67df3a42010-04-21 13:53:05 +0000177 inferior process, or some subclass pointer e.g. (PyBytesObject*)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000178
179 There will be a subclass for every refined PyObject type that we care
180 about.
181
182 Note that at every stage the underlying pointer could be NULL, point
183 to corrupt data, etc; this is the debugger, after all.
184 """
185 _typename = 'PyObject'
186
187 def __init__(self, gdbval, cast_to=None):
188 if cast_to:
189 self._gdbval = gdbval.cast(cast_to)
190 else:
191 self._gdbval = gdbval
192
193 def field(self, name):
194 '''
195 Get the gdb.Value for the given field within the PyObject, coping with
196 some python 2 versus python 3 differences.
197
198 Various libpython types are defined using the "PyObject_HEAD" and
199 "PyObject_VAR_HEAD" macros.
200
201 In Python 2, this these are defined so that "ob_type" and (for a var
202 object) "ob_size" are fields of the type in question.
203
204 In Python 3, this is defined as an embedded PyVarObject type thus:
205 PyVarObject ob_base;
206 so that the "ob_size" field is located insize the "ob_base" field, and
207 the "ob_type" is most easily accessed by casting back to a (PyObject*).
208 '''
209 if self.is_null():
210 raise NullPyObjectPtr(self)
211
212 if name == 'ob_type':
213 pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
214 return pyo_ptr.dereference()[name]
215
216 if name == 'ob_size':
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000217 pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
218 return pyo_ptr.dereference()[name]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000219
220 # General case: look it up inside the object:
221 return self._gdbval.dereference()[name]
222
223 def pyop_field(self, name):
224 '''
225 Get a PyObjectPtr for the given PyObject* field within this PyObject,
226 coping with some python 2 versus python 3 differences.
227 '''
228 return PyObjectPtr.from_pyobject_ptr(self.field(name))
229
230 def write_field_repr(self, name, out, visited):
231 '''
232 Extract the PyObject* field named "name", and write its representation
233 to file-like object "out"
234 '''
235 field_obj = self.pyop_field(name)
236 field_obj.write_repr(out, visited)
237
238 def get_truncated_repr(self, maxlen):
239 '''
240 Get a repr-like string for the data, but truncate it at "maxlen" bytes
241 (ending the object graph traversal as soon as you do)
242 '''
243 out = TruncatedStringIO(maxlen)
244 try:
245 self.write_repr(out, set())
246 except StringTruncated:
247 # Truncation occurred:
248 return out.getvalue() + '...(truncated)'
249
250 # No truncation occurred:
251 return out.getvalue()
252
253 def type(self):
254 return PyTypeObjectPtr(self.field('ob_type'))
255
256 def is_null(self):
257 return 0 == long(self._gdbval)
258
259 def is_optimized_out(self):
260 '''
261 Is the value of the underlying PyObject* visible to the debugger?
262
263 This can vary with the precise version of the compiler used to build
264 Python, and the precise version of gdb.
265
266 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
267 PyEval_EvalFrameEx's "f"
268 '''
269 return self._gdbval.is_optimized_out
270
271 def safe_tp_name(self):
272 try:
273 return self.type().field('tp_name').string()
274 except NullPyObjectPtr:
275 # NULL tp_name?
276 return 'unknown'
277 except RuntimeError:
278 # Can't even read the object at all?
279 return 'unknown'
280
281 def proxyval(self, visited):
282 '''
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.
286
287 Derived classes will override this.
288
289 For example, a PyIntObject* with ob_ival 42 in the inferior process
290 should result in an int(42) in this process.
291
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
295 Py_ReprLeave
296 '''
297
298 class FakeRepr(object):
299 """
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
302 a sane repr().
303 """
304
305 def __init__(self, tp_name, address):
306 self.tp_name = tp_name
307 self.address = address
308
309 def __repr__(self):
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:
314 return '0x0'
315 return '<%s at remote 0x%x>' % (self.tp_name, self.address)
316
317 return FakeRepr(self.safe_tp_name(),
318 long(self._gdbval))
319
320 def write_repr(self, out, visited):
321 '''
322 Write a string representation of the value scraped from the inferior
323 process to "out", a file-like object.
324 '''
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)))
329
330 @classmethod
331 def subclass_from_type(cls, t):
332 '''
333 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
334 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
335 to use
336
337 Ideally, we would look up the symbols for the global types, but that
338 isn't working yet:
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.
344
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
347 flags
348 '''
349 try:
350 tp_name = t.field('tp_name').string()
351 tp_flags = int(t.field('tp_flags'))
352 except RuntimeError:
353 # Handle any kind of error e.g. NULL ptrs by simply using the base
354 # class
355 return cls
356
Antoine Pitroue50240c2013-11-23 17:40:36 +0100357 #print('tp_flags = 0x%08x' % tp_flags)
358 #print('tp_name = %r' % tp_name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000359
360 name_map = {'bool': PyBoolObjectPtr,
361 'classobj': PyClassObjectPtr,
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000362 'NoneType': PyNoneStructPtr,
363 'frame': PyFrameObjectPtr,
364 'set' : PySetObjectPtr,
365 'frozenset' : PySetObjectPtr,
366 'builtin_function_or_method' : PyCFunctionObjectPtr,
Victor Stinner61108332017-02-01 16:29:54 +0100367 'method-wrapper': wrapperobject,
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000368 }
369 if tp_name in name_map:
370 return name_map[tp_name]
371
372 if tp_flags & Py_TPFLAGS_HEAPTYPE:
373 return HeapTypeObjectPtr
374
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000375 if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
376 return PyLongObjectPtr
377 if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
378 return PyListObjectPtr
379 if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
380 return PyTupleObjectPtr
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000381 if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
Victor Stinner67df3a42010-04-21 13:53:05 +0000382 return PyBytesObjectPtr
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000383 if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
384 return PyUnicodeObjectPtr
385 if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
386 return PyDictObjectPtr
387 if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
388 return PyBaseExceptionObjectPtr
389 #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
390 # return PyTypeObjectPtr
391
392 # Use the base class:
393 return cls
394
395 @classmethod
396 def from_pyobject_ptr(cls, gdbval):
397 '''
398 Try to locate the appropriate derived class dynamically, and cast
399 the pointer accordingly.
400 '''
401 try:
402 p = PyObjectPtr(gdbval)
403 cls = cls.subclass_from_type(p.type())
404 return cls(gdbval, cast_to=cls.get_gdb_type())
405 except RuntimeError:
406 # Handle any kind of error e.g. NULL ptrs by simply using the base
407 # class
408 pass
409 return cls(gdbval)
410
411 @classmethod
412 def get_gdb_type(cls):
413 return gdb.lookup_type(cls._typename).pointer()
414
415 def as_address(self):
416 return long(self._gdbval)
417
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000418class PyVarObjectPtr(PyObjectPtr):
419 _typename = 'PyVarObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000420
421class ProxyAlreadyVisited(object):
422 '''
423 Placeholder proxy to use when protecting against infinite recursion due to
424 loops in the object graph.
425
426 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
427 '''
428 def __init__(self, rep):
429 self._rep = rep
430
431 def __repr__(self):
432 return self._rep
433
434
435def _write_instance_repr(out, visited, name, pyop_attrdict, address):
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100436 '''Shared code for use by all classes:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000437 write a representation to file-like object "out"'''
438 out.write('<')
439 out.write(name)
440
441 # Write dictionary of instance attributes:
442 if isinstance(pyop_attrdict, PyDictObjectPtr):
443 out.write('(')
444 first = True
445 for pyop_arg, pyop_val in pyop_attrdict.iteritems():
446 if not first:
447 out.write(', ')
448 first = False
449 out.write(pyop_arg.proxyval(visited))
450 out.write('=')
451 pyop_val.write_repr(out, visited)
452 out.write(')')
453 out.write(' at remote 0x%x>' % address)
454
455
456class InstanceProxy(object):
457
458 def __init__(self, cl_name, attrdict, address):
459 self.cl_name = cl_name
460 self.attrdict = attrdict
461 self.address = address
462
463 def __repr__(self):
464 if isinstance(self.attrdict, dict):
465 kwargs = ', '.join(["%s=%r" % (arg, val)
466 for arg, val in self.attrdict.iteritems()])
467 return '<%s(%s) at remote 0x%x>' % (self.cl_name,
468 kwargs, self.address)
469 else:
470 return '<%s at remote 0x%x>' % (self.cl_name,
471 self.address)
472
473def _PyObject_VAR_SIZE(typeobj, nitems):
Victor Stinnerd2084162011-12-19 13:42:24 +0100474 if _PyObject_VAR_SIZE._type_size_t is None:
475 _PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t')
476
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000477 return ( ( typeobj.field('tp_basicsize') +
478 nitems * typeobj.field('tp_itemsize') +
Victor Stinner4e75ca82016-04-20 18:07:21 +0200479 (_sizeof_void_p() - 1)
480 ) & ~(_sizeof_void_p() - 1)
Victor Stinnerd2084162011-12-19 13:42:24 +0100481 ).cast(_PyObject_VAR_SIZE._type_size_t)
482_PyObject_VAR_SIZE._type_size_t = None
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000483
484class HeapTypeObjectPtr(PyObjectPtr):
485 _typename = 'PyObject'
486
487 def get_attr_dict(self):
488 '''
489 Get the PyDictObject ptr representing the attribute dictionary
490 (or None if there's a problem)
491 '''
492 try:
493 typeobj = self.type()
494 dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
495 if dictoffset != 0:
496 if dictoffset < 0:
497 type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
498 tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
499 if tsize < 0:
500 tsize = -tsize
501 size = _PyObject_VAR_SIZE(typeobj, tsize)
502 dictoffset += size
503 assert dictoffset > 0
Victor Stinner4e75ca82016-04-20 18:07:21 +0200504 assert dictoffset % _sizeof_void_p() == 0
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000505
Victor Stinner4e75ca82016-04-20 18:07:21 +0200506 dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000507 PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
508 dictptr = dictptr.cast(PyObjectPtrPtr)
509 return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
510 except RuntimeError:
511 # Corrupt data somewhere; fail safe
512 pass
513
514 # Not found, or some kind of error:
515 return None
516
517 def proxyval(self, visited):
518 '''
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100519 Support for classes.
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000520
521 Currently we just locate the dictionary using a transliteration to
522 python of _PyObject_GetDictPtr, ignoring descriptors
523 '''
524 # Guard against infinite loops:
525 if self.as_address() in visited:
526 return ProxyAlreadyVisited('<...>')
527 visited.add(self.as_address())
528
529 pyop_attr_dict = self.get_attr_dict()
530 if pyop_attr_dict:
531 attr_dict = pyop_attr_dict.proxyval(visited)
532 else:
533 attr_dict = {}
534 tp_name = self.safe_tp_name()
535
Florent Xiclunaaa6c1d22011-12-12 18:54:29 +0100536 # Class:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000537 return InstanceProxy(tp_name, attr_dict, long(self._gdbval))
538
539 def write_repr(self, out, visited):
540 # Guard against infinite loops:
541 if self.as_address() in visited:
542 out.write('<...>')
543 return
544 visited.add(self.as_address())
545
546 pyop_attrdict = self.get_attr_dict()
547 _write_instance_repr(out, visited,
548 self.safe_tp_name(), pyop_attrdict, self.as_address())
549
550class ProxyException(Exception):
551 def __init__(self, tp_name, args):
552 self.tp_name = tp_name
553 self.args = args
554
555 def __repr__(self):
556 return '%s%r' % (self.tp_name, self.args)
557
558class PyBaseExceptionObjectPtr(PyObjectPtr):
559 """
560 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
561 within the process being debugged.
562 """
563 _typename = 'PyBaseExceptionObject'
564
565 def proxyval(self, visited):
566 # Guard against infinite loops:
567 if self.as_address() in visited:
568 return ProxyAlreadyVisited('(...)')
569 visited.add(self.as_address())
570 arg_proxy = self.pyop_field('args').proxyval(visited)
571 return ProxyException(self.safe_tp_name(),
572 arg_proxy)
573
574 def write_repr(self, out, visited):
575 # Guard against infinite loops:
576 if self.as_address() in visited:
577 out.write('(...)')
578 return
579 visited.add(self.as_address())
580
581 out.write(self.safe_tp_name())
582 self.write_field_repr('args', out, visited)
583
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000584class PyClassObjectPtr(PyObjectPtr):
585 """
586 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
587 instance within the process being debugged.
588 """
589 _typename = 'PyClassObject'
590
591
592class BuiltInFunctionProxy(object):
593 def __init__(self, ml_name):
594 self.ml_name = ml_name
595
596 def __repr__(self):
597 return "<built-in function %s>" % self.ml_name
598
599class BuiltInMethodProxy(object):
600 def __init__(self, ml_name, pyop_m_self):
601 self.ml_name = ml_name
602 self.pyop_m_self = pyop_m_self
603
604 def __repr__(self):
605 return ('<built-in method %s of %s object at remote 0x%x>'
606 % (self.ml_name,
607 self.pyop_m_self.safe_tp_name(),
608 self.pyop_m_self.as_address())
609 )
610
611class PyCFunctionObjectPtr(PyObjectPtr):
612 """
613 Class wrapping a gdb.Value that's a PyCFunctionObject*
614 (see Include/methodobject.h and Objects/methodobject.c)
615 """
616 _typename = 'PyCFunctionObject'
617
618 def proxyval(self, visited):
619 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
620 ml_name = m_ml['ml_name'].string()
621
622 pyop_m_self = self.pyop_field('m_self')
623 if pyop_m_self.is_null():
624 return BuiltInFunctionProxy(ml_name)
625 else:
626 return BuiltInMethodProxy(ml_name, pyop_m_self)
627
628
629class PyCodeObjectPtr(PyObjectPtr):
630 """
631 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
632 within the process being debugged.
633 """
634 _typename = 'PyCodeObject'
635
636 def addr2line(self, addrq):
637 '''
638 Get the line number for a given bytecode offset
639
640 Analogous to PyCode_Addr2Line; translated from pseudocode in
641 Objects/lnotab_notes.txt
642 '''
643 co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
644
645 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
646 # not 0, as lnotab_notes.txt has it:
647 lineno = int_from_int(self.field('co_firstlineno'))
648
649 addr = 0
650 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
651 addr += ord(addr_incr)
652 if addr > addrq:
653 return lineno
654 lineno += ord(line_incr)
655 return lineno
656
657
658class PyDictObjectPtr(PyObjectPtr):
659 """
660 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
661 within the process being debugged.
662 """
663 _typename = 'PyDictObject'
664
665 def iteritems(self):
666 '''
667 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
Ezio Melotti7c4a7e62013-08-26 01:32:56 +0300668 analogous to dict.iteritems()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000669 '''
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400670 keys = self.field('ma_keys')
671 values = self.field('ma_values')
INADA Naokid7d2bc82016-11-22 19:40:58 +0900672 entries, nentries = self._get_entries(keys)
673 for i in safe_range(nentries):
674 ep = entries[i]
Benjamin Peterson7d95e402012-04-23 11:24:50 -0400675 if long(values):
676 pyop_value = PyObjectPtr.from_pyobject_ptr(values[i])
677 else:
678 pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000679 if not pyop_value.is_null():
680 pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
681 yield (pyop_key, pyop_value)
682
683 def proxyval(self, visited):
684 # Guard against infinite loops:
685 if self.as_address() in visited:
686 return ProxyAlreadyVisited('{...}')
687 visited.add(self.as_address())
688
689 result = {}
690 for pyop_key, pyop_value in self.iteritems():
691 proxy_key = pyop_key.proxyval(visited)
692 proxy_value = pyop_value.proxyval(visited)
693 result[proxy_key] = proxy_value
694 return result
695
696 def write_repr(self, out, visited):
697 # Guard against infinite loops:
698 if self.as_address() in visited:
699 out.write('{...}')
700 return
701 visited.add(self.as_address())
702
703 out.write('{')
704 first = True
705 for pyop_key, pyop_value in self.iteritems():
706 if not first:
707 out.write(', ')
708 first = False
709 pyop_key.write_repr(out, visited)
710 out.write(': ')
711 pyop_value.write_repr(out, visited)
712 out.write('}')
713
INADA Naokid7d2bc82016-11-22 19:40:58 +0900714 def _get_entries(self, keys):
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100715 dk_nentries = int(keys['dk_nentries'])
INADA Naokid7d2bc82016-11-22 19:40:58 +0900716 dk_size = int(keys['dk_size'])
717 try:
718 # <= Python 3.5
719 return keys['dk_entries'], dk_size
Lev Abalkin661ca882017-03-01 13:16:23 -0500720 except RuntimeError:
INADA Naokid7d2bc82016-11-22 19:40:58 +0900721 # >= Python 3.6
722 pass
723
724 if dk_size <= 0xFF:
725 offset = dk_size
726 elif dk_size <= 0xFFFF:
727 offset = 2 * dk_size
728 elif dk_size <= 0xFFFFFFFF:
729 offset = 4 * dk_size
730 else:
731 offset = 8 * dk_size
732
Gregory P. Smith53f67d42018-04-20 11:32:08 -0700733 ent_addr = keys['dk_indices'].address
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100734 ent_addr = ent_addr.cast(_type_unsigned_char_ptr()) + offset
INADA Naokid7d2bc82016-11-22 19:40:58 +0900735 ent_ptr_t = gdb.lookup_type('PyDictKeyEntry').pointer()
Victor Stinner3a5d79f2016-11-22 13:09:39 +0100736 ent_addr = ent_addr.cast(ent_ptr_t)
737
738 return ent_addr, dk_nentries
INADA Naokid7d2bc82016-11-22 19:40:58 +0900739
740
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000741class PyListObjectPtr(PyObjectPtr):
742 _typename = 'PyListObject'
743
744 def __getitem__(self, i):
745 # Get the gdb.Value for the (PyObject*) with the given index:
746 field_ob_item = self.field('ob_item')
747 return field_ob_item[i]
748
749 def proxyval(self, visited):
750 # Guard against infinite loops:
751 if self.as_address() in visited:
752 return ProxyAlreadyVisited('[...]')
753 visited.add(self.as_address())
754
755 result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
756 for i in safe_range(int_from_int(self.field('ob_size')))]
757 return result
758
759 def write_repr(self, out, visited):
760 # Guard against infinite loops:
761 if self.as_address() in visited:
762 out.write('[...]')
763 return
764 visited.add(self.as_address())
765
766 out.write('[')
767 for i in safe_range(int_from_int(self.field('ob_size'))):
768 if i > 0:
769 out.write(', ')
770 element = PyObjectPtr.from_pyobject_ptr(self[i])
771 element.write_repr(out, visited)
772 out.write(']')
773
774class PyLongObjectPtr(PyObjectPtr):
775 _typename = 'PyLongObject'
776
777 def proxyval(self, visited):
778 '''
779 Python's Include/longobjrep.h has this declaration:
780 struct _longobject {
781 PyObject_VAR_HEAD
782 digit ob_digit[1];
783 };
784
785 with this description:
786 The absolute value of a number is equal to
787 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
788 Negative numbers are represented with ob_size < 0;
789 zero is represented by ob_size == 0.
790
791 where SHIFT can be either:
792 #define PyLong_SHIFT 30
793 #define PyLong_SHIFT 15
794 '''
795 ob_size = long(self.field('ob_size'))
796 if ob_size == 0:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100797 return 0
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000798
799 ob_digit = self.field('ob_digit')
800
801 if gdb.lookup_type('digit').sizeof == 2:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100802 SHIFT = 15
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000803 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +0100804 SHIFT = 30
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000805
806 digits = [long(ob_digit[i]) * 2**(SHIFT*i)
807 for i in safe_range(abs(ob_size))]
808 result = sum(digits)
809 if ob_size < 0:
810 result = -result
811 return result
812
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000813 def write_repr(self, out, visited):
814 # Write this out as a Python 3 int literal, i.e. without the "L" suffix
815 proxy = self.proxyval(visited)
816 out.write("%s" % proxy)
817
818
819class PyBoolObjectPtr(PyLongObjectPtr):
820 """
821 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
822 <bool> instances (Py_True/Py_False) within the process being debugged.
823 """
824 def proxyval(self, visited):
825 if PyLongObjectPtr.proxyval(self, visited):
826 return True
827 else:
828 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000829
830class PyNoneStructPtr(PyObjectPtr):
831 """
832 Class wrapping a gdb.Value that's a PyObject* pointing to the
833 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
834 """
835 _typename = 'PyObject'
836
837 def proxyval(self, visited):
838 return None
839
840
841class PyFrameObjectPtr(PyObjectPtr):
842 _typename = 'PyFrameObject'
843
Victor Stinnerd2084162011-12-19 13:42:24 +0100844 def __init__(self, gdbval, cast_to=None):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000845 PyObjectPtr.__init__(self, gdbval, cast_to)
846
847 if not self.is_optimized_out():
848 self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
849 self.co_name = self.co.pyop_field('co_name')
850 self.co_filename = self.co.pyop_field('co_filename')
851
852 self.f_lineno = int_from_int(self.field('f_lineno'))
853 self.f_lasti = int_from_int(self.field('f_lasti'))
854 self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
855 self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
856
857 def iter_locals(self):
858 '''
859 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
860 the local variables of this frame
861 '''
862 if self.is_optimized_out():
863 return
864
865 f_localsplus = self.field('f_localsplus')
866 for i in safe_range(self.co_nlocals):
867 pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
868 if not pyop_value.is_null():
869 pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
870 yield (pyop_name, pyop_value)
871
872 def iter_globals(self):
873 '''
874 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
875 the global variables of this frame
876 '''
877 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100878 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000879
880 pyop_globals = self.pyop_field('f_globals')
881 return pyop_globals.iteritems()
882
883 def iter_builtins(self):
884 '''
885 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
886 the builtin variables
887 '''
888 if self.is_optimized_out():
Victor Stinnerd2084162011-12-19 13:42:24 +0100889 return ()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000890
891 pyop_builtins = self.pyop_field('f_builtins')
892 return pyop_builtins.iteritems()
893
894 def get_var_by_name(self, name):
895 '''
896 Look for the named local variable, returning a (PyObjectPtr, scope) pair
897 where scope is a string 'local', 'global', 'builtin'
898
899 If not found, return (None, None)
900 '''
901 for pyop_name, pyop_value in self.iter_locals():
902 if name == pyop_name.proxyval(set()):
903 return pyop_value, 'local'
904 for pyop_name, pyop_value in self.iter_globals():
905 if name == pyop_name.proxyval(set()):
906 return pyop_value, 'global'
907 for pyop_name, pyop_value in self.iter_builtins():
908 if name == pyop_name.proxyval(set()):
909 return pyop_value, 'builtin'
910 return None, None
911
912 def filename(self):
913 '''Get the path of the current Python source file, as a string'''
914 if self.is_optimized_out():
915 return '(frame information optimized out)'
916 return self.co_filename.proxyval(set())
917
918 def current_line_num(self):
919 '''Get current line number as an integer (1-based)
920
921 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
922
923 See Objects/lnotab_notes.txt
924 '''
925 if self.is_optimized_out():
926 return None
927 f_trace = self.field('f_trace')
928 if long(f_trace) != 0:
929 # we have a non-NULL f_trace:
930 return self.f_lineno
931 else:
932 #try:
933 return self.co.addr2line(self.f_lasti)
934 #except ValueError:
935 # return self.f_lineno
936
937 def current_line(self):
938 '''Get the text of the current source line as a string, with a trailing
939 newline character'''
940 if self.is_optimized_out():
941 return '(frame information optimized out)'
Victor Stinner6ffbee72010-10-17 19:35:30 +0000942 filename = self.filename()
Victor Stinnerd57c5c82011-07-01 12:57:44 +0200943 try:
944 f = open(os_fsencode(filename), 'r')
945 except IOError:
946 return None
947 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000948 all_lines = f.readlines()
949 # Convert from 1-based current_line_num to 0-based list offset:
950 return all_lines[self.current_line_num()-1]
951
952 def write_repr(self, out, visited):
953 if self.is_optimized_out():
954 out.write('(frame information optimized out)')
955 return
956 out.write('Frame 0x%x, for file %s, line %i, in %s ('
957 % (self.as_address(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000958 self.co_filename.proxyval(visited),
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000959 self.current_line_num(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000960 self.co_name.proxyval(visited)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000961 first = True
962 for pyop_name, pyop_value in self.iter_locals():
963 if not first:
964 out.write(', ')
965 first = False
966
967 out.write(pyop_name.proxyval(visited))
968 out.write('=')
969 pyop_value.write_repr(out, visited)
970
971 out.write(')')
972
Victor Stinnere670c882011-05-13 17:40:15 +0200973 def print_traceback(self):
974 if self.is_optimized_out():
975 sys.stdout.write(' (frame information optimized out)\n')
Victor Stinnerd2084162011-12-19 13:42:24 +0100976 return
Victor Stinnere670c882011-05-13 17:40:15 +0200977 visited = set()
978 sys.stdout.write(' File "%s", line %i, in %s\n'
979 % (self.co_filename.proxyval(visited),
980 self.current_line_num(),
981 self.co_name.proxyval(visited)))
982
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000983class PySetObjectPtr(PyObjectPtr):
984 _typename = 'PySetObject'
985
Antoine Pitrou9d952542013-08-24 21:07:07 +0200986 @classmethod
987 def _dummy_key(self):
988 return gdb.lookup_global_symbol('_PySet_Dummy').value()
989
990 def __iter__(self):
991 dummy_ptr = self._dummy_key()
992 table = self.field('table')
993 for i in safe_range(self.field('mask') + 1):
994 setentry = table[i]
995 key = setentry['key']
996 if key != 0 and key != dummy_ptr:
997 yield PyObjectPtr.from_pyobject_ptr(key)
998
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000999 def proxyval(self, visited):
1000 # Guard against infinite loops:
1001 if self.as_address() in visited:
1002 return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
1003 visited.add(self.as_address())
1004
Antoine Pitrou9d952542013-08-24 21:07:07 +02001005 members = (key.proxyval(visited) for key in self)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001006 if self.safe_tp_name() == 'frozenset':
1007 return frozenset(members)
1008 else:
1009 return set(members)
1010
1011 def write_repr(self, out, visited):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001012 # Emulate Python 3's set_repr
1013 tp_name = self.safe_tp_name()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001014
1015 # Guard against infinite loops:
1016 if self.as_address() in visited:
1017 out.write('(...)')
1018 return
1019 visited.add(self.as_address())
1020
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001021 # Python 3's set_repr special-cases the empty set:
1022 if not self.field('used'):
1023 out.write(tp_name)
1024 out.write('()')
1025 return
1026
1027 # Python 3 uses {} for set literals:
1028 if tp_name != 'set':
1029 out.write(tp_name)
1030 out.write('(')
1031
1032 out.write('{')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001033 first = True
Antoine Pitrou9d952542013-08-24 21:07:07 +02001034 for key in self:
1035 if not first:
1036 out.write(', ')
1037 first = False
1038 key.write_repr(out, visited)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001039 out.write('}')
1040
1041 if tp_name != 'set':
1042 out.write(')')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001043
1044
Victor Stinner67df3a42010-04-21 13:53:05 +00001045class PyBytesObjectPtr(PyObjectPtr):
1046 _typename = 'PyBytesObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001047
1048 def __str__(self):
1049 field_ob_size = self.field('ob_size')
1050 field_ob_sval = self.field('ob_sval')
Victor Stinner4e75ca82016-04-20 18:07:21 +02001051 char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001052 return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1053
1054 def proxyval(self, visited):
1055 return str(self)
1056
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001057 def write_repr(self, out, visited):
1058 # Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1059
1060 # Get a PyStringObject* within the Python 2 gdb process:
1061 proxy = self.proxyval(visited)
1062
1063 # Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1064 # to Python 2 code:
1065 quote = "'"
1066 if "'" in proxy and not '"' in proxy:
1067 quote = '"'
1068 out.write('b')
1069 out.write(quote)
1070 for byte in proxy:
1071 if byte == quote or byte == '\\':
1072 out.write('\\')
1073 out.write(byte)
1074 elif byte == '\t':
1075 out.write('\\t')
1076 elif byte == '\n':
1077 out.write('\\n')
1078 elif byte == '\r':
1079 out.write('\\r')
1080 elif byte < ' ' or ord(byte) >= 0x7f:
1081 out.write('\\x')
1082 out.write(hexdigits[(ord(byte) & 0xf0) >> 4])
1083 out.write(hexdigits[ord(byte) & 0xf])
1084 else:
1085 out.write(byte)
1086 out.write(quote)
1087
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001088class PyTupleObjectPtr(PyObjectPtr):
1089 _typename = 'PyTupleObject'
1090
1091 def __getitem__(self, i):
1092 # Get the gdb.Value for the (PyObject*) with the given index:
1093 field_ob_item = self.field('ob_item')
1094 return field_ob_item[i]
1095
1096 def proxyval(self, visited):
1097 # Guard against infinite loops:
1098 if self.as_address() in visited:
1099 return ProxyAlreadyVisited('(...)')
1100 visited.add(self.as_address())
1101
Jon Dufresne39726282017-05-18 07:35:54 -07001102 result = tuple(PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1103 for i in safe_range(int_from_int(self.field('ob_size'))))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001104 return result
1105
1106 def write_repr(self, out, visited):
1107 # Guard against infinite loops:
1108 if self.as_address() in visited:
1109 out.write('(...)')
1110 return
1111 visited.add(self.as_address())
1112
1113 out.write('(')
1114 for i in safe_range(int_from_int(self.field('ob_size'))):
1115 if i > 0:
1116 out.write(', ')
1117 element = PyObjectPtr.from_pyobject_ptr(self[i])
1118 element.write_repr(out, visited)
1119 if self.field('ob_size') == 1:
1120 out.write(',)')
1121 else:
1122 out.write(')')
1123
1124class PyTypeObjectPtr(PyObjectPtr):
1125 _typename = 'PyTypeObject'
1126
1127
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001128def _unichr_is_printable(char):
1129 # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1130 if char == u" ":
1131 return True
1132 import unicodedata
Antoine Pitroub41e1282010-09-08 20:57:48 +00001133 return unicodedata.category(char) not in ("C", "Z")
1134
1135if sys.maxunicode >= 0x10000:
1136 _unichr = unichr
1137else:
1138 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1139 def _unichr(x):
1140 if x < 0x10000:
1141 return unichr(x)
1142 x -= 0x10000
1143 ch1 = 0xD800 | (x >> 10)
1144 ch2 = 0xDC00 | (x & 0x3FF)
1145 return unichr(ch1) + unichr(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001146
1147
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001148class PyUnicodeObjectPtr(PyObjectPtr):
1149 _typename = 'PyUnicodeObject'
1150
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001151 def char_width(self):
1152 _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1153 return _type_Py_UNICODE.sizeof
1154
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001155 def proxyval(self, visited):
Victor Stinner0c4fbff2011-12-08 00:08:22 +01001156 global _is_pep393
1157 if _is_pep393 is None:
1158 fields = gdb.lookup_type('PyUnicodeObject').target().fields()
1159 _is_pep393 = 'data' in [f.name for f in fields]
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001160 if _is_pep393:
1161 # Python 3.3 and newer
1162 may_have_surrogates = False
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001163 compact = self.field('_base')
1164 ascii = compact['_base']
1165 state = ascii['state']
Victor Stinnera3b334d2011-10-03 13:53:37 +02001166 is_compact_ascii = (int(state['ascii']) and int(state['compact']))
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001167 if not int(state['ready']):
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001168 # string is not ready
Victor Stinnerf16a3502011-11-04 22:34:01 +01001169 field_length = long(compact['wstr_length'])
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001170 may_have_surrogates = True
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001171 field_str = ascii['wstr']
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001172 else:
Victor Stinnerf16a3502011-11-04 22:34:01 +01001173 field_length = long(ascii['length'])
Victor Stinnera3b334d2011-10-03 13:53:37 +02001174 if is_compact_ascii:
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001175 field_str = ascii.address + 1
1176 elif int(state['compact']):
1177 field_str = compact.address + 1
1178 else:
1179 field_str = self.field('data')['any']
1180 repr_kind = int(state['kind'])
1181 if repr_kind == 1:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001182 field_str = field_str.cast(_type_unsigned_char_ptr())
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001183 elif repr_kind == 2:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001184 field_str = field_str.cast(_type_unsigned_short_ptr())
Antoine Pitrou3c0c5f22011-10-08 19:33:24 +02001185 elif repr_kind == 4:
Victor Stinner4e75ca82016-04-20 18:07:21 +02001186 field_str = field_str.cast(_type_unsigned_int_ptr())
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001187 else:
1188 # Python 3.2 and earlier
Martin v. Löwis24fa9832011-09-28 08:35:25 +02001189 field_length = long(self.field('length'))
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001190 field_str = self.field('str')
1191 may_have_surrogates = self.char_width() == 2
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001192
1193 # Gather a list of ints from the Py_UNICODE array; these are either
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001194 # UCS-1, UCS-2 or UCS-4 code points:
1195 if not may_have_surrogates:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001196 Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1197 else:
1198 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1199 # inferior process: we must join surrogate pairs.
1200 Py_UNICODEs = []
1201 i = 0
Antoine Pitroub1856d72010-09-08 21:07:40 +00001202 limit = safety_limit(field_length)
1203 while i < limit:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001204 ucs = int(field_str[i])
1205 i += 1
1206 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1207 Py_UNICODEs.append(ucs)
1208 continue
1209 # This could be a surrogate pair.
1210 ucs2 = int(field_str[i])
1211 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1212 continue
1213 code = (ucs & 0x03FF) << 10
1214 code |= ucs2 & 0x03FF
1215 code += 0x00010000
1216 Py_UNICODEs.append(code)
1217 i += 1
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001218
1219 # Convert the int code points to unicode characters, and generate a
Antoine Pitroub41e1282010-09-08 20:57:48 +00001220 # local unicode instance.
1221 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
Victor Stinnerd8a5cc92013-04-11 21:37:45 +02001222 result = u''.join([
1223 (_unichr(ucs) if ucs <= 0x10ffff else '\ufffd')
1224 for ucs in Py_UNICODEs])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001225 return result
1226
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001227 def write_repr(self, out, visited):
1228 # Write this out as a Python 3 str literal, i.e. without a "u" prefix
1229
1230 # Get a PyUnicodeObject* within the Python 2 gdb process:
1231 proxy = self.proxyval(visited)
1232
1233 # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1234 # to Python 2:
1235 if "'" in proxy and '"' not in proxy:
1236 quote = '"'
1237 else:
1238 quote = "'"
1239 out.write(quote)
1240
1241 i = 0
1242 while i < len(proxy):
1243 ch = proxy[i]
1244 i += 1
1245
1246 # Escape quotes and backslashes
1247 if ch == quote or ch == '\\':
1248 out.write('\\')
1249 out.write(ch)
1250
1251 # Map special whitespace to '\t', \n', '\r'
1252 elif ch == '\t':
1253 out.write('\\t')
1254 elif ch == '\n':
1255 out.write('\\n')
1256 elif ch == '\r':
1257 out.write('\\r')
1258
1259 # Map non-printable US ASCII to '\xhh' */
1260 elif ch < ' ' or ch == 0x7F:
1261 out.write('\\x')
1262 out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
1263 out.write(hexdigits[ord(ch) & 0x000F])
1264
1265 # Copy ASCII characters as-is
1266 elif ord(ch) < 0x7F:
1267 out.write(ch)
1268
1269 # Non-ASCII characters
1270 else:
Victor Stinner150016f2010-05-19 23:04:56 +00001271 ucs = ch
Antoine Pitroub41e1282010-09-08 20:57:48 +00001272 ch2 = None
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001273 if sys.maxunicode < 0x10000:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001274 # If sizeof(Py_UNICODE) is 2 here (in gdb), join
1275 # surrogate pairs before calling _unichr_is_printable.
Victor Stinner150016f2010-05-19 23:04:56 +00001276 if (i < len(proxy)
1277 and 0xD800 <= ord(ch) < 0xDC00 \
1278 and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001279 ch2 = proxy[i]
Antoine Pitroub41e1282010-09-08 20:57:48 +00001280 ucs = ch + ch2
Victor Stinner150016f2010-05-19 23:04:56 +00001281 i += 1
Victor Stinner150016f2010-05-19 23:04:56 +00001282
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001283 # Unfortuately, Python 2's unicode type doesn't seem
1284 # to expose the "isprintable" method
Victor Stinner150016f2010-05-19 23:04:56 +00001285 printable = _unichr_is_printable(ucs)
1286 if printable:
1287 try:
1288 ucs.encode(ENCODING)
1289 except UnicodeEncodeError:
1290 printable = False
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001291
1292 # Map Unicode whitespace and control characters
1293 # (categories Z* and C* except ASCII space)
Victor Stinner150016f2010-05-19 23:04:56 +00001294 if not printable:
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001295 if ch2 is not None:
1296 # Match Python 3's representation of non-printable
1297 # wide characters.
1298 code = (ord(ch) & 0x03FF) << 10
1299 code |= ord(ch2) & 0x03FF
1300 code += 0x00010000
1301 else:
1302 code = ord(ucs)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001303
1304 # Map 8-bit characters to '\\xhh'
Victor Stinner150016f2010-05-19 23:04:56 +00001305 if code <= 0xff:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001306 out.write('\\x')
Victor Stinner150016f2010-05-19 23:04:56 +00001307 out.write(hexdigits[(code >> 4) & 0x000F])
1308 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001309 # Map 21-bit characters to '\U00xxxxxx'
Victor Stinner150016f2010-05-19 23:04:56 +00001310 elif code >= 0x10000:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001311 out.write('\\U')
Victor Stinner150016f2010-05-19 23:04:56 +00001312 out.write(hexdigits[(code >> 28) & 0x0000000F])
1313 out.write(hexdigits[(code >> 24) & 0x0000000F])
1314 out.write(hexdigits[(code >> 20) & 0x0000000F])
1315 out.write(hexdigits[(code >> 16) & 0x0000000F])
1316 out.write(hexdigits[(code >> 12) & 0x0000000F])
1317 out.write(hexdigits[(code >> 8) & 0x0000000F])
1318 out.write(hexdigits[(code >> 4) & 0x0000000F])
1319 out.write(hexdigits[code & 0x0000000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001320 # Map 16-bit characters to '\uxxxx'
1321 else:
1322 out.write('\\u')
Victor Stinner150016f2010-05-19 23:04:56 +00001323 out.write(hexdigits[(code >> 12) & 0x000F])
1324 out.write(hexdigits[(code >> 8) & 0x000F])
1325 out.write(hexdigits[(code >> 4) & 0x000F])
1326 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001327 else:
1328 # Copy characters as-is
1329 out.write(ch)
Antoine Pitroub41e1282010-09-08 20:57:48 +00001330 if ch2 is not None:
Victor Stinner150016f2010-05-19 23:04:56 +00001331 out.write(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001332
1333 out.write(quote)
1334
1335
Victor Stinner61108332017-02-01 16:29:54 +01001336class wrapperobject(PyObjectPtr):
1337 _typename = 'wrapperobject'
1338
1339 def safe_name(self):
1340 try:
1341 name = self.field('descr')['d_base']['name'].string()
1342 return repr(name)
1343 except (NullPyObjectPtr, RuntimeError):
1344 return '<unknown name>'
1345
1346 def safe_tp_name(self):
1347 try:
1348 return self.field('self')['ob_type']['tp_name'].string()
1349 except (NullPyObjectPtr, RuntimeError):
1350 return '<unknown tp_name>'
1351
1352 def safe_self_addresss(self):
1353 try:
1354 address = long(self.field('self'))
1355 return '%#x' % address
1356 except (NullPyObjectPtr, RuntimeError):
1357 return '<failed to get self address>'
1358
1359 def proxyval(self, visited):
1360 name = self.safe_name()
1361 tp_name = self.safe_tp_name()
1362 self_address = self.safe_self_addresss()
1363 return ("<method-wrapper %s of %s object at %s>"
1364 % (name, tp_name, self_address))
1365
1366 def write_repr(self, out, visited):
1367 proxy = self.proxyval(visited)
1368 out.write(proxy)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001369
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001370
1371def int_from_int(gdbval):
1372 return int(str(gdbval))
1373
1374
1375def stringify(val):
1376 # TODO: repr() puts everything on one line; pformat can be nicer, but
1377 # can lead to v.long results; this function isolates the choice
1378 if True:
1379 return repr(val)
1380 else:
1381 from pprint import pformat
1382 return pformat(val)
1383
1384
1385class PyObjectPtrPrinter:
1386 "Prints a (PyObject*)"
1387
1388 def __init__ (self, gdbval):
1389 self.gdbval = gdbval
1390
1391 def to_string (self):
1392 pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1393 if True:
1394 return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1395 else:
1396 # Generate full proxy value then stringify it.
1397 # Doing so could be expensive
1398 proxyval = pyop.proxyval(set())
1399 return stringify(proxyval)
1400
1401def pretty_printer_lookup(gdbval):
1402 type = gdbval.type.unqualified()
Victor Stinner61108332017-02-01 16:29:54 +01001403 if type.code != gdb.TYPE_CODE_PTR:
1404 return None
1405
1406 type = type.target().unqualified()
1407 t = str(type)
1408 if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
1409 return PyObjectPtrPrinter(gdbval)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001410
1411"""
1412During development, I've been manually invoking the code in this way:
1413(gdb) python
1414
1415import sys
1416sys.path.append('/home/david/coding/python-gdb')
1417import libpython
1418end
1419
1420then reloading it after each edit like this:
1421(gdb) python reload(libpython)
1422
1423The following code should ensure that the prettyprinter is registered
1424if the code is autoloaded by gdb when visiting libpython.so, provided
1425that this python file is installed to the same path as the library (or its
1426.debug file) plus a "-gdb.py" suffix, e.g:
1427 /usr/lib/libpython2.6.so.1.0-gdb.py
1428 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1429"""
1430def register (obj):
Benjamin Petersonb29614e2012-10-09 11:16:03 -04001431 if obj is None:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001432 obj = gdb
1433
1434 # Wire up the pretty-printer
1435 obj.pretty_printers.append(pretty_printer_lookup)
1436
1437register (gdb.current_objfile ())
1438
1439
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001440
1441# Unfortunately, the exact API exposed by the gdb module varies somewhat
1442# from build to build
1443# See http://bugs.python.org/issue8279?#msg102276
1444
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001445class Frame(object):
1446 '''
1447 Wrapper for gdb.Frame, adding various methods
1448 '''
1449 def __init__(self, gdbframe):
1450 self._gdbframe = gdbframe
1451
1452 def older(self):
1453 older = self._gdbframe.older()
1454 if older:
1455 return Frame(older)
1456 else:
1457 return None
1458
1459 def newer(self):
1460 newer = self._gdbframe.newer()
1461 if newer:
1462 return Frame(newer)
1463 else:
1464 return None
1465
1466 def select(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001467 '''If supported, select this frame and return True; return False if unsupported
1468
1469 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1470 onwards, but absent on Ubuntu buildbot'''
1471 if not hasattr(self._gdbframe, 'select'):
1472 print ('Unable to select frame: '
1473 'this build of gdb does not expose a gdb.Frame.select method')
1474 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001475 self._gdbframe.select()
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001476 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001477
1478 def get_index(self):
1479 '''Calculate index of frame, starting at 0 for the newest frame within
1480 this thread'''
1481 index = 0
1482 # Go down until you reach the newest frame:
1483 iter_frame = self
1484 while iter_frame.newer():
1485 index += 1
1486 iter_frame = iter_frame.newer()
1487 return index
1488
David Malcolm8d37ffa2012-06-27 14:15:34 -04001489 # We divide frames into:
1490 # - "python frames":
1491 # - "bytecode frames" i.e. PyEval_EvalFrameEx
1492 # - "other python frames": things that are of interest from a python
1493 # POV, but aren't bytecode (e.g. GC, GIL)
1494 # - everything else
1495
1496 def is_python_frame(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001497 '''Is this a _PyEval_EvalFrameDefault frame, or some other important
David Malcolm8d37ffa2012-06-27 14:15:34 -04001498 frame? (see is_other_python_frame for what "important" means in this
1499 context)'''
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001500 if self.is_evalframe():
David Malcolm8d37ffa2012-06-27 14:15:34 -04001501 return True
1502 if self.is_other_python_frame():
1503 return True
1504 return False
1505
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001506 def is_evalframe(self):
1507 '''Is this a _PyEval_EvalFrameDefault frame?'''
1508 if self._gdbframe.name() == EVALFRAME:
Victor Stinner50eb60e2010-04-20 22:32:07 +00001509 '''
1510 I believe we also need to filter on the inline
1511 struct frame_id.inline_depth, only regarding frames with
1512 an inline depth of 0 as actually being this function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001513
Victor Stinner50eb60e2010-04-20 22:32:07 +00001514 So we reject those with type gdb.INLINE_FRAME
1515 '''
1516 if self._gdbframe.type() == gdb.NORMAL_FRAME:
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001517 # We have a _PyEval_EvalFrameDefault frame:
Victor Stinner50eb60e2010-04-20 22:32:07 +00001518 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001519
1520 return False
1521
David Malcolm8d37ffa2012-06-27 14:15:34 -04001522 def is_other_python_frame(self):
1523 '''Is this frame worth displaying in python backtraces?
1524 Examples:
1525 - waiting on the GIL
1526 - garbage-collecting
1527 - within a CFunction
1528 If it is, return a descriptive string
1529 For other frames, return False
1530 '''
1531 if self.is_waiting_for_gil():
1532 return 'Waiting for the GIL'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001533
1534 if self.is_gc_collect():
David Malcolm8d37ffa2012-06-27 14:15:34 -04001535 return 'Garbage-collecting'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001536
1537 # Detect invocations of PyCFunction instances:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001538 frame = self._gdbframe
1539 caller = frame.name()
Victor Stinnereae64fd2016-11-22 22:53:18 +01001540 if not caller:
1541 return False
1542
Victor Stinnerfa025f12017-01-18 17:20:01 +01001543 if caller in ('_PyCFunction_FastCallDict',
1544 '_PyCFunction_FastCallKeywords'):
INADA Naoki5566bbb2017-02-03 07:43:03 +09001545 arg_name = 'func'
Victor Stinnereae64fd2016-11-22 22:53:18 +01001546 # Within that frame:
1547 # "func" is the local containing the PyObject* of the
1548 # PyCFunctionObject instance
1549 # "f" is the same value, but cast to (PyCFunctionObject*)
1550 # "self" is the (PyObject*) of the 'self'
1551 try:
1552 # Use the prettyprinter for the func:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001553 func = frame.read_var(arg_name)
Victor Stinnereae64fd2016-11-22 22:53:18 +01001554 return str(func)
Victor Stinner019d33b2018-06-14 16:28:07 +02001555 except ValueError:
1556 return ('PyCFunction invocation (unable to read %s: '
1557 'missing debuginfos?)' % arg_name)
Victor Stinnereae64fd2016-11-22 22:53:18 +01001558 except RuntimeError:
Victor Stinnerfa025f12017-01-18 17:20:01 +01001559 return 'PyCFunction invocation (unable to read %s)' % arg_name
David Malcolm8d37ffa2012-06-27 14:15:34 -04001560
Victor Stinner61108332017-02-01 16:29:54 +01001561 if caller == 'wrapper_call':
Victor Stinner019d33b2018-06-14 16:28:07 +02001562 arg_name = 'wp'
Victor Stinner61108332017-02-01 16:29:54 +01001563 try:
Victor Stinner019d33b2018-06-14 16:28:07 +02001564 func = frame.read_var(arg_name)
Victor Stinner61108332017-02-01 16:29:54 +01001565 return str(func)
Victor Stinner019d33b2018-06-14 16:28:07 +02001566 except ValueError:
1567 return ('<wrapper_call invocation (unable to read %s: '
1568 'missing debuginfos?)>' % arg_name)
Victor Stinner61108332017-02-01 16:29:54 +01001569 except RuntimeError:
Victor Stinner019d33b2018-06-14 16:28:07 +02001570 return '<wrapper_call invocation (unable to read %s)>' % arg_name
Victor Stinner61108332017-02-01 16:29:54 +01001571
David Malcolm8d37ffa2012-06-27 14:15:34 -04001572 # This frame isn't worth reporting:
1573 return False
1574
1575 def is_waiting_for_gil(self):
1576 '''Is this frame waiting on the GIL?'''
1577 # This assumes the _POSIX_THREADS version of Python/ceval_gil.h:
1578 name = self._gdbframe.name()
1579 if name:
David Malcolmd08b2102013-05-06 14:47:15 -04001580 return 'pthread_cond_timedwait' in name
David Malcolm8d37ffa2012-06-27 14:15:34 -04001581
1582 def is_gc_collect(self):
Ezio Melotti3f5db392013-01-27 06:20:14 +02001583 '''Is this frame "collect" within the garbage-collector?'''
David Malcolm8d37ffa2012-06-27 14:15:34 -04001584 return self._gdbframe.name() == 'collect'
1585
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001586 def get_pyop(self):
1587 try:
1588 f = self._gdbframe.read_var('f')
Victor Stinnerd2084162011-12-19 13:42:24 +01001589 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1590 if not frame.is_optimized_out():
1591 return frame
1592 # gdb is unable to get the "f" argument of PyEval_EvalFrameEx()
1593 # because it was "optimized out". Try to get "f" from the frame
1594 # of the caller, PyEval_EvalCodeEx().
1595 orig_frame = frame
1596 caller = self._gdbframe.older()
1597 if caller:
1598 f = caller.read_var('f')
1599 frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1600 if not frame.is_optimized_out():
1601 return frame
1602 return orig_frame
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001603 except ValueError:
1604 return None
1605
1606 @classmethod
1607 def get_selected_frame(cls):
1608 _gdbframe = gdb.selected_frame()
1609 if _gdbframe:
1610 return Frame(_gdbframe)
1611 return None
1612
1613 @classmethod
1614 def get_selected_python_frame(cls):
David Malcolm8d37ffa2012-06-27 14:15:34 -04001615 '''Try to obtain the Frame for the python-related code in the selected
1616 frame, or None'''
Victor Stinner610f5d72016-12-16 10:00:39 +01001617 try:
1618 frame = cls.get_selected_frame()
1619 except gdb.error:
1620 # No frame: Python didn't start yet
1621 return None
David Malcolm8d37ffa2012-06-27 14:15:34 -04001622
1623 while frame:
1624 if frame.is_python_frame():
1625 return frame
1626 frame = frame.older()
1627
1628 # Not found:
1629 return None
1630
1631 @classmethod
1632 def get_selected_bytecode_frame(cls):
1633 '''Try to obtain the Frame for the python bytecode interpreter in the
1634 selected GDB frame, or None'''
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001635 frame = cls.get_selected_frame()
1636
1637 while frame:
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001638 if frame.is_evalframe():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001639 return frame
1640 frame = frame.older()
1641
1642 # Not found:
1643 return None
1644
1645 def print_summary(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001646 if self.is_evalframe():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001647 pyop = self.get_pyop()
1648 if pyop:
Victor Stinner0e5a41b2010-08-17 22:49:25 +00001649 line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1650 write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
Victor Stinnerd2084162011-12-19 13:42:24 +01001651 if not pyop.is_optimized_out():
1652 line = pyop.current_line()
1653 if line is not None:
1654 sys.stdout.write(' %s\n' % line.strip())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001655 else:
1656 sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1657 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001658 info = self.is_other_python_frame()
1659 if info:
1660 sys.stdout.write('#%i %s\n' % (self.get_index(), info))
1661 else:
1662 sys.stdout.write('#%i\n' % self.get_index())
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001663
Victor Stinnere670c882011-05-13 17:40:15 +02001664 def print_traceback(self):
Łukasz Langa5fe59f82017-08-21 16:40:29 -07001665 if self.is_evalframe():
Victor Stinnere670c882011-05-13 17:40:15 +02001666 pyop = self.get_pyop()
1667 if pyop:
1668 pyop.print_traceback()
Victor Stinnerd2084162011-12-19 13:42:24 +01001669 if not pyop.is_optimized_out():
1670 line = pyop.current_line()
1671 if line is not None:
1672 sys.stdout.write(' %s\n' % line.strip())
Victor Stinnere670c882011-05-13 17:40:15 +02001673 else:
1674 sys.stdout.write(' (unable to read python frame information)\n')
1675 else:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001676 info = self.is_other_python_frame()
1677 if info:
1678 sys.stdout.write(' %s\n' % info)
1679 else:
1680 sys.stdout.write(' (not a python frame)\n')
Victor Stinnere670c882011-05-13 17:40:15 +02001681
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001682class PyList(gdb.Command):
1683 '''List the current Python source code, if any
1684
1685 Use
1686 py-list START
1687 to list at a different line number within the python source.
1688
1689 Use
1690 py-list START, END
1691 to list a specific range of lines within the python source.
1692 '''
1693
1694 def __init__(self):
1695 gdb.Command.__init__ (self,
1696 "py-list",
1697 gdb.COMMAND_FILES,
1698 gdb.COMPLETE_NONE)
1699
1700
1701 def invoke(self, args, from_tty):
1702 import re
1703
1704 start = None
1705 end = None
1706
1707 m = re.match(r'\s*(\d+)\s*', args)
1708 if m:
1709 start = int(m.group(0))
1710 end = start + 10
1711
1712 m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1713 if m:
1714 start, end = map(int, m.groups())
1715
David Malcolm8d37ffa2012-06-27 14:15:34 -04001716 # py-list requires an actual PyEval_EvalFrameEx frame:
1717 frame = Frame.get_selected_bytecode_frame()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001718 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001719 print('Unable to locate gdb frame for python bytecode interpreter')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001720 return
1721
1722 pyop = frame.get_pyop()
Victor Stinnerd2084162011-12-19 13:42:24 +01001723 if not pyop or pyop.is_optimized_out():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001724 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001725 return
1726
1727 filename = pyop.filename()
1728 lineno = pyop.current_line_num()
1729
1730 if start is None:
1731 start = lineno - 5
1732 end = lineno + 5
1733
1734 if start<1:
1735 start = 1
1736
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001737 try:
1738 f = open(os_fsencode(filename), 'r')
1739 except IOError as err:
1740 sys.stdout.write('Unable to open %s: %s\n'
1741 % (filename, err))
1742 return
1743 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001744 all_lines = f.readlines()
1745 # start and end are 1-based, all_lines is 0-based;
1746 # so [start-1:end] as a python slice gives us [start, end] as a
1747 # closed interval
1748 for i, line in enumerate(all_lines[start-1:end]):
1749 linestr = str(i+start)
1750 # Highlight current line:
1751 if i + start == lineno:
1752 linestr = '>' + linestr
1753 sys.stdout.write('%4s %s' % (linestr, line))
1754
1755
1756# ...and register the command:
1757PyList()
1758
1759def move_in_stack(move_up):
1760 '''Move up or down the stack (for the py-up/py-down command)'''
1761 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001762 if not frame:
1763 print('Unable to locate python frame')
1764 return
1765
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001766 while frame:
1767 if move_up:
1768 iter_frame = frame.older()
1769 else:
1770 iter_frame = frame.newer()
1771
1772 if not iter_frame:
1773 break
1774
David Malcolm8d37ffa2012-06-27 14:15:34 -04001775 if iter_frame.is_python_frame():
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001776 # Result:
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001777 if iter_frame.select():
1778 iter_frame.print_summary()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001779 return
1780
1781 frame = iter_frame
1782
1783 if move_up:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001784 print('Unable to find an older python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001785 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001786 print('Unable to find a newer python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001787
1788class PyUp(gdb.Command):
1789 'Select and print the python stack frame that called this one (if any)'
1790 def __init__(self):
1791 gdb.Command.__init__ (self,
1792 "py-up",
1793 gdb.COMMAND_STACK,
1794 gdb.COMPLETE_NONE)
1795
1796
1797 def invoke(self, args, from_tty):
1798 move_in_stack(move_up=True)
1799
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001800class PyDown(gdb.Command):
1801 'Select and print the python stack frame called by this one (if any)'
1802 def __init__(self):
1803 gdb.Command.__init__ (self,
1804 "py-down",
1805 gdb.COMMAND_STACK,
1806 gdb.COMPLETE_NONE)
1807
1808
1809 def invoke(self, args, from_tty):
1810 move_in_stack(move_up=False)
1811
Victor Stinner50eb60e2010-04-20 22:32:07 +00001812# Not all builds of gdb have gdb.Frame.select
1813if hasattr(gdb.Frame, 'select'):
1814 PyUp()
1815 PyDown()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001816
Victor Stinnere670c882011-05-13 17:40:15 +02001817class PyBacktraceFull(gdb.Command):
1818 'Display the current python frame and all the frames within its call stack (if any)'
1819 def __init__(self):
1820 gdb.Command.__init__ (self,
1821 "py-bt-full",
1822 gdb.COMMAND_STACK,
1823 gdb.COMPLETE_NONE)
1824
1825
1826 def invoke(self, args, from_tty):
1827 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001828 if not frame:
1829 print('Unable to locate python frame')
1830 return
1831
Victor Stinnere670c882011-05-13 17:40:15 +02001832 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001833 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001834 frame.print_summary()
1835 frame = frame.older()
1836
1837PyBacktraceFull()
1838
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001839class PyBacktrace(gdb.Command):
1840 'Display the current python frame and all the frames within its call stack (if any)'
1841 def __init__(self):
1842 gdb.Command.__init__ (self,
1843 "py-bt",
1844 gdb.COMMAND_STACK,
1845 gdb.COMPLETE_NONE)
1846
1847
1848 def invoke(self, args, from_tty):
1849 frame = Frame.get_selected_python_frame()
Victor Stinner610f5d72016-12-16 10:00:39 +01001850 if not frame:
1851 print('Unable to locate python frame')
1852 return
1853
1854 sys.stdout.write('Traceback (most recent call first):\n')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001855 while frame:
David Malcolm8d37ffa2012-06-27 14:15:34 -04001856 if frame.is_python_frame():
Victor Stinnere670c882011-05-13 17:40:15 +02001857 frame.print_traceback()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001858 frame = frame.older()
1859
1860PyBacktrace()
1861
1862class PyPrint(gdb.Command):
1863 'Look up the given python variable name, and print it'
1864 def __init__(self):
1865 gdb.Command.__init__ (self,
1866 "py-print",
1867 gdb.COMMAND_DATA,
1868 gdb.COMPLETE_NONE)
1869
1870
1871 def invoke(self, args, from_tty):
1872 name = str(args)
1873
1874 frame = Frame.get_selected_python_frame()
1875 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001876 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001877 return
1878
1879 pyop_frame = frame.get_pyop()
1880 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001881 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001882 return
1883
1884 pyop_var, scope = pyop_frame.get_var_by_name(name)
1885
1886 if pyop_var:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001887 print('%s %r = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001888 % (scope,
1889 name,
1890 pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1891 else:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001892 print('%r not found' % name)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001893
1894PyPrint()
1895
1896class PyLocals(gdb.Command):
1897 'Look up the given python variable name, and print it'
1898 def __init__(self):
1899 gdb.Command.__init__ (self,
1900 "py-locals",
1901 gdb.COMMAND_DATA,
1902 gdb.COMPLETE_NONE)
1903
1904
1905 def invoke(self, args, from_tty):
1906 name = str(args)
1907
1908 frame = Frame.get_selected_python_frame()
1909 if not frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001910 print('Unable to locate python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001911 return
1912
1913 pyop_frame = frame.get_pyop()
1914 if not pyop_frame:
Antoine Pitroue50240c2013-11-23 17:40:36 +01001915 print('Unable to read information on python frame')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001916 return
1917
1918 for pyop_name, pyop_value in pyop_frame.iter_locals():
Antoine Pitroue50240c2013-11-23 17:40:36 +01001919 print('%s = %s'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001920 % (pyop_name.proxyval(set()),
1921 pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1922
1923PyLocals()