blob: ca1dc60cc3d5945bd7861f2e8a304de03b9d39a3 [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'''
43from __future__ import with_statement
44import gdb
Victor Stinner150016f2010-05-19 23:04:56 +000045import locale
Georg Brandlb639c142010-07-14 08:54:40 +000046import sys
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000047
48# Look up the gdb.Type for some standard types:
49_type_char_ptr = gdb.lookup_type('char').pointer() # char*
50_type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char*
51_type_void_ptr = gdb.lookup_type('void').pointer() # void*
52_type_size_t = gdb.lookup_type('size_t')
53
54SIZEOF_VOID_P = _type_void_ptr.sizeof
55
56
57Py_TPFLAGS_HEAPTYPE = (1L << 9)
58
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000059Py_TPFLAGS_LONG_SUBCLASS = (1L << 24)
60Py_TPFLAGS_LIST_SUBCLASS = (1L << 25)
61Py_TPFLAGS_TUPLE_SUBCLASS = (1L << 26)
Martin v. Löwis5ae68102010-04-21 22:38:42 +000062Py_TPFLAGS_BYTES_SUBCLASS = (1L << 27)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000063Py_TPFLAGS_UNICODE_SUBCLASS = (1L << 28)
64Py_TPFLAGS_DICT_SUBCLASS = (1L << 29)
65Py_TPFLAGS_BASE_EXC_SUBCLASS = (1L << 30)
66Py_TPFLAGS_TYPE_SUBCLASS = (1L << 31)
67
68
69MAX_OUTPUT_LEN=1024
70
Martin v. Löwis5ae68102010-04-21 22:38:42 +000071hexdigits = "0123456789abcdef"
72
Victor Stinner150016f2010-05-19 23:04:56 +000073ENCODING = locale.getpreferredencoding()
Martin v. Löwis5ae68102010-04-21 22:38:42 +000074
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000075class NullPyObjectPtr(RuntimeError):
76 pass
77
78
79def safety_limit(val):
80 # Given a integer value from the process being debugged, limit it to some
81 # safety threshold so that arbitrary breakage within said process doesn't
82 # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
83 return min(val, 1000)
84
85
86def safe_range(val):
87 # As per range, but don't trust the value too much: cap it to a safety
88 # threshold in case the data was corrupted
89 return xrange(safety_limit(val))
90
Victor Stinner0e5a41b2010-08-17 22:49:25 +000091def write_unicode(file, text):
92 # Write a byte or unicode string to file. Unicode strings are encoded to
93 # ENCODING encoding with 'backslashreplace' error handler to avoid
94 # UnicodeEncodeError.
95 if isinstance(text, unicode):
96 text = text.encode(ENCODING, 'backslashreplace')
97 file.write(text)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +000098
Victor Stinner6ffbee72010-10-17 19:35:30 +000099def os_fsencode(filename):
100 if not isinstance(filename, unicode):
101 return filename
102 encoding = sys.getfilesystemencoding()
103 if encoding == 'mbcs':
104 # mbcs doesn't support surrogateescape
105 return filename.encode(encoding)
106 encoded = []
107 for char in filename:
108 # surrogateescape error handler
109 if 0xDC80 <= ord(char) <= 0xDCFF:
110 byte = chr(ord(char) - 0xDC00)
111 else:
112 byte = char.encode(encoding)
113 encoded.append(byte)
114 return ''.join(encoded)
115
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000116class StringTruncated(RuntimeError):
117 pass
118
119class TruncatedStringIO(object):
120 '''Similar to cStringIO, but can truncate the output by raising a
121 StringTruncated exception'''
122 def __init__(self, maxlen=None):
123 self._val = ''
124 self.maxlen = maxlen
125
126 def write(self, data):
127 if self.maxlen:
128 if len(data) + len(self._val) > self.maxlen:
129 # Truncation:
130 self._val += data[0:self.maxlen - len(self._val)]
131 raise StringTruncated()
132
133 self._val += data
134
135 def getvalue(self):
136 return self._val
137
138class PyObjectPtr(object):
139 """
140 Class wrapping a gdb.Value that's a either a (PyObject*) within the
Victor Stinner67df3a42010-04-21 13:53:05 +0000141 inferior process, or some subclass pointer e.g. (PyBytesObject*)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000142
143 There will be a subclass for every refined PyObject type that we care
144 about.
145
146 Note that at every stage the underlying pointer could be NULL, point
147 to corrupt data, etc; this is the debugger, after all.
148 """
149 _typename = 'PyObject'
150
151 def __init__(self, gdbval, cast_to=None):
152 if cast_to:
153 self._gdbval = gdbval.cast(cast_to)
154 else:
155 self._gdbval = gdbval
156
157 def field(self, name):
158 '''
159 Get the gdb.Value for the given field within the PyObject, coping with
160 some python 2 versus python 3 differences.
161
162 Various libpython types are defined using the "PyObject_HEAD" and
163 "PyObject_VAR_HEAD" macros.
164
165 In Python 2, this these are defined so that "ob_type" and (for a var
166 object) "ob_size" are fields of the type in question.
167
168 In Python 3, this is defined as an embedded PyVarObject type thus:
169 PyVarObject ob_base;
170 so that the "ob_size" field is located insize the "ob_base" field, and
171 the "ob_type" is most easily accessed by casting back to a (PyObject*).
172 '''
173 if self.is_null():
174 raise NullPyObjectPtr(self)
175
176 if name == 'ob_type':
177 pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
178 return pyo_ptr.dereference()[name]
179
180 if name == 'ob_size':
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000181 pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
182 return pyo_ptr.dereference()[name]
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000183
184 # General case: look it up inside the object:
185 return self._gdbval.dereference()[name]
186
187 def pyop_field(self, name):
188 '''
189 Get a PyObjectPtr for the given PyObject* field within this PyObject,
190 coping with some python 2 versus python 3 differences.
191 '''
192 return PyObjectPtr.from_pyobject_ptr(self.field(name))
193
194 def write_field_repr(self, name, out, visited):
195 '''
196 Extract the PyObject* field named "name", and write its representation
197 to file-like object "out"
198 '''
199 field_obj = self.pyop_field(name)
200 field_obj.write_repr(out, visited)
201
202 def get_truncated_repr(self, maxlen):
203 '''
204 Get a repr-like string for the data, but truncate it at "maxlen" bytes
205 (ending the object graph traversal as soon as you do)
206 '''
207 out = TruncatedStringIO(maxlen)
208 try:
209 self.write_repr(out, set())
210 except StringTruncated:
211 # Truncation occurred:
212 return out.getvalue() + '...(truncated)'
213
214 # No truncation occurred:
215 return out.getvalue()
216
217 def type(self):
218 return PyTypeObjectPtr(self.field('ob_type'))
219
220 def is_null(self):
221 return 0 == long(self._gdbval)
222
223 def is_optimized_out(self):
224 '''
225 Is the value of the underlying PyObject* visible to the debugger?
226
227 This can vary with the precise version of the compiler used to build
228 Python, and the precise version of gdb.
229
230 See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
231 PyEval_EvalFrameEx's "f"
232 '''
233 return self._gdbval.is_optimized_out
234
235 def safe_tp_name(self):
236 try:
237 return self.type().field('tp_name').string()
238 except NullPyObjectPtr:
239 # NULL tp_name?
240 return 'unknown'
241 except RuntimeError:
242 # Can't even read the object at all?
243 return 'unknown'
244
245 def proxyval(self, visited):
246 '''
247 Scrape a value from the inferior process, and try to represent it
248 within the gdb process, whilst (hopefully) avoiding crashes when
249 the remote data is corrupt.
250
251 Derived classes will override this.
252
253 For example, a PyIntObject* with ob_ival 42 in the inferior process
254 should result in an int(42) in this process.
255
256 visited: a set of all gdb.Value pyobject pointers already visited
257 whilst generating this value (to guard against infinite recursion when
258 visiting object graphs with loops). Analogous to Py_ReprEnter and
259 Py_ReprLeave
260 '''
261
262 class FakeRepr(object):
263 """
264 Class representing a non-descript PyObject* value in the inferior
265 process for when we don't have a custom scraper, intended to have
266 a sane repr().
267 """
268
269 def __init__(self, tp_name, address):
270 self.tp_name = tp_name
271 self.address = address
272
273 def __repr__(self):
274 # For the NULL pointer, we have no way of knowing a type, so
275 # special-case it as per
276 # http://bugs.python.org/issue8032#msg100882
277 if self.address == 0:
278 return '0x0'
279 return '<%s at remote 0x%x>' % (self.tp_name, self.address)
280
281 return FakeRepr(self.safe_tp_name(),
282 long(self._gdbval))
283
284 def write_repr(self, out, visited):
285 '''
286 Write a string representation of the value scraped from the inferior
287 process to "out", a file-like object.
288 '''
289 # Default implementation: generate a proxy value and write its repr
290 # However, this could involve a lot of work for complicated objects,
291 # so for derived classes we specialize this
292 return out.write(repr(self.proxyval(visited)))
293
294 @classmethod
295 def subclass_from_type(cls, t):
296 '''
297 Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
298 (PyTypeObject*), determine the corresponding subclass of PyObjectPtr
299 to use
300
301 Ideally, we would look up the symbols for the global types, but that
302 isn't working yet:
303 (gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
304 Traceback (most recent call last):
305 File "<string>", line 1, in <module>
306 NotImplementedError: Symbol type not yet supported in Python scripts.
307 Error while executing Python code.
308
309 For now, we use tp_flags, after doing some string comparisons on the
310 tp_name for some special-cases that don't seem to be visible through
311 flags
312 '''
313 try:
314 tp_name = t.field('tp_name').string()
315 tp_flags = int(t.field('tp_flags'))
316 except RuntimeError:
317 # Handle any kind of error e.g. NULL ptrs by simply using the base
318 # class
319 return cls
320
321 #print 'tp_flags = 0x%08x' % tp_flags
322 #print 'tp_name = %r' % tp_name
323
324 name_map = {'bool': PyBoolObjectPtr,
325 'classobj': PyClassObjectPtr,
326 'instance': PyInstanceObjectPtr,
327 'NoneType': PyNoneStructPtr,
328 'frame': PyFrameObjectPtr,
329 'set' : PySetObjectPtr,
330 'frozenset' : PySetObjectPtr,
331 'builtin_function_or_method' : PyCFunctionObjectPtr,
332 }
333 if tp_name in name_map:
334 return name_map[tp_name]
335
336 if tp_flags & Py_TPFLAGS_HEAPTYPE:
337 return HeapTypeObjectPtr
338
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000339 if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
340 return PyLongObjectPtr
341 if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
342 return PyListObjectPtr
343 if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
344 return PyTupleObjectPtr
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000345 if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
Victor Stinner67df3a42010-04-21 13:53:05 +0000346 return PyBytesObjectPtr
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000347 if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
348 return PyUnicodeObjectPtr
349 if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
350 return PyDictObjectPtr
351 if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
352 return PyBaseExceptionObjectPtr
353 #if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
354 # return PyTypeObjectPtr
355
356 # Use the base class:
357 return cls
358
359 @classmethod
360 def from_pyobject_ptr(cls, gdbval):
361 '''
362 Try to locate the appropriate derived class dynamically, and cast
363 the pointer accordingly.
364 '''
365 try:
366 p = PyObjectPtr(gdbval)
367 cls = cls.subclass_from_type(p.type())
368 return cls(gdbval, cast_to=cls.get_gdb_type())
369 except RuntimeError:
370 # Handle any kind of error e.g. NULL ptrs by simply using the base
371 # class
372 pass
373 return cls(gdbval)
374
375 @classmethod
376 def get_gdb_type(cls):
377 return gdb.lookup_type(cls._typename).pointer()
378
379 def as_address(self):
380 return long(self._gdbval)
381
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000382class PyVarObjectPtr(PyObjectPtr):
383 _typename = 'PyVarObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000384
385class ProxyAlreadyVisited(object):
386 '''
387 Placeholder proxy to use when protecting against infinite recursion due to
388 loops in the object graph.
389
390 Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
391 '''
392 def __init__(self, rep):
393 self._rep = rep
394
395 def __repr__(self):
396 return self._rep
397
398
399def _write_instance_repr(out, visited, name, pyop_attrdict, address):
400 '''Shared code for use by old-style and new-style classes:
401 write a representation to file-like object "out"'''
402 out.write('<')
403 out.write(name)
404
405 # Write dictionary of instance attributes:
406 if isinstance(pyop_attrdict, PyDictObjectPtr):
407 out.write('(')
408 first = True
409 for pyop_arg, pyop_val in pyop_attrdict.iteritems():
410 if not first:
411 out.write(', ')
412 first = False
413 out.write(pyop_arg.proxyval(visited))
414 out.write('=')
415 pyop_val.write_repr(out, visited)
416 out.write(')')
417 out.write(' at remote 0x%x>' % address)
418
419
420class InstanceProxy(object):
421
422 def __init__(self, cl_name, attrdict, address):
423 self.cl_name = cl_name
424 self.attrdict = attrdict
425 self.address = address
426
427 def __repr__(self):
428 if isinstance(self.attrdict, dict):
429 kwargs = ', '.join(["%s=%r" % (arg, val)
430 for arg, val in self.attrdict.iteritems()])
431 return '<%s(%s) at remote 0x%x>' % (self.cl_name,
432 kwargs, self.address)
433 else:
434 return '<%s at remote 0x%x>' % (self.cl_name,
435 self.address)
436
437def _PyObject_VAR_SIZE(typeobj, nitems):
438 return ( ( typeobj.field('tp_basicsize') +
439 nitems * typeobj.field('tp_itemsize') +
440 (SIZEOF_VOID_P - 1)
441 ) & ~(SIZEOF_VOID_P - 1)
442 ).cast(_type_size_t)
443
444class HeapTypeObjectPtr(PyObjectPtr):
445 _typename = 'PyObject'
446
447 def get_attr_dict(self):
448 '''
449 Get the PyDictObject ptr representing the attribute dictionary
450 (or None if there's a problem)
451 '''
452 try:
453 typeobj = self.type()
454 dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
455 if dictoffset != 0:
456 if dictoffset < 0:
457 type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
458 tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
459 if tsize < 0:
460 tsize = -tsize
461 size = _PyObject_VAR_SIZE(typeobj, tsize)
462 dictoffset += size
463 assert dictoffset > 0
464 assert dictoffset % SIZEOF_VOID_P == 0
465
466 dictptr = self._gdbval.cast(_type_char_ptr) + dictoffset
467 PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
468 dictptr = dictptr.cast(PyObjectPtrPtr)
469 return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
470 except RuntimeError:
471 # Corrupt data somewhere; fail safe
472 pass
473
474 # Not found, or some kind of error:
475 return None
476
477 def proxyval(self, visited):
478 '''
479 Support for new-style classes.
480
481 Currently we just locate the dictionary using a transliteration to
482 python of _PyObject_GetDictPtr, ignoring descriptors
483 '''
484 # Guard against infinite loops:
485 if self.as_address() in visited:
486 return ProxyAlreadyVisited('<...>')
487 visited.add(self.as_address())
488
489 pyop_attr_dict = self.get_attr_dict()
490 if pyop_attr_dict:
491 attr_dict = pyop_attr_dict.proxyval(visited)
492 else:
493 attr_dict = {}
494 tp_name = self.safe_tp_name()
495
496 # New-style class:
497 return InstanceProxy(tp_name, attr_dict, long(self._gdbval))
498
499 def write_repr(self, out, visited):
500 # Guard against infinite loops:
501 if self.as_address() in visited:
502 out.write('<...>')
503 return
504 visited.add(self.as_address())
505
506 pyop_attrdict = self.get_attr_dict()
507 _write_instance_repr(out, visited,
508 self.safe_tp_name(), pyop_attrdict, self.as_address())
509
510class ProxyException(Exception):
511 def __init__(self, tp_name, args):
512 self.tp_name = tp_name
513 self.args = args
514
515 def __repr__(self):
516 return '%s%r' % (self.tp_name, self.args)
517
518class PyBaseExceptionObjectPtr(PyObjectPtr):
519 """
520 Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
521 within the process being debugged.
522 """
523 _typename = 'PyBaseExceptionObject'
524
525 def proxyval(self, visited):
526 # Guard against infinite loops:
527 if self.as_address() in visited:
528 return ProxyAlreadyVisited('(...)')
529 visited.add(self.as_address())
530 arg_proxy = self.pyop_field('args').proxyval(visited)
531 return ProxyException(self.safe_tp_name(),
532 arg_proxy)
533
534 def write_repr(self, out, visited):
535 # Guard against infinite loops:
536 if self.as_address() in visited:
537 out.write('(...)')
538 return
539 visited.add(self.as_address())
540
541 out.write(self.safe_tp_name())
542 self.write_field_repr('args', out, visited)
543
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000544class PyClassObjectPtr(PyObjectPtr):
545 """
546 Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
547 instance within the process being debugged.
548 """
549 _typename = 'PyClassObject'
550
551
552class BuiltInFunctionProxy(object):
553 def __init__(self, ml_name):
554 self.ml_name = ml_name
555
556 def __repr__(self):
557 return "<built-in function %s>" % self.ml_name
558
559class BuiltInMethodProxy(object):
560 def __init__(self, ml_name, pyop_m_self):
561 self.ml_name = ml_name
562 self.pyop_m_self = pyop_m_self
563
564 def __repr__(self):
565 return ('<built-in method %s of %s object at remote 0x%x>'
566 % (self.ml_name,
567 self.pyop_m_self.safe_tp_name(),
568 self.pyop_m_self.as_address())
569 )
570
571class PyCFunctionObjectPtr(PyObjectPtr):
572 """
573 Class wrapping a gdb.Value that's a PyCFunctionObject*
574 (see Include/methodobject.h and Objects/methodobject.c)
575 """
576 _typename = 'PyCFunctionObject'
577
578 def proxyval(self, visited):
579 m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
580 ml_name = m_ml['ml_name'].string()
581
582 pyop_m_self = self.pyop_field('m_self')
583 if pyop_m_self.is_null():
584 return BuiltInFunctionProxy(ml_name)
585 else:
586 return BuiltInMethodProxy(ml_name, pyop_m_self)
587
588
589class PyCodeObjectPtr(PyObjectPtr):
590 """
591 Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
592 within the process being debugged.
593 """
594 _typename = 'PyCodeObject'
595
596 def addr2line(self, addrq):
597 '''
598 Get the line number for a given bytecode offset
599
600 Analogous to PyCode_Addr2Line; translated from pseudocode in
601 Objects/lnotab_notes.txt
602 '''
603 co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
604
605 # Initialize lineno to co_firstlineno as per PyCode_Addr2Line
606 # not 0, as lnotab_notes.txt has it:
607 lineno = int_from_int(self.field('co_firstlineno'))
608
609 addr = 0
610 for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
611 addr += ord(addr_incr)
612 if addr > addrq:
613 return lineno
614 lineno += ord(line_incr)
615 return lineno
616
617
618class PyDictObjectPtr(PyObjectPtr):
619 """
620 Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
621 within the process being debugged.
622 """
623 _typename = 'PyDictObject'
624
625 def iteritems(self):
626 '''
627 Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
628 analagous to dict.iteritems()
629 '''
630 for i in safe_range(self.field('ma_mask') + 1):
631 ep = self.field('ma_table') + i
632 pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
633 if not pyop_value.is_null():
634 pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
635 yield (pyop_key, pyop_value)
636
637 def proxyval(self, visited):
638 # Guard against infinite loops:
639 if self.as_address() in visited:
640 return ProxyAlreadyVisited('{...}')
641 visited.add(self.as_address())
642
643 result = {}
644 for pyop_key, pyop_value in self.iteritems():
645 proxy_key = pyop_key.proxyval(visited)
646 proxy_value = pyop_value.proxyval(visited)
647 result[proxy_key] = proxy_value
648 return result
649
650 def write_repr(self, out, visited):
651 # Guard against infinite loops:
652 if self.as_address() in visited:
653 out.write('{...}')
654 return
655 visited.add(self.as_address())
656
657 out.write('{')
658 first = True
659 for pyop_key, pyop_value in self.iteritems():
660 if not first:
661 out.write(', ')
662 first = False
663 pyop_key.write_repr(out, visited)
664 out.write(': ')
665 pyop_value.write_repr(out, visited)
666 out.write('}')
667
668class PyInstanceObjectPtr(PyObjectPtr):
669 _typename = 'PyInstanceObject'
670
671 def proxyval(self, visited):
672 # Guard against infinite loops:
673 if self.as_address() in visited:
674 return ProxyAlreadyVisited('<...>')
675 visited.add(self.as_address())
676
677 # Get name of class:
678 in_class = self.pyop_field('in_class')
679 cl_name = in_class.pyop_field('cl_name').proxyval(visited)
680
681 # Get dictionary of instance attributes:
682 in_dict = self.pyop_field('in_dict').proxyval(visited)
683
684 # Old-style class:
685 return InstanceProxy(cl_name, in_dict, long(self._gdbval))
686
687 def write_repr(self, out, visited):
688 # Guard against infinite loops:
689 if self.as_address() in visited:
690 out.write('<...>')
691 return
692 visited.add(self.as_address())
693
694 # Old-style class:
695
696 # Get name of class:
697 in_class = self.pyop_field('in_class')
698 cl_name = in_class.pyop_field('cl_name').proxyval(visited)
699
700 # Get dictionary of instance attributes:
701 pyop_in_dict = self.pyop_field('in_dict')
702
703 _write_instance_repr(out, visited,
704 cl_name, pyop_in_dict, self.as_address())
705
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000706class PyListObjectPtr(PyObjectPtr):
707 _typename = 'PyListObject'
708
709 def __getitem__(self, i):
710 # Get the gdb.Value for the (PyObject*) with the given index:
711 field_ob_item = self.field('ob_item')
712 return field_ob_item[i]
713
714 def proxyval(self, visited):
715 # Guard against infinite loops:
716 if self.as_address() in visited:
717 return ProxyAlreadyVisited('[...]')
718 visited.add(self.as_address())
719
720 result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
721 for i in safe_range(int_from_int(self.field('ob_size')))]
722 return result
723
724 def write_repr(self, out, visited):
725 # Guard against infinite loops:
726 if self.as_address() in visited:
727 out.write('[...]')
728 return
729 visited.add(self.as_address())
730
731 out.write('[')
732 for i in safe_range(int_from_int(self.field('ob_size'))):
733 if i > 0:
734 out.write(', ')
735 element = PyObjectPtr.from_pyobject_ptr(self[i])
736 element.write_repr(out, visited)
737 out.write(']')
738
739class PyLongObjectPtr(PyObjectPtr):
740 _typename = 'PyLongObject'
741
742 def proxyval(self, visited):
743 '''
744 Python's Include/longobjrep.h has this declaration:
745 struct _longobject {
746 PyObject_VAR_HEAD
747 digit ob_digit[1];
748 };
749
750 with this description:
751 The absolute value of a number is equal to
752 SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
753 Negative numbers are represented with ob_size < 0;
754 zero is represented by ob_size == 0.
755
756 where SHIFT can be either:
757 #define PyLong_SHIFT 30
758 #define PyLong_SHIFT 15
759 '''
760 ob_size = long(self.field('ob_size'))
761 if ob_size == 0:
762 return 0L
763
764 ob_digit = self.field('ob_digit')
765
766 if gdb.lookup_type('digit').sizeof == 2:
767 SHIFT = 15L
768 else:
769 SHIFT = 30L
770
771 digits = [long(ob_digit[i]) * 2**(SHIFT*i)
772 for i in safe_range(abs(ob_size))]
773 result = sum(digits)
774 if ob_size < 0:
775 result = -result
776 return result
777
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000778 def write_repr(self, out, visited):
779 # Write this out as a Python 3 int literal, i.e. without the "L" suffix
780 proxy = self.proxyval(visited)
781 out.write("%s" % proxy)
782
783
784class PyBoolObjectPtr(PyLongObjectPtr):
785 """
786 Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
787 <bool> instances (Py_True/Py_False) within the process being debugged.
788 """
789 def proxyval(self, visited):
790 if PyLongObjectPtr.proxyval(self, visited):
791 return True
792 else:
793 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000794
795class PyNoneStructPtr(PyObjectPtr):
796 """
797 Class wrapping a gdb.Value that's a PyObject* pointing to the
798 singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
799 """
800 _typename = 'PyObject'
801
802 def proxyval(self, visited):
803 return None
804
805
806class PyFrameObjectPtr(PyObjectPtr):
807 _typename = 'PyFrameObject'
808
809 def __init__(self, gdbval, cast_to):
810 PyObjectPtr.__init__(self, gdbval, cast_to)
811
812 if not self.is_optimized_out():
813 self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
814 self.co_name = self.co.pyop_field('co_name')
815 self.co_filename = self.co.pyop_field('co_filename')
816
817 self.f_lineno = int_from_int(self.field('f_lineno'))
818 self.f_lasti = int_from_int(self.field('f_lasti'))
819 self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
820 self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
821
822 def iter_locals(self):
823 '''
824 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
825 the local variables of this frame
826 '''
827 if self.is_optimized_out():
828 return
829
830 f_localsplus = self.field('f_localsplus')
831 for i in safe_range(self.co_nlocals):
832 pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
833 if not pyop_value.is_null():
834 pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
835 yield (pyop_name, pyop_value)
836
837 def iter_globals(self):
838 '''
839 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
840 the global variables of this frame
841 '''
842 if self.is_optimized_out():
843 return
844
845 pyop_globals = self.pyop_field('f_globals')
846 return pyop_globals.iteritems()
847
848 def iter_builtins(self):
849 '''
850 Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
851 the builtin variables
852 '''
853 if self.is_optimized_out():
854 return
855
856 pyop_builtins = self.pyop_field('f_builtins')
857 return pyop_builtins.iteritems()
858
859 def get_var_by_name(self, name):
860 '''
861 Look for the named local variable, returning a (PyObjectPtr, scope) pair
862 where scope is a string 'local', 'global', 'builtin'
863
864 If not found, return (None, None)
865 '''
866 for pyop_name, pyop_value in self.iter_locals():
867 if name == pyop_name.proxyval(set()):
868 return pyop_value, 'local'
869 for pyop_name, pyop_value in self.iter_globals():
870 if name == pyop_name.proxyval(set()):
871 return pyop_value, 'global'
872 for pyop_name, pyop_value in self.iter_builtins():
873 if name == pyop_name.proxyval(set()):
874 return pyop_value, 'builtin'
875 return None, None
876
877 def filename(self):
878 '''Get the path of the current Python source file, as a string'''
879 if self.is_optimized_out():
880 return '(frame information optimized out)'
881 return self.co_filename.proxyval(set())
882
883 def current_line_num(self):
884 '''Get current line number as an integer (1-based)
885
886 Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
887
888 See Objects/lnotab_notes.txt
889 '''
890 if self.is_optimized_out():
891 return None
892 f_trace = self.field('f_trace')
893 if long(f_trace) != 0:
894 # we have a non-NULL f_trace:
895 return self.f_lineno
896 else:
897 #try:
898 return self.co.addr2line(self.f_lasti)
899 #except ValueError:
900 # return self.f_lineno
901
902 def current_line(self):
903 '''Get the text of the current source line as a string, with a trailing
904 newline character'''
905 if self.is_optimized_out():
906 return '(frame information optimized out)'
Victor Stinner6ffbee72010-10-17 19:35:30 +0000907 filename = self.filename()
Victor Stinnerd57c5c82011-07-01 12:57:44 +0200908 try:
909 f = open(os_fsencode(filename), 'r')
910 except IOError:
911 return None
912 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000913 all_lines = f.readlines()
914 # Convert from 1-based current_line_num to 0-based list offset:
915 return all_lines[self.current_line_num()-1]
916
917 def write_repr(self, out, visited):
918 if self.is_optimized_out():
919 out.write('(frame information optimized out)')
920 return
921 out.write('Frame 0x%x, for file %s, line %i, in %s ('
922 % (self.as_address(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000923 self.co_filename.proxyval(visited),
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000924 self.current_line_num(),
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000925 self.co_name.proxyval(visited)))
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000926 first = True
927 for pyop_name, pyop_value in self.iter_locals():
928 if not first:
929 out.write(', ')
930 first = False
931
932 out.write(pyop_name.proxyval(visited))
933 out.write('=')
934 pyop_value.write_repr(out, visited)
935
936 out.write(')')
937
Victor Stinnere670c882011-05-13 17:40:15 +0200938 def print_traceback(self):
939 if self.is_optimized_out():
940 sys.stdout.write(' (frame information optimized out)\n')
941 visited = set()
942 sys.stdout.write(' File "%s", line %i, in %s\n'
943 % (self.co_filename.proxyval(visited),
944 self.current_line_num(),
945 self.co_name.proxyval(visited)))
946
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000947class PySetObjectPtr(PyObjectPtr):
948 _typename = 'PySetObject'
949
950 def proxyval(self, visited):
951 # Guard against infinite loops:
952 if self.as_address() in visited:
953 return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
954 visited.add(self.as_address())
955
956 members = []
957 table = self.field('table')
958 for i in safe_range(self.field('mask')+1):
959 setentry = table[i]
960 key = setentry['key']
961 if key != 0:
962 key_proxy = PyObjectPtr.from_pyobject_ptr(key).proxyval(visited)
963 if key_proxy != '<dummy key>':
964 members.append(key_proxy)
965 if self.safe_tp_name() == 'frozenset':
966 return frozenset(members)
967 else:
968 return set(members)
969
970 def write_repr(self, out, visited):
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000971 # Emulate Python 3's set_repr
972 tp_name = self.safe_tp_name()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000973
974 # Guard against infinite loops:
975 if self.as_address() in visited:
976 out.write('(...)')
977 return
978 visited.add(self.as_address())
979
Martin v. Löwis5ae68102010-04-21 22:38:42 +0000980 # Python 3's set_repr special-cases the empty set:
981 if not self.field('used'):
982 out.write(tp_name)
983 out.write('()')
984 return
985
986 # Python 3 uses {} for set literals:
987 if tp_name != 'set':
988 out.write(tp_name)
989 out.write('(')
990
991 out.write('{')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +0000992 first = True
993 table = self.field('table')
994 for i in safe_range(self.field('mask')+1):
995 setentry = table[i]
996 key = setentry['key']
997 if key != 0:
998 pyop_key = PyObjectPtr.from_pyobject_ptr(key)
999 key_proxy = pyop_key.proxyval(visited) # FIXME!
1000 if key_proxy != '<dummy key>':
1001 if not first:
1002 out.write(', ')
1003 first = False
1004 pyop_key.write_repr(out, visited)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001005 out.write('}')
1006
1007 if tp_name != 'set':
1008 out.write(')')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001009
1010
Victor Stinner67df3a42010-04-21 13:53:05 +00001011class PyBytesObjectPtr(PyObjectPtr):
1012 _typename = 'PyBytesObject'
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001013
1014 def __str__(self):
1015 field_ob_size = self.field('ob_size')
1016 field_ob_sval = self.field('ob_sval')
1017 char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr)
1018 return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1019
1020 def proxyval(self, visited):
1021 return str(self)
1022
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001023 def write_repr(self, out, visited):
1024 # Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1025
1026 # Get a PyStringObject* within the Python 2 gdb process:
1027 proxy = self.proxyval(visited)
1028
1029 # Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1030 # to Python 2 code:
1031 quote = "'"
1032 if "'" in proxy and not '"' in proxy:
1033 quote = '"'
1034 out.write('b')
1035 out.write(quote)
1036 for byte in proxy:
1037 if byte == quote or byte == '\\':
1038 out.write('\\')
1039 out.write(byte)
1040 elif byte == '\t':
1041 out.write('\\t')
1042 elif byte == '\n':
1043 out.write('\\n')
1044 elif byte == '\r':
1045 out.write('\\r')
1046 elif byte < ' ' or ord(byte) >= 0x7f:
1047 out.write('\\x')
1048 out.write(hexdigits[(ord(byte) & 0xf0) >> 4])
1049 out.write(hexdigits[ord(byte) & 0xf])
1050 else:
1051 out.write(byte)
1052 out.write(quote)
1053
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001054class PyTupleObjectPtr(PyObjectPtr):
1055 _typename = 'PyTupleObject'
1056
1057 def __getitem__(self, i):
1058 # Get the gdb.Value for the (PyObject*) with the given index:
1059 field_ob_item = self.field('ob_item')
1060 return field_ob_item[i]
1061
1062 def proxyval(self, visited):
1063 # Guard against infinite loops:
1064 if self.as_address() in visited:
1065 return ProxyAlreadyVisited('(...)')
1066 visited.add(self.as_address())
1067
1068 result = tuple([PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1069 for i in safe_range(int_from_int(self.field('ob_size')))])
1070 return result
1071
1072 def write_repr(self, out, visited):
1073 # Guard against infinite loops:
1074 if self.as_address() in visited:
1075 out.write('(...)')
1076 return
1077 visited.add(self.as_address())
1078
1079 out.write('(')
1080 for i in safe_range(int_from_int(self.field('ob_size'))):
1081 if i > 0:
1082 out.write(', ')
1083 element = PyObjectPtr.from_pyobject_ptr(self[i])
1084 element.write_repr(out, visited)
1085 if self.field('ob_size') == 1:
1086 out.write(',)')
1087 else:
1088 out.write(')')
1089
1090class PyTypeObjectPtr(PyObjectPtr):
1091 _typename = 'PyTypeObject'
1092
1093
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001094def _unichr_is_printable(char):
1095 # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1096 if char == u" ":
1097 return True
1098 import unicodedata
Antoine Pitroub41e1282010-09-08 20:57:48 +00001099 return unicodedata.category(char) not in ("C", "Z")
1100
1101if sys.maxunicode >= 0x10000:
1102 _unichr = unichr
1103else:
1104 # Needed for proper surrogate support if sizeof(Py_UNICODE) is 2 in gdb
1105 def _unichr(x):
1106 if x < 0x10000:
1107 return unichr(x)
1108 x -= 0x10000
1109 ch1 = 0xD800 | (x >> 10)
1110 ch2 = 0xDC00 | (x & 0x3FF)
1111 return unichr(ch1) + unichr(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001112
1113
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001114class PyUnicodeObjectPtr(PyObjectPtr):
1115 _typename = 'PyUnicodeObject'
1116
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001117 def char_width(self):
1118 _type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1119 return _type_Py_UNICODE.sizeof
1120
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001121 def proxyval(self, visited):
1122 # From unicodeobject.h:
1123 # Py_ssize_t length; /* Length of raw Unicode data in buffer */
1124 # Py_UNICODE *str; /* Raw Unicode buffer */
1125 field_length = long(self.field('length'))
1126 field_str = self.field('str')
1127
1128 # Gather a list of ints from the Py_UNICODE array; these are either
1129 # UCS-2 or UCS-4 code points:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001130 if self.char_width() > 2:
1131 Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1132 else:
1133 # A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1134 # inferior process: we must join surrogate pairs.
1135 Py_UNICODEs = []
1136 i = 0
Antoine Pitroub1856d72010-09-08 21:07:40 +00001137 limit = safety_limit(field_length)
1138 while i < limit:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001139 ucs = int(field_str[i])
1140 i += 1
1141 if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1142 Py_UNICODEs.append(ucs)
1143 continue
1144 # This could be a surrogate pair.
1145 ucs2 = int(field_str[i])
1146 if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1147 continue
1148 code = (ucs & 0x03FF) << 10
1149 code |= ucs2 & 0x03FF
1150 code += 0x00010000
1151 Py_UNICODEs.append(code)
1152 i += 1
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001153
1154 # Convert the int code points to unicode characters, and generate a
Antoine Pitroub41e1282010-09-08 20:57:48 +00001155 # local unicode instance.
1156 # This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
1157 result = u''.join([_unichr(ucs) for ucs in Py_UNICODEs])
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001158 return result
1159
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001160 def write_repr(self, out, visited):
1161 # Write this out as a Python 3 str literal, i.e. without a "u" prefix
1162
1163 # Get a PyUnicodeObject* within the Python 2 gdb process:
1164 proxy = self.proxyval(visited)
1165
1166 # Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1167 # to Python 2:
1168 if "'" in proxy and '"' not in proxy:
1169 quote = '"'
1170 else:
1171 quote = "'"
1172 out.write(quote)
1173
1174 i = 0
1175 while i < len(proxy):
1176 ch = proxy[i]
1177 i += 1
1178
1179 # Escape quotes and backslashes
1180 if ch == quote or ch == '\\':
1181 out.write('\\')
1182 out.write(ch)
1183
1184 # Map special whitespace to '\t', \n', '\r'
1185 elif ch == '\t':
1186 out.write('\\t')
1187 elif ch == '\n':
1188 out.write('\\n')
1189 elif ch == '\r':
1190 out.write('\\r')
1191
1192 # Map non-printable US ASCII to '\xhh' */
1193 elif ch < ' ' or ch == 0x7F:
1194 out.write('\\x')
1195 out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
1196 out.write(hexdigits[ord(ch) & 0x000F])
1197
1198 # Copy ASCII characters as-is
1199 elif ord(ch) < 0x7F:
1200 out.write(ch)
1201
1202 # Non-ASCII characters
1203 else:
Victor Stinner150016f2010-05-19 23:04:56 +00001204 ucs = ch
Antoine Pitroub41e1282010-09-08 20:57:48 +00001205 ch2 = None
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001206 if sys.maxunicode < 0x10000:
Antoine Pitroub41e1282010-09-08 20:57:48 +00001207 # If sizeof(Py_UNICODE) is 2 here (in gdb), join
1208 # surrogate pairs before calling _unichr_is_printable.
Victor Stinner150016f2010-05-19 23:04:56 +00001209 if (i < len(proxy)
1210 and 0xD800 <= ord(ch) < 0xDC00 \
1211 and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001212 ch2 = proxy[i]
Antoine Pitroub41e1282010-09-08 20:57:48 +00001213 ucs = ch + ch2
Victor Stinner150016f2010-05-19 23:04:56 +00001214 i += 1
Victor Stinner150016f2010-05-19 23:04:56 +00001215
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001216 # Unfortuately, Python 2's unicode type doesn't seem
1217 # to expose the "isprintable" method
Victor Stinner150016f2010-05-19 23:04:56 +00001218 printable = _unichr_is_printable(ucs)
1219 if printable:
1220 try:
1221 ucs.encode(ENCODING)
1222 except UnicodeEncodeError:
1223 printable = False
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001224
1225 # Map Unicode whitespace and control characters
1226 # (categories Z* and C* except ASCII space)
Victor Stinner150016f2010-05-19 23:04:56 +00001227 if not printable:
Antoine Pitrou7c9cf012010-09-08 21:57:37 +00001228 if ch2 is not None:
1229 # Match Python 3's representation of non-printable
1230 # wide characters.
1231 code = (ord(ch) & 0x03FF) << 10
1232 code |= ord(ch2) & 0x03FF
1233 code += 0x00010000
1234 else:
1235 code = ord(ucs)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001236
1237 # Map 8-bit characters to '\\xhh'
Victor Stinner150016f2010-05-19 23:04:56 +00001238 if code <= 0xff:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001239 out.write('\\x')
Victor Stinner150016f2010-05-19 23:04:56 +00001240 out.write(hexdigits[(code >> 4) & 0x000F])
1241 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001242 # Map 21-bit characters to '\U00xxxxxx'
Victor Stinner150016f2010-05-19 23:04:56 +00001243 elif code >= 0x10000:
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001244 out.write('\\U')
Victor Stinner150016f2010-05-19 23:04:56 +00001245 out.write(hexdigits[(code >> 28) & 0x0000000F])
1246 out.write(hexdigits[(code >> 24) & 0x0000000F])
1247 out.write(hexdigits[(code >> 20) & 0x0000000F])
1248 out.write(hexdigits[(code >> 16) & 0x0000000F])
1249 out.write(hexdigits[(code >> 12) & 0x0000000F])
1250 out.write(hexdigits[(code >> 8) & 0x0000000F])
1251 out.write(hexdigits[(code >> 4) & 0x0000000F])
1252 out.write(hexdigits[code & 0x0000000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001253 # Map 16-bit characters to '\uxxxx'
1254 else:
1255 out.write('\\u')
Victor Stinner150016f2010-05-19 23:04:56 +00001256 out.write(hexdigits[(code >> 12) & 0x000F])
1257 out.write(hexdigits[(code >> 8) & 0x000F])
1258 out.write(hexdigits[(code >> 4) & 0x000F])
1259 out.write(hexdigits[code & 0x000F])
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001260 else:
1261 # Copy characters as-is
1262 out.write(ch)
Antoine Pitroub41e1282010-09-08 20:57:48 +00001263 if ch2 is not None:
Victor Stinner150016f2010-05-19 23:04:56 +00001264 out.write(ch2)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001265
1266 out.write(quote)
1267
1268
1269
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001270
1271def int_from_int(gdbval):
1272 return int(str(gdbval))
1273
1274
1275def stringify(val):
1276 # TODO: repr() puts everything on one line; pformat can be nicer, but
1277 # can lead to v.long results; this function isolates the choice
1278 if True:
1279 return repr(val)
1280 else:
1281 from pprint import pformat
1282 return pformat(val)
1283
1284
1285class PyObjectPtrPrinter:
1286 "Prints a (PyObject*)"
1287
1288 def __init__ (self, gdbval):
1289 self.gdbval = gdbval
1290
1291 def to_string (self):
1292 pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1293 if True:
1294 return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1295 else:
1296 # Generate full proxy value then stringify it.
1297 # Doing so could be expensive
1298 proxyval = pyop.proxyval(set())
1299 return stringify(proxyval)
1300
1301def pretty_printer_lookup(gdbval):
1302 type = gdbval.type.unqualified()
1303 if type.code == gdb.TYPE_CODE_PTR:
1304 type = type.target().unqualified()
1305 t = str(type)
Martin v. Löwis5ae68102010-04-21 22:38:42 +00001306 if t in ("PyObject", "PyFrameObject", "PyUnicodeObject"):
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001307 return PyObjectPtrPrinter(gdbval)
1308
1309"""
1310During development, I've been manually invoking the code in this way:
1311(gdb) python
1312
1313import sys
1314sys.path.append('/home/david/coding/python-gdb')
1315import libpython
1316end
1317
1318then reloading it after each edit like this:
1319(gdb) python reload(libpython)
1320
1321The following code should ensure that the prettyprinter is registered
1322if the code is autoloaded by gdb when visiting libpython.so, provided
1323that this python file is installed to the same path as the library (or its
1324.debug file) plus a "-gdb.py" suffix, e.g:
1325 /usr/lib/libpython2.6.so.1.0-gdb.py
1326 /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1327"""
1328def register (obj):
1329 if obj == None:
1330 obj = gdb
1331
1332 # Wire up the pretty-printer
1333 obj.pretty_printers.append(pretty_printer_lookup)
1334
1335register (gdb.current_objfile ())
1336
1337
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001338
1339# Unfortunately, the exact API exposed by the gdb module varies somewhat
1340# from build to build
1341# See http://bugs.python.org/issue8279?#msg102276
1342
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001343class Frame(object):
1344 '''
1345 Wrapper for gdb.Frame, adding various methods
1346 '''
1347 def __init__(self, gdbframe):
1348 self._gdbframe = gdbframe
1349
1350 def older(self):
1351 older = self._gdbframe.older()
1352 if older:
1353 return Frame(older)
1354 else:
1355 return None
1356
1357 def newer(self):
1358 newer = self._gdbframe.newer()
1359 if newer:
1360 return Frame(newer)
1361 else:
1362 return None
1363
1364 def select(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001365 '''If supported, select this frame and return True; return False if unsupported
1366
1367 Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1368 onwards, but absent on Ubuntu buildbot'''
1369 if not hasattr(self._gdbframe, 'select'):
1370 print ('Unable to select frame: '
1371 'this build of gdb does not expose a gdb.Frame.select method')
1372 return False
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001373 self._gdbframe.select()
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001374 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001375
1376 def get_index(self):
1377 '''Calculate index of frame, starting at 0 for the newest frame within
1378 this thread'''
1379 index = 0
1380 # Go down until you reach the newest frame:
1381 iter_frame = self
1382 while iter_frame.newer():
1383 index += 1
1384 iter_frame = iter_frame.newer()
1385 return index
1386
1387 def is_evalframeex(self):
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001388 '''Is this a PyEval_EvalFrameEx frame?'''
Victor Stinner50eb60e2010-04-20 22:32:07 +00001389 if self._gdbframe.name() == 'PyEval_EvalFrameEx':
1390 '''
1391 I believe we also need to filter on the inline
1392 struct frame_id.inline_depth, only regarding frames with
1393 an inline depth of 0 as actually being this function
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001394
Victor Stinner50eb60e2010-04-20 22:32:07 +00001395 So we reject those with type gdb.INLINE_FRAME
1396 '''
1397 if self._gdbframe.type() == gdb.NORMAL_FRAME:
1398 # We have a PyEval_EvalFrameEx frame:
1399 return True
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001400
1401 return False
1402
1403 def get_pyop(self):
1404 try:
1405 f = self._gdbframe.read_var('f')
1406 return PyFrameObjectPtr.from_pyobject_ptr(f)
1407 except ValueError:
1408 return None
1409
1410 @classmethod
1411 def get_selected_frame(cls):
1412 _gdbframe = gdb.selected_frame()
1413 if _gdbframe:
1414 return Frame(_gdbframe)
1415 return None
1416
1417 @classmethod
1418 def get_selected_python_frame(cls):
1419 '''Try to obtain the Frame for the python code in the selected frame,
1420 or None'''
1421 frame = cls.get_selected_frame()
1422
1423 while frame:
1424 if frame.is_evalframeex():
1425 return frame
1426 frame = frame.older()
1427
1428 # Not found:
1429 return None
1430
1431 def print_summary(self):
1432 if self.is_evalframeex():
1433 pyop = self.get_pyop()
1434 if pyop:
Victor Stinner0e5a41b2010-08-17 22:49:25 +00001435 line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1436 write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001437 line = pyop.current_line()
1438 if line is not None:
1439 sys.stdout.write(line)
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001440 else:
1441 sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1442 else:
1443 sys.stdout.write('#%i\n' % self.get_index())
1444
Victor Stinnere670c882011-05-13 17:40:15 +02001445 def print_traceback(self):
1446 if self.is_evalframeex():
1447 pyop = self.get_pyop()
1448 if pyop:
1449 pyop.print_traceback()
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001450 line = pyop.current_line()
1451 if line is not None:
1452 sys.stdout.write(' %s\n' % line.strip())
Victor Stinnere670c882011-05-13 17:40:15 +02001453 else:
1454 sys.stdout.write(' (unable to read python frame information)\n')
1455 else:
1456 sys.stdout.write(' (not a python frame)\n')
1457
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001458class PyList(gdb.Command):
1459 '''List the current Python source code, if any
1460
1461 Use
1462 py-list START
1463 to list at a different line number within the python source.
1464
1465 Use
1466 py-list START, END
1467 to list a specific range of lines within the python source.
1468 '''
1469
1470 def __init__(self):
1471 gdb.Command.__init__ (self,
1472 "py-list",
1473 gdb.COMMAND_FILES,
1474 gdb.COMPLETE_NONE)
1475
1476
1477 def invoke(self, args, from_tty):
1478 import re
1479
1480 start = None
1481 end = None
1482
1483 m = re.match(r'\s*(\d+)\s*', args)
1484 if m:
1485 start = int(m.group(0))
1486 end = start + 10
1487
1488 m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1489 if m:
1490 start, end = map(int, m.groups())
1491
1492 frame = Frame.get_selected_python_frame()
1493 if not frame:
1494 print 'Unable to locate python frame'
1495 return
1496
1497 pyop = frame.get_pyop()
1498 if not pyop:
1499 print 'Unable to read information on python frame'
1500 return
1501
1502 filename = pyop.filename()
1503 lineno = pyop.current_line_num()
1504
1505 if start is None:
1506 start = lineno - 5
1507 end = lineno + 5
1508
1509 if start<1:
1510 start = 1
1511
Victor Stinnerd57c5c82011-07-01 12:57:44 +02001512 try:
1513 f = open(os_fsencode(filename), 'r')
1514 except IOError as err:
1515 sys.stdout.write('Unable to open %s: %s\n'
1516 % (filename, err))
1517 return
1518 with f:
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001519 all_lines = f.readlines()
1520 # start and end are 1-based, all_lines is 0-based;
1521 # so [start-1:end] as a python slice gives us [start, end] as a
1522 # closed interval
1523 for i, line in enumerate(all_lines[start-1:end]):
1524 linestr = str(i+start)
1525 # Highlight current line:
1526 if i + start == lineno:
1527 linestr = '>' + linestr
1528 sys.stdout.write('%4s %s' % (linestr, line))
1529
1530
1531# ...and register the command:
1532PyList()
1533
1534def move_in_stack(move_up):
1535 '''Move up or down the stack (for the py-up/py-down command)'''
1536 frame = Frame.get_selected_python_frame()
1537 while frame:
1538 if move_up:
1539 iter_frame = frame.older()
1540 else:
1541 iter_frame = frame.newer()
1542
1543 if not iter_frame:
1544 break
1545
1546 if iter_frame.is_evalframeex():
1547 # Result:
Martin v. Löwis5226fd62010-04-21 06:05:58 +00001548 if iter_frame.select():
1549 iter_frame.print_summary()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001550 return
1551
1552 frame = iter_frame
1553
1554 if move_up:
1555 print 'Unable to find an older python frame'
1556 else:
1557 print 'Unable to find a newer python frame'
1558
1559class PyUp(gdb.Command):
1560 'Select and print the python stack frame that called this one (if any)'
1561 def __init__(self):
1562 gdb.Command.__init__ (self,
1563 "py-up",
1564 gdb.COMMAND_STACK,
1565 gdb.COMPLETE_NONE)
1566
1567
1568 def invoke(self, args, from_tty):
1569 move_in_stack(move_up=True)
1570
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001571class PyDown(gdb.Command):
1572 'Select and print the python stack frame called by this one (if any)'
1573 def __init__(self):
1574 gdb.Command.__init__ (self,
1575 "py-down",
1576 gdb.COMMAND_STACK,
1577 gdb.COMPLETE_NONE)
1578
1579
1580 def invoke(self, args, from_tty):
1581 move_in_stack(move_up=False)
1582
Victor Stinner50eb60e2010-04-20 22:32:07 +00001583# Not all builds of gdb have gdb.Frame.select
1584if hasattr(gdb.Frame, 'select'):
1585 PyUp()
1586 PyDown()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001587
Victor Stinnere670c882011-05-13 17:40:15 +02001588class PyBacktraceFull(gdb.Command):
1589 'Display the current python frame and all the frames within its call stack (if any)'
1590 def __init__(self):
1591 gdb.Command.__init__ (self,
1592 "py-bt-full",
1593 gdb.COMMAND_STACK,
1594 gdb.COMPLETE_NONE)
1595
1596
1597 def invoke(self, args, from_tty):
1598 frame = Frame.get_selected_python_frame()
1599 while frame:
1600 if frame.is_evalframeex():
1601 frame.print_summary()
1602 frame = frame.older()
1603
1604PyBacktraceFull()
1605
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001606class PyBacktrace(gdb.Command):
1607 'Display the current python frame and all the frames within its call stack (if any)'
1608 def __init__(self):
1609 gdb.Command.__init__ (self,
1610 "py-bt",
1611 gdb.COMMAND_STACK,
1612 gdb.COMPLETE_NONE)
1613
1614
1615 def invoke(self, args, from_tty):
Victor Stinnere670c882011-05-13 17:40:15 +02001616 sys.stdout.write('Traceback (most recent call first):\n')
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001617 frame = Frame.get_selected_python_frame()
1618 while frame:
1619 if frame.is_evalframeex():
Victor Stinnere670c882011-05-13 17:40:15 +02001620 frame.print_traceback()
Benjamin Peterson6a6666a2010-04-11 21:49:28 +00001621 frame = frame.older()
1622
1623PyBacktrace()
1624
1625class PyPrint(gdb.Command):
1626 'Look up the given python variable name, and print it'
1627 def __init__(self):
1628 gdb.Command.__init__ (self,
1629 "py-print",
1630 gdb.COMMAND_DATA,
1631 gdb.COMPLETE_NONE)
1632
1633
1634 def invoke(self, args, from_tty):
1635 name = str(args)
1636
1637 frame = Frame.get_selected_python_frame()
1638 if not frame:
1639 print 'Unable to locate python frame'
1640 return
1641
1642 pyop_frame = frame.get_pyop()
1643 if not pyop_frame:
1644 print 'Unable to read information on python frame'
1645 return
1646
1647 pyop_var, scope = pyop_frame.get_var_by_name(name)
1648
1649 if pyop_var:
1650 print ('%s %r = %s'
1651 % (scope,
1652 name,
1653 pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1654 else:
1655 print '%r not found' % name
1656
1657PyPrint()
1658
1659class PyLocals(gdb.Command):
1660 'Look up the given python variable name, and print it'
1661 def __init__(self):
1662 gdb.Command.__init__ (self,
1663 "py-locals",
1664 gdb.COMMAND_DATA,
1665 gdb.COMPLETE_NONE)
1666
1667
1668 def invoke(self, args, from_tty):
1669 name = str(args)
1670
1671 frame = Frame.get_selected_python_frame()
1672 if not frame:
1673 print 'Unable to locate python frame'
1674 return
1675
1676 pyop_frame = frame.get_pyop()
1677 if not pyop_frame:
1678 print 'Unable to read information on python frame'
1679 return
1680
1681 for pyop_name, pyop_value in pyop_frame.iter_locals():
1682 print ('%s = %s'
1683 % (pyop_name.proxyval(set()),
1684 pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1685
1686PyLocals()