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