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