3
# NOTE: Most of this file is taken from the Python source distribution
4
# It can be found under Tools/gdb/libpython.py. It is shipped with Cython
5
# because it's not installed as a python module, and because changes are only
6
# merged into new python versions (v3.2+).
7
# We added some of our code below the "## added, not in CPython" comment.
10
From gdb 7 onwards, gdb's build can be configured --with-python, allowing gdb
11
to be extended with Python code e.g. for library-specific data visualizations,
12
such as for the C++ STL types. Documentation on this API can be seen at:
13
http://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html
16
This python module deals with the case when the process being debugged (the
17
"inferior process" in gdb parlance) is itself python, or more specifically,
18
linked against libpython. In this situation, almost every item of data is a
19
(PyObject*), and having the debugger merely print their addresses is not very
22
This module embeds knowledge about the implementation details of libpython so
23
that we can emit useful visualizations e.g. a string, a list, a dict, a frame
24
giving file/line information and the state of local variables
26
In particular, given a gdb.Value corresponding to a PyObject* in the inferior
27
process, we can generate a "proxy value" within the gdb process. For example,
28
given a PyObject* in the inferior process that is in fact a PyListObject*
29
holding three PyObject* that turn out to be PyBytesObject* instances, we can
30
generate a proxy value within the gdb process that is a list of bytes
32
[b"foo", b"bar", b"baz"]
34
Doing so can be expensive for complicated graphs of objects, and could take
35
some time, so we also have a "write_repr" method that writes a representation
36
of the data to a file-like object. This allows us to stop the traversal by
37
having the file-like object raise an exception if it gets too much data.
39
With both "proxyval" and "write_repr" we keep track of the set of all addresses
40
visited so far in the traversal, to avoid infinite recursion due to cycles in
41
the graph of object references.
43
We try to defer gdb.lookup_type() invocations for python types until as late as
44
possible: for a dynamically linked python binary, when the process starts in
45
the debugger, the libpython.so hasn't been dynamically loaded yet, so none of
46
the type names are known to the debugger
48
The module also extends gdb with some python-specific commands.
51
# NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax
52
# compatible (2.6+ and 3.0+). See #19308.
59
# Look up the gdb.Type for some standard types:
60
# Those need to be refreshed as types (pointer sizes) may change when
61
# gdb loads different executables
64
return gdb.lookup_type('char').pointer() # char*
67
def _type_unsigned_char_ptr():
68
return gdb.lookup_type('unsigned char').pointer() # unsigned char*
71
def _type_unsigned_short_ptr():
72
return gdb.lookup_type('unsigned short').pointer()
75
def _type_unsigned_int_ptr():
76
return gdb.lookup_type('unsigned int').pointer()
80
return gdb.lookup_type('void').pointer().sizeof
83
# value computed later, see PyUnicodeObjectPtr.proxy()
86
Py_TPFLAGS_HEAPTYPE = (1 << 9)
87
Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
88
Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
89
Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
90
Py_TPFLAGS_BYTES_SUBCLASS = (1 << 27)
91
Py_TPFLAGS_UNICODE_SUBCLASS = (1 << 28)
92
Py_TPFLAGS_DICT_SUBCLASS = (1 << 29)
93
Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
94
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
99
hexdigits = "0123456789abcdef"
101
ENCODING = locale.getpreferredencoding()
103
FRAME_INFO_OPTIMIZED_OUT = '(frame information optimized out)'
104
UNABLE_READ_INFO_PYTHON_FRAME = 'Unable to read information on python frame'
105
EVALFRAME = '_PyEval_EvalFrameDefault'
107
class NullPyObjectPtr(RuntimeError):
111
def safety_limit(val):
112
# Given an integer value from the process being debugged, limit it to some
113
# safety threshold so that arbitrary breakage within said process doesn't
114
# break the gdb process too much (e.g. sizes of iterations, sizes of lists)
115
return min(val, 1000)
119
# As per range, but don't trust the value too much: cap it to a safety
120
# threshold in case the data was corrupted
121
return range(safety_limit(int(val)))
123
def write_unicode(file, text):
127
os_fsencode = os.fsencode
128
except AttributeError:
129
def os_fsencode(filename):
130
if not isinstance(filename, unicode):
132
encoding = sys.getfilesystemencoding()
133
if encoding == 'mbcs':
134
# mbcs doesn't support surrogateescape
135
return filename.encode(encoding)
137
for char in filename:
138
# surrogateescape error handler
139
if 0xDC80 <= ord(char) <= 0xDCFF:
140
byte = chr(ord(char) - 0xDC00)
142
byte = char.encode(encoding)
144
return ''.join(encoded)
146
class StringTruncated(RuntimeError):
149
class TruncatedStringIO:
150
'''Similar to io.StringIO, but can truncate the output by raising a
151
StringTruncated exception'''
152
def __init__(self, maxlen=None):
156
def write(self, data):
158
if len(data) + len(self._val) > self.maxlen:
160
self._val += data[0:self.maxlen - len(self._val)]
161
raise StringTruncated()
170
Class wrapping a gdb.Value that's either a (PyObject*) within the
171
inferior process, or some subclass pointer e.g. (PyBytesObject*)
173
There will be a subclass for every refined PyObject type that we care
176
Note that at every stage the underlying pointer could be NULL, point
177
to corrupt data, etc; this is the debugger, after all.
179
_typename = 'PyObject'
181
def __init__(self, gdbval, cast_to=None):
183
self._gdbval = gdbval.cast(cast_to)
185
self._gdbval = gdbval
187
def field(self, name):
189
Get the gdb.Value for the given field within the PyObject, coping with
190
some python 2 versus python 3 differences.
192
Various libpython types are defined using the "PyObject_HEAD" and
193
"PyObject_VAR_HEAD" macros.
195
In Python 2, this these are defined so that "ob_type" and (for a var
196
object) "ob_size" are fields of the type in question.
198
In Python 3, this is defined as an embedded PyVarObject type thus:
200
so that the "ob_size" field is located insize the "ob_base" field, and
201
the "ob_type" is most easily accessed by casting back to a (PyObject*).
204
raise NullPyObjectPtr(self)
206
if name == 'ob_type':
207
pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type())
208
return pyo_ptr.dereference()[name]
210
if name == 'ob_size':
211
pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type())
212
return pyo_ptr.dereference()[name]
214
# General case: look it up inside the object:
215
return self._gdbval.dereference()[name]
217
def pyop_field(self, name):
219
Get a PyObjectPtr for the given PyObject* field within this PyObject,
220
coping with some python 2 versus python 3 differences.
222
return PyObjectPtr.from_pyobject_ptr(self.field(name))
224
def write_field_repr(self, name, out, visited):
226
Extract the PyObject* field named "name", and write its representation
227
to file-like object "out"
229
field_obj = self.pyop_field(name)
230
field_obj.write_repr(out, visited)
232
def get_truncated_repr(self, maxlen):
234
Get a repr-like string for the data, but truncate it at "maxlen" bytes
235
(ending the object graph traversal as soon as you do)
237
out = TruncatedStringIO(maxlen)
239
self.write_repr(out, set())
240
except StringTruncated:
241
# Truncation occurred:
242
return out.getvalue() + '...(truncated)'
244
# No truncation occurred:
245
return out.getvalue()
248
return PyTypeObjectPtr(self.field('ob_type'))
251
return 0 == int(self._gdbval)
253
def is_optimized_out(self):
255
Is the value of the underlying PyObject* visible to the debugger?
257
This can vary with the precise version of the compiler used to build
258
Python, and the precise version of gdb.
260
See e.g. https://bugzilla.redhat.com/show_bug.cgi?id=556975 with
261
PyEval_EvalFrameEx's "f"
263
return self._gdbval.is_optimized_out
265
def safe_tp_name(self):
267
ob_type = self.type()
268
tp_name = ob_type.field('tp_name')
269
return tp_name.string()
270
# NullPyObjectPtr: NULL tp_name?
271
# RuntimeError: Can't even read the object at all?
272
# UnicodeDecodeError: Failed to decode tp_name bytestring
273
except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
276
def proxyval(self, visited):
278
Scrape a value from the inferior process, and try to represent it
279
within the gdb process, whilst (hopefully) avoiding crashes when
280
the remote data is corrupt.
282
Derived classes will override this.
284
For example, a PyIntObject* with ob_ival 42 in the inferior process
285
should result in an int(42) in this process.
287
visited: a set of all gdb.Value pyobject pointers already visited
288
whilst generating this value (to guard against infinite recursion when
289
visiting object graphs with loops). Analogous to Py_ReprEnter and
295
Class representing a non-descript PyObject* value in the inferior
296
process for when we don't have a custom scraper, intended to have
300
def __init__(self, tp_name, address):
301
self.tp_name = tp_name
302
self.address = address
305
# For the NULL pointer, we have no way of knowing a type, so
306
# special-case it as per
307
# http://bugs.python.org/issue8032#msg100882
308
if self.address == 0:
310
return '<%s at remote 0x%x>' % (self.tp_name, self.address)
312
return FakeRepr(self.safe_tp_name(),
315
def write_repr(self, out, visited):
317
Write a string representation of the value scraped from the inferior
318
process to "out", a file-like object.
320
# Default implementation: generate a proxy value and write its repr
321
# However, this could involve a lot of work for complicated objects,
322
# so for derived classes we specialize this
323
return out.write(repr(self.proxyval(visited)))
326
def subclass_from_type(cls, t):
328
Given a PyTypeObjectPtr instance wrapping a gdb.Value that's a
329
(PyTypeObject*), determine the corresponding subclass of PyObjectPtr
332
Ideally, we would look up the symbols for the global types, but that
334
(gdb) python print gdb.lookup_symbol('PyList_Type')[0].value
335
Traceback (most recent call last):
336
File "<string>", line 1, in <module>
337
NotImplementedError: Symbol type not yet supported in Python scripts.
338
Error while executing Python code.
340
For now, we use tp_flags, after doing some string comparisons on the
341
tp_name for some special-cases that don't seem to be visible through
345
tp_name = t.field('tp_name').string()
346
tp_flags = int(t.field('tp_flags'))
347
# RuntimeError: NULL pointers
348
# UnicodeDecodeError: string() fails to decode the bytestring
349
except (RuntimeError, UnicodeDecodeError):
350
# Handle any kind of error e.g. NULL ptrs by simply using the base
354
#print('tp_flags = 0x%08x' % tp_flags)
355
#print('tp_name = %r' % tp_name)
357
name_map = {'bool': PyBoolObjectPtr,
358
'classobj': PyClassObjectPtr,
359
'NoneType': PyNoneStructPtr,
360
'frame': PyFrameObjectPtr,
361
'set' : PySetObjectPtr,
362
'frozenset' : PySetObjectPtr,
363
'builtin_function_or_method' : PyCFunctionObjectPtr,
364
'method-wrapper': wrapperobject,
366
if tp_name in name_map:
367
return name_map[tp_name]
369
if tp_flags & Py_TPFLAGS_HEAPTYPE:
370
return HeapTypeObjectPtr
372
if tp_flags & Py_TPFLAGS_LONG_SUBCLASS:
373
return PyLongObjectPtr
374
if tp_flags & Py_TPFLAGS_LIST_SUBCLASS:
375
return PyListObjectPtr
376
if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
377
return PyTupleObjectPtr
378
if tp_flags & Py_TPFLAGS_BYTES_SUBCLASS:
379
return PyBytesObjectPtr
380
if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
381
return PyUnicodeObjectPtr
382
if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
383
return PyDictObjectPtr
384
if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
385
return PyBaseExceptionObjectPtr
386
#if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
387
# return PyTypeObjectPtr
389
# Use the base class:
393
def from_pyobject_ptr(cls, gdbval):
395
Try to locate the appropriate derived class dynamically, and cast
396
the pointer accordingly.
399
p = PyObjectPtr(gdbval)
400
cls = cls.subclass_from_type(p.type())
401
return cls(gdbval, cast_to=cls.get_gdb_type())
403
# Handle any kind of error e.g. NULL ptrs by simply using the base
409
def get_gdb_type(cls):
410
return gdb.lookup_type(cls._typename).pointer()
412
def as_address(self):
413
return int(self._gdbval)
415
class PyVarObjectPtr(PyObjectPtr):
416
_typename = 'PyVarObject'
418
class ProxyAlreadyVisited:
420
Placeholder proxy to use when protecting against infinite recursion due to
421
loops in the object graph.
423
Analogous to the values emitted by the users of Py_ReprEnter and Py_ReprLeave
425
def __init__(self, rep):
432
def _write_instance_repr(out, visited, name, pyop_attrdict, address):
433
'''Shared code for use by all classes:
434
write a representation to file-like object "out"'''
438
# Write dictionary of instance attributes:
439
if isinstance(pyop_attrdict, PyDictObjectPtr):
442
for pyop_arg, pyop_val in pyop_attrdict.iteritems():
446
out.write(pyop_arg.proxyval(visited))
448
pyop_val.write_repr(out, visited)
450
out.write(' at remote 0x%x>' % address)
455
def __init__(self, cl_name, attrdict, address):
456
self.cl_name = cl_name
457
self.attrdict = attrdict
458
self.address = address
461
if isinstance(self.attrdict, dict):
462
kwargs = ', '.join(["%s=%r" % (arg, val)
463
for arg, val in self.attrdict.iteritems()])
464
return '<%s(%s) at remote 0x%x>' % (self.cl_name,
465
kwargs, self.address)
467
return '<%s at remote 0x%x>' % (self.cl_name,
470
def _PyObject_VAR_SIZE(typeobj, nitems):
471
if _PyObject_VAR_SIZE._type_size_t is None:
472
_PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t')
474
return ( ( typeobj.field('tp_basicsize') +
475
nitems * typeobj.field('tp_itemsize') +
476
(_sizeof_void_p() - 1)
477
) & ~(_sizeof_void_p() - 1)
478
).cast(_PyObject_VAR_SIZE._type_size_t)
479
_PyObject_VAR_SIZE._type_size_t = None
481
class HeapTypeObjectPtr(PyObjectPtr):
482
_typename = 'PyObject'
484
def get_attr_dict(self):
486
Get the PyDictObject ptr representing the attribute dictionary
487
(or None if there's a problem)
490
typeobj = self.type()
491
dictoffset = int_from_int(typeobj.field('tp_dictoffset'))
494
type_PyVarObject_ptr = gdb.lookup_type('PyVarObject').pointer()
495
tsize = int_from_int(self._gdbval.cast(type_PyVarObject_ptr)['ob_size'])
498
size = _PyObject_VAR_SIZE(typeobj, tsize)
500
assert dictoffset > 0
501
assert dictoffset % _sizeof_void_p() == 0
503
dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset
504
PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
505
dictptr = dictptr.cast(PyObjectPtrPtr)
506
return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
508
# Corrupt data somewhere; fail safe
511
# Not found, or some kind of error:
514
def proxyval(self, visited):
518
Currently we just locate the dictionary using a transliteration to
519
python of _PyObject_GetDictPtr, ignoring descriptors
521
# Guard against infinite loops:
522
if self.as_address() in visited:
523
return ProxyAlreadyVisited('<...>')
524
visited.add(self.as_address())
526
pyop_attr_dict = self.get_attr_dict()
528
attr_dict = pyop_attr_dict.proxyval(visited)
531
tp_name = self.safe_tp_name()
534
return InstanceProxy(tp_name, attr_dict, int(self._gdbval))
536
def write_repr(self, out, visited):
537
# Guard against infinite loops:
538
if self.as_address() in visited:
541
visited.add(self.as_address())
543
pyop_attrdict = self.get_attr_dict()
544
_write_instance_repr(out, visited,
545
self.safe_tp_name(), pyop_attrdict, self.as_address())
547
class ProxyException(Exception):
548
def __init__(self, tp_name, args):
549
self.tp_name = tp_name
553
return '%s%r' % (self.tp_name, self.args)
555
class PyBaseExceptionObjectPtr(PyObjectPtr):
557
Class wrapping a gdb.Value that's a PyBaseExceptionObject* i.e. an exception
558
within the process being debugged.
560
_typename = 'PyBaseExceptionObject'
562
def proxyval(self, visited):
563
# Guard against infinite loops:
564
if self.as_address() in visited:
565
return ProxyAlreadyVisited('(...)')
566
visited.add(self.as_address())
567
arg_proxy = self.pyop_field('args').proxyval(visited)
568
return ProxyException(self.safe_tp_name(),
571
def write_repr(self, out, visited):
572
# Guard against infinite loops:
573
if self.as_address() in visited:
576
visited.add(self.as_address())
578
out.write(self.safe_tp_name())
579
self.write_field_repr('args', out, visited)
581
class PyClassObjectPtr(PyObjectPtr):
583
Class wrapping a gdb.Value that's a PyClassObject* i.e. a <classobj>
584
instance within the process being debugged.
586
_typename = 'PyClassObject'
589
class BuiltInFunctionProxy:
590
def __init__(self, ml_name):
591
self.ml_name = ml_name
594
return "<built-in function %s>" % self.ml_name
596
class BuiltInMethodProxy:
597
def __init__(self, ml_name, pyop_m_self):
598
self.ml_name = ml_name
599
self.pyop_m_self = pyop_m_self
602
return ('<built-in method %s of %s object at remote 0x%x>'
604
self.pyop_m_self.safe_tp_name(),
605
self.pyop_m_self.as_address())
608
class PyCFunctionObjectPtr(PyObjectPtr):
610
Class wrapping a gdb.Value that's a PyCFunctionObject*
611
(see Include/methodobject.h and Objects/methodobject.c)
613
_typename = 'PyCFunctionObject'
615
def proxyval(self, visited):
616
m_ml = self.field('m_ml') # m_ml is a (PyMethodDef*)
618
ml_name = m_ml['ml_name'].string()
619
except UnicodeDecodeError:
620
ml_name = '<ml_name:UnicodeDecodeError>'
622
pyop_m_self = self.pyop_field('m_self')
623
if pyop_m_self.is_null():
624
return BuiltInFunctionProxy(ml_name)
626
return BuiltInMethodProxy(ml_name, pyop_m_self)
629
class PyCodeObjectPtr(PyObjectPtr):
631
Class wrapping a gdb.Value that's a PyCodeObject* i.e. a <code> instance
632
within the process being debugged.
634
_typename = 'PyCodeObject'
636
def addr2line(self, addrq):
638
Get the line number for a given bytecode offset
640
Analogous to PyCode_Addr2Line; translated from pseudocode in
641
Objects/lnotab_notes.txt
643
co_lnotab = self.pyop_field('co_lnotab').proxyval(set())
645
# Initialize lineno to co_firstlineno as per PyCode_Addr2Line
646
# not 0, as lnotab_notes.txt has it:
647
lineno = int_from_int(self.field('co_firstlineno'))
650
for addr_incr, line_incr in zip(co_lnotab[::2], co_lnotab[1::2]):
651
addr += ord(addr_incr)
654
lineno += ord(line_incr)
658
class PyDictObjectPtr(PyObjectPtr):
660
Class wrapping a gdb.Value that's a PyDictObject* i.e. a dict instance
661
within the process being debugged.
663
_typename = 'PyDictObject'
667
Yields a sequence of (PyObjectPtr key, PyObjectPtr value) pairs,
668
analogous to dict.iteritems()
670
keys = self.field('ma_keys')
671
values = self.field('ma_values')
672
entries, nentries = self._get_entries(keys)
673
for i in safe_range(nentries):
676
pyop_value = PyObjectPtr.from_pyobject_ptr(values[i])
678
pyop_value = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
679
if not pyop_value.is_null():
680
pyop_key = PyObjectPtr.from_pyobject_ptr(ep['me_key'])
681
yield (pyop_key, pyop_value)
683
def proxyval(self, visited):
684
# Guard against infinite loops:
685
if self.as_address() in visited:
686
return ProxyAlreadyVisited('{...}')
687
visited.add(self.as_address())
690
for pyop_key, pyop_value in self.iteritems():
691
proxy_key = pyop_key.proxyval(visited)
692
proxy_value = pyop_value.proxyval(visited)
693
result[proxy_key] = proxy_value
696
def write_repr(self, out, visited):
697
# Guard against infinite loops:
698
if self.as_address() in visited:
701
visited.add(self.as_address())
705
for pyop_key, pyop_value in self.iteritems():
709
pyop_key.write_repr(out, visited)
711
pyop_value.write_repr(out, visited)
714
def _get_entries(self, keys):
715
dk_nentries = int(keys['dk_nentries'])
716
dk_size = int(keys['dk_size'])
719
return keys['dk_entries'], dk_size
726
elif dk_size <= 0xFFFF:
728
elif dk_size <= 0xFFFFFFFF:
733
ent_addr = keys['dk_indices'].address
734
ent_addr = ent_addr.cast(_type_unsigned_char_ptr()) + offset
735
ent_ptr_t = gdb.lookup_type('PyDictKeyEntry').pointer()
736
ent_addr = ent_addr.cast(ent_ptr_t)
738
return ent_addr, dk_nentries
741
class PyListObjectPtr(PyObjectPtr):
742
_typename = 'PyListObject'
744
def __getitem__(self, i):
745
# Get the gdb.Value for the (PyObject*) with the given index:
746
field_ob_item = self.field('ob_item')
747
return field_ob_item[i]
749
def proxyval(self, visited):
750
# Guard against infinite loops:
751
if self.as_address() in visited:
752
return ProxyAlreadyVisited('[...]')
753
visited.add(self.as_address())
755
result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
756
for i in safe_range(int_from_int(self.field('ob_size')))]
759
def write_repr(self, out, visited):
760
# Guard against infinite loops:
761
if self.as_address() in visited:
764
visited.add(self.as_address())
767
for i in safe_range(int_from_int(self.field('ob_size'))):
770
element = PyObjectPtr.from_pyobject_ptr(self[i])
771
element.write_repr(out, visited)
774
class PyLongObjectPtr(PyObjectPtr):
775
_typename = 'PyLongObject'
777
def proxyval(self, visited):
779
Python's Include/longobjrep.h has this declaration:
785
with this description:
786
The absolute value of a number is equal to
787
SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
788
Negative numbers are represented with ob_size < 0;
789
zero is represented by ob_size == 0.
791
where SHIFT can be either:
792
#define PyLong_SHIFT 30
793
#define PyLong_SHIFT 15
795
ob_size = int(self.field('ob_size'))
799
ob_digit = self.field('ob_digit')
801
if gdb.lookup_type('digit').sizeof == 2:
806
digits = [int(ob_digit[i]) * 2**(SHIFT*i)
807
for i in safe_range(abs(ob_size))]
813
def write_repr(self, out, visited):
814
# Write this out as a Python 3 int literal, i.e. without the "L" suffix
815
proxy = self.proxyval(visited)
816
out.write("%s" % proxy)
819
class PyBoolObjectPtr(PyLongObjectPtr):
821
Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
822
<bool> instances (Py_True/Py_False) within the process being debugged.
824
def proxyval(self, visited):
825
if PyLongObjectPtr.proxyval(self, visited):
830
class PyNoneStructPtr(PyObjectPtr):
832
Class wrapping a gdb.Value that's a PyObject* pointing to the
833
singleton (we hope) _Py_NoneStruct with ob_type PyNone_Type
835
_typename = 'PyObject'
837
def proxyval(self, visited):
841
class PyFrameObjectPtr(PyObjectPtr):
842
_typename = 'PyFrameObject'
844
def __init__(self, gdbval, cast_to=None):
845
PyObjectPtr.__init__(self, gdbval, cast_to)
847
if not self.is_optimized_out():
848
self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
849
self.co_name = self.co.pyop_field('co_name')
850
self.co_filename = self.co.pyop_field('co_filename')
852
self.f_lineno = int_from_int(self.field('f_lineno'))
853
self.f_lasti = int_from_int(self.field('f_lasti'))
854
self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
855
self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
857
def iter_locals(self):
859
Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
860
the local variables of this frame
862
if self.is_optimized_out():
865
f_localsplus = self.field('f_localsplus')
866
for i in safe_range(self.co_nlocals):
867
pyop_value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
868
if not pyop_value.is_null():
869
pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_varnames[i])
870
yield (pyop_name, pyop_value)
872
def iter_globals(self):
874
Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
875
the global variables of this frame
877
if self.is_optimized_out():
880
pyop_globals = self.pyop_field('f_globals')
881
return pyop_globals.iteritems()
883
def iter_builtins(self):
885
Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
886
the builtin variables
888
if self.is_optimized_out():
891
pyop_builtins = self.pyop_field('f_builtins')
892
return pyop_builtins.iteritems()
894
def get_var_by_name(self, name):
896
Look for the named local variable, returning a (PyObjectPtr, scope) pair
897
where scope is a string 'local', 'global', 'builtin'
899
If not found, return (None, None)
901
for pyop_name, pyop_value in self.iter_locals():
902
if name == pyop_name.proxyval(set()):
903
return pyop_value, 'local'
904
for pyop_name, pyop_value in self.iter_globals():
905
if name == pyop_name.proxyval(set()):
906
return pyop_value, 'global'
907
for pyop_name, pyop_value in self.iter_builtins():
908
if name == pyop_name.proxyval(set()):
909
return pyop_value, 'builtin'
913
'''Get the path of the current Python source file, as a string'''
914
if self.is_optimized_out():
915
return FRAME_INFO_OPTIMIZED_OUT
916
return self.co_filename.proxyval(set())
918
def current_line_num(self):
919
'''Get current line number as an integer (1-based)
921
Translated from PyFrame_GetLineNumber and PyCode_Addr2Line
923
See Objects/lnotab_notes.txt
925
if self.is_optimized_out():
927
f_trace = self.field('f_trace')
928
if int(f_trace) != 0:
929
# we have a non-NULL f_trace:
933
return self.co.addr2line(self.f_lasti)
935
# bpo-34989: addr2line() is a complex function, it can fail in many
936
# ways. For example, it fails with a TypeError on "FakeRepr" if
937
# gdb fails to load debug symbols. Use a catch-all "except
938
# Exception" to make the whole function safe. The caller has to
939
# handle None anyway for optimized Python.
942
def current_line(self):
943
'''Get the text of the current source line as a string, with a trailing
945
if self.is_optimized_out():
946
return FRAME_INFO_OPTIMIZED_OUT
948
lineno = self.current_line_num()
950
return '(failed to get frame line number)'
952
filename = self.filename()
954
with open(os_fsencode(filename)) as fp:
955
lines = fp.readlines()
960
# Convert from 1-based current_line_num to 0-based list offset
961
return lines[lineno - 1]
965
def write_repr(self, out, visited):
966
if self.is_optimized_out():
967
out.write(FRAME_INFO_OPTIMIZED_OUT)
969
lineno = self.current_line_num()
970
lineno = str(lineno) if lineno is not None else "?"
971
out.write('Frame 0x%x, for file %s, line %s, in %s ('
972
% (self.as_address(),
973
self.co_filename.proxyval(visited),
975
self.co_name.proxyval(visited)))
977
for pyop_name, pyop_value in self.iter_locals():
982
out.write(pyop_name.proxyval(visited))
984
pyop_value.write_repr(out, visited)
988
def print_traceback(self):
989
if self.is_optimized_out():
990
sys.stdout.write(' %s\n' % FRAME_INFO_OPTIMIZED_OUT)
993
lineno = self.current_line_num()
994
lineno = str(lineno) if lineno is not None else "?"
995
sys.stdout.write(' File "%s", line %s, in %s\n'
996
% (self.co_filename.proxyval(visited),
998
self.co_name.proxyval(visited)))
1000
class PySetObjectPtr(PyObjectPtr):
1001
_typename = 'PySetObject'
1004
def _dummy_key(self):
1005
return gdb.lookup_global_symbol('_PySet_Dummy').value()
1008
dummy_ptr = self._dummy_key()
1009
table = self.field('table')
1010
for i in safe_range(self.field('mask') + 1):
1012
key = setentry['key']
1013
if key != 0 and key != dummy_ptr:
1014
yield PyObjectPtr.from_pyobject_ptr(key)
1016
def proxyval(self, visited):
1017
# Guard against infinite loops:
1018
if self.as_address() in visited:
1019
return ProxyAlreadyVisited('%s(...)' % self.safe_tp_name())
1020
visited.add(self.as_address())
1022
members = (key.proxyval(visited) for key in self)
1023
if self.safe_tp_name() == 'frozenset':
1024
return frozenset(members)
1028
def write_repr(self, out, visited):
1029
# Emulate Python 3's set_repr
1030
tp_name = self.safe_tp_name()
1032
# Guard against infinite loops:
1033
if self.as_address() in visited:
1036
visited.add(self.as_address())
1038
# Python 3's set_repr special-cases the empty set:
1039
if not self.field('used'):
1044
# Python 3 uses {} for set literals:
1045
if tp_name != 'set':
1055
key.write_repr(out, visited)
1058
if tp_name != 'set':
1062
class PyBytesObjectPtr(PyObjectPtr):
1063
_typename = 'PyBytesObject'
1066
field_ob_size = self.field('ob_size')
1067
field_ob_sval = self.field('ob_sval')
1068
char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr())
1069
return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
1071
def proxyval(self, visited):
1074
def write_repr(self, out, visited):
1075
# Write this out as a Python 3 bytes literal, i.e. with a "b" prefix
1077
# Get a PyStringObject* within the Python 2 gdb process:
1078
proxy = self.proxyval(visited)
1080
# Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr
1083
if "'" in proxy and not '"' in proxy:
1088
if byte == quote or byte == '\\':
1097
elif byte < ' ' or ord(byte) >= 0x7f:
1099
out.write(hexdigits[(ord(byte) & 0xf0) >> 4])
1100
out.write(hexdigits[ord(byte) & 0xf])
1105
class PyTupleObjectPtr(PyObjectPtr):
1106
_typename = 'PyTupleObject'
1108
def __getitem__(self, i):
1109
# Get the gdb.Value for the (PyObject*) with the given index:
1110
field_ob_item = self.field('ob_item')
1111
return field_ob_item[i]
1113
def proxyval(self, visited):
1114
# Guard against infinite loops:
1115
if self.as_address() in visited:
1116
return ProxyAlreadyVisited('(...)')
1117
visited.add(self.as_address())
1119
result = tuple(PyObjectPtr.from_pyobject_ptr(self[i]).proxyval(visited)
1120
for i in safe_range(int_from_int(self.field('ob_size'))))
1123
def write_repr(self, out, visited):
1124
# Guard against infinite loops:
1125
if self.as_address() in visited:
1128
visited.add(self.as_address())
1131
for i in safe_range(int_from_int(self.field('ob_size'))):
1134
element = PyObjectPtr.from_pyobject_ptr(self[i])
1135
element.write_repr(out, visited)
1136
if self.field('ob_size') == 1:
1141
class PyTypeObjectPtr(PyObjectPtr):
1142
_typename = 'PyTypeObject'
1145
def _unichr_is_printable(char):
1146
# Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
1150
return unicodedata.category(char) not in ("C", "Z")
1153
class PyUnicodeObjectPtr(PyObjectPtr):
1154
_typename = 'PyUnicodeObject'
1156
def char_width(self):
1157
_type_Py_UNICODE = gdb.lookup_type('Py_UNICODE')
1158
return _type_Py_UNICODE.sizeof
1160
def proxyval(self, visited):
1162
if _is_pep393 is None:
1163
fields = gdb.lookup_type('PyUnicodeObject').fields()
1164
_is_pep393 = 'data' in [f.name for f in fields]
1166
# Python 3.3 and newer
1167
may_have_surrogates = False
1168
compact = self.field('_base')
1169
ascii = compact['_base']
1170
state = ascii['state']
1171
is_compact_ascii = (int(state['ascii']) and int(state['compact']))
1172
if not int(state['ready']):
1173
# string is not ready
1174
field_length = int(compact['wstr_length'])
1175
may_have_surrogates = True
1176
field_str = ascii['wstr']
1178
field_length = int(ascii['length'])
1179
if is_compact_ascii:
1180
field_str = ascii.address + 1
1181
elif int(state['compact']):
1182
field_str = compact.address + 1
1184
field_str = self.field('data')['any']
1185
repr_kind = int(state['kind'])
1187
field_str = field_str.cast(_type_unsigned_char_ptr())
1188
elif repr_kind == 2:
1189
field_str = field_str.cast(_type_unsigned_short_ptr())
1190
elif repr_kind == 4:
1191
field_str = field_str.cast(_type_unsigned_int_ptr())
1193
# Python 3.2 and earlier
1194
field_length = int(self.field('length'))
1195
field_str = self.field('str')
1196
may_have_surrogates = self.char_width() == 2
1198
# Gather a list of ints from the Py_UNICODE array; these are either
1199
# UCS-1, UCS-2 or UCS-4 code points:
1200
if not may_have_surrogates:
1201
Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
1203
# A more elaborate routine if sizeof(Py_UNICODE) is 2 in the
1204
# inferior process: we must join surrogate pairs.
1207
limit = safety_limit(field_length)
1209
ucs = int(field_str[i])
1211
if ucs < 0xD800 or ucs >= 0xDC00 or i == field_length:
1212
Py_UNICODEs.append(ucs)
1214
# This could be a surrogate pair.
1215
ucs2 = int(field_str[i])
1216
if ucs2 < 0xDC00 or ucs2 > 0xDFFF:
1218
code = (ucs & 0x03FF) << 10
1219
code |= ucs2 & 0x03FF
1221
Py_UNICODEs.append(code)
1224
# Convert the int code points to unicode characters, and generate a
1225
# local unicode instance.
1226
# This splits surrogate pairs if sizeof(Py_UNICODE) is 2 here (in gdb).
1228
(chr(ucs) if ucs <= 0x10ffff else '\ufffd')
1229
for ucs in Py_UNICODEs])
1232
def write_repr(self, out, visited):
1233
# Write this out as a Python 3 str literal, i.e. without a "u" prefix
1235
# Get a PyUnicodeObject* within the Python 2 gdb process:
1236
proxy = self.proxyval(visited)
1238
# Transliteration of Python 3's Object/unicodeobject.c:unicode_repr
1240
if "'" in proxy and '"' not in proxy:
1247
while i < len(proxy):
1251
# Escape quotes and backslashes
1252
if ch == quote or ch == '\\':
1256
# Map special whitespace to '\t', \n', '\r'
1264
# Map non-printable US ASCII to '\xhh' */
1265
elif ch < ' ' or ch == 0x7F:
1267
out.write(hexdigits[(ord(ch) >> 4) & 0x000F])
1268
out.write(hexdigits[ord(ch) & 0x000F])
1270
# Copy ASCII characters as-is
1271
elif ord(ch) < 0x7F:
1274
# Non-ASCII characters
1278
if sys.maxunicode < 0x10000:
1279
# If sizeof(Py_UNICODE) is 2 here (in gdb), join
1280
# surrogate pairs before calling _unichr_is_printable.
1282
and 0xD800 <= ord(ch) < 0xDC00
1283
and 0xDC00 <= ord(proxy[i]) <= 0xDFFF):
1288
# Unfortunately, Python 2's unicode type doesn't seem
1289
# to expose the "isprintable" method
1290
printable = _unichr_is_printable(ucs)
1293
ucs.encode(ENCODING)
1294
except UnicodeEncodeError:
1297
# Map Unicode whitespace and control characters
1298
# (categories Z* and C* except ASCII space)
1301
# Match Python 3's representation of non-printable
1303
code = (ord(ch) & 0x03FF) << 10
1304
code |= ord(ch2) & 0x03FF
1309
# Map 8-bit characters to '\\xhh'
1312
out.write(hexdigits[(code >> 4) & 0x000F])
1313
out.write(hexdigits[code & 0x000F])
1314
# Map 21-bit characters to '\U00xxxxxx'
1315
elif code >= 0x10000:
1317
out.write(hexdigits[(code >> 28) & 0x0000000F])
1318
out.write(hexdigits[(code >> 24) & 0x0000000F])
1319
out.write(hexdigits[(code >> 20) & 0x0000000F])
1320
out.write(hexdigits[(code >> 16) & 0x0000000F])
1321
out.write(hexdigits[(code >> 12) & 0x0000000F])
1322
out.write(hexdigits[(code >> 8) & 0x0000000F])
1323
out.write(hexdigits[(code >> 4) & 0x0000000F])
1324
out.write(hexdigits[code & 0x0000000F])
1325
# Map 16-bit characters to '\uxxxx'
1328
out.write(hexdigits[(code >> 12) & 0x000F])
1329
out.write(hexdigits[(code >> 8) & 0x000F])
1330
out.write(hexdigits[(code >> 4) & 0x000F])
1331
out.write(hexdigits[code & 0x000F])
1333
# Copy characters as-is
1341
class wrapperobject(PyObjectPtr):
1342
_typename = 'wrapperobject'
1344
def safe_name(self):
1346
name = self.field('descr')['d_base']['name'].string()
1348
except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
1349
return '<unknown name>'
1351
def safe_tp_name(self):
1353
return self.field('self')['ob_type']['tp_name'].string()
1354
except (NullPyObjectPtr, RuntimeError, UnicodeDecodeError):
1355
return '<unknown tp_name>'
1357
def safe_self_addresss(self):
1359
address = int(self.field('self'))
1360
return '%#x' % address
1361
except (NullPyObjectPtr, RuntimeError):
1362
return '<failed to get self address>'
1364
def proxyval(self, visited):
1365
name = self.safe_name()
1366
tp_name = self.safe_tp_name()
1367
self_address = self.safe_self_addresss()
1368
return ("<method-wrapper %s of %s object at %s>"
1369
% (name, tp_name, self_address))
1371
def write_repr(self, out, visited):
1372
proxy = self.proxyval(visited)
1376
def int_from_int(gdbval):
1381
# TODO: repr() puts everything on one line; pformat can be nicer, but
1382
# can lead to v.long results; this function isolates the choice
1386
from pprint import pformat
1390
class PyObjectPtrPrinter:
1391
"Prints a (PyObject*)"
1393
def __init__ (self, gdbval):
1394
self.gdbval = gdbval
1396
def to_string (self):
1397
pyop = PyObjectPtr.from_pyobject_ptr(self.gdbval)
1399
return pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1401
# Generate full proxy value then stringify it.
1402
# Doing so could be expensive
1403
proxyval = pyop.proxyval(set())
1404
return stringify(proxyval)
1406
def pretty_printer_lookup(gdbval):
1407
type = gdbval.type.unqualified()
1408
if type.code != gdb.TYPE_CODE_PTR:
1411
type = type.target().unqualified()
1413
if t in ("PyObject", "PyFrameObject", "PyUnicodeObject", "wrapperobject"):
1414
return PyObjectPtrPrinter(gdbval)
1417
During development, I've been manually invoking the code in this way:
1421
sys.path.append('/home/david/coding/python-gdb')
1425
then reloading it after each edit like this:
1426
(gdb) python reload(libpython)
1428
The following code should ensure that the prettyprinter is registered
1429
if the code is autoloaded by gdb when visiting libpython.so, provided
1430
that this python file is installed to the same path as the library (or its
1431
.debug file) plus a "-gdb.py" suffix, e.g:
1432
/usr/lib/libpython2.6.so.1.0-gdb.py
1433
/usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py
1439
# Wire up the pretty-printer
1440
obj.pretty_printers.append(pretty_printer_lookup)
1442
register (gdb.current_objfile ())
1446
# Unfortunately, the exact API exposed by the gdb module varies somewhat
1447
# from build to build
1448
# See http://bugs.python.org/issue8279?#msg102276
1452
Wrapper for gdb.Frame, adding various methods
1454
def __init__(self, gdbframe):
1455
self._gdbframe = gdbframe
1458
older = self._gdbframe.older()
1465
newer = self._gdbframe.newer()
1472
'''If supported, select this frame and return True; return False if unsupported
1474
Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12
1475
onwards, but absent on Ubuntu buildbot'''
1476
if not hasattr(self._gdbframe, 'select'):
1477
print ('Unable to select frame: '
1478
'this build of gdb does not expose a gdb.Frame.select method')
1480
self._gdbframe.select()
1483
def get_index(self):
1484
'''Calculate index of frame, starting at 0 for the newest frame within
1487
# Go down until you reach the newest frame:
1489
while iter_frame.newer():
1491
iter_frame = iter_frame.newer()
1494
# We divide frames into:
1495
# - "python frames":
1496
# - "bytecode frames" i.e. PyEval_EvalFrameEx
1497
# - "other python frames": things that are of interest from a python
1498
# POV, but aren't bytecode (e.g. GC, GIL)
1501
def is_python_frame(self):
1502
'''Is this a _PyEval_EvalFrameDefault frame, or some other important
1503
frame? (see is_other_python_frame for what "important" means in this
1505
if self.is_evalframe():
1507
if self.is_other_python_frame():
1511
def is_evalframe(self):
1512
'''Is this a _PyEval_EvalFrameDefault frame?'''
1513
if self._gdbframe.name() == EVALFRAME:
1515
I believe we also need to filter on the inline
1516
struct frame_id.inline_depth, only regarding frames with
1517
an inline depth of 0 as actually being this function
1519
So we reject those with type gdb.INLINE_FRAME
1521
if self._gdbframe.type() == gdb.NORMAL_FRAME:
1522
# We have a _PyEval_EvalFrameDefault frame:
1527
def is_other_python_frame(self):
1528
'''Is this frame worth displaying in python backtraces?
1530
- waiting on the GIL
1531
- garbage-collecting
1532
- within a CFunction
1533
If it is, return a descriptive string
1534
For other frames, return False
1536
if self.is_waiting_for_gil():
1537
return 'Waiting for the GIL'
1539
if self.is_gc_collect():
1540
return 'Garbage-collecting'
1542
# Detect invocations of PyCFunction instances:
1543
frame = self._gdbframe
1544
caller = frame.name()
1548
if (caller.startswith('cfunction_vectorcall_') or
1549
caller == 'cfunction_call'):
1551
# Within that frame:
1552
# "func" is the local containing the PyObject* of the
1553
# PyCFunctionObject instance
1554
# "f" is the same value, but cast to (PyCFunctionObject*)
1555
# "self" is the (PyObject*) of the 'self'
1557
# Use the prettyprinter for the func:
1558
func = frame.read_var(arg_name)
1561
return ('PyCFunction invocation (unable to read %s: '
1562
'missing debuginfos?)' % arg_name)
1563
except RuntimeError:
1564
return 'PyCFunction invocation (unable to read %s)' % arg_name
1566
if caller == 'wrapper_call':
1569
func = frame.read_var(arg_name)
1572
return ('<wrapper_call invocation (unable to read %s: '
1573
'missing debuginfos?)>' % arg_name)
1574
except RuntimeError:
1575
return '<wrapper_call invocation (unable to read %s)>' % arg_name
1577
# This frame isn't worth reporting:
1580
def is_waiting_for_gil(self):
1581
'''Is this frame waiting on the GIL?'''
1582
# This assumes the _POSIX_THREADS version of Python/ceval_gil.h:
1583
name = self._gdbframe.name()
1585
return (name == 'take_gil')
1587
def is_gc_collect(self):
1588
'''Is this frame "collect" within the garbage-collector?'''
1589
return self._gdbframe.name() == 'collect'
1593
f = self._gdbframe.read_var('f')
1594
frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1595
if not frame.is_optimized_out():
1597
# gdb is unable to get the "f" argument of PyEval_EvalFrameEx()
1598
# because it was "optimized out". Try to get "f" from the frame
1599
# of the caller, PyEval_EvalCodeEx().
1601
caller = self._gdbframe.older()
1603
f = caller.read_var('f')
1604
frame = PyFrameObjectPtr.from_pyobject_ptr(f)
1605
if not frame.is_optimized_out():
1612
def get_selected_frame(cls):
1613
_gdbframe = gdb.selected_frame()
1615
return Frame(_gdbframe)
1619
def get_selected_python_frame(cls):
1620
'''Try to obtain the Frame for the python-related code in the selected
1623
frame = cls.get_selected_frame()
1625
# No frame: Python didn't start yet
1629
if frame.is_python_frame():
1631
frame = frame.older()
1637
def get_selected_bytecode_frame(cls):
1638
'''Try to obtain the Frame for the python bytecode interpreter in the
1639
selected GDB frame, or None'''
1640
frame = cls.get_selected_frame()
1643
if frame.is_evalframe():
1645
frame = frame.older()
1650
def print_summary(self):
1651
if self.is_evalframe():
1652
pyop = self.get_pyop()
1654
line = pyop.get_truncated_repr(MAX_OUTPUT_LEN)
1655
write_unicode(sys.stdout, '#%i %s\n' % (self.get_index(), line))
1656
if not pyop.is_optimized_out():
1657
line = pyop.current_line()
1658
if line is not None:
1659
sys.stdout.write(' %s\n' % line.strip())
1661
sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
1663
info = self.is_other_python_frame()
1665
sys.stdout.write('#%i %s\n' % (self.get_index(), info))
1667
sys.stdout.write('#%i\n' % self.get_index())
1669
def print_traceback(self):
1670
if self.is_evalframe():
1671
pyop = self.get_pyop()
1673
pyop.print_traceback()
1674
if not pyop.is_optimized_out():
1675
line = pyop.current_line()
1676
if line is not None:
1677
sys.stdout.write(' %s\n' % line.strip())
1679
sys.stdout.write(' (unable to read python frame information)\n')
1681
info = self.is_other_python_frame()
1683
sys.stdout.write(' %s\n' % info)
1685
sys.stdout.write(' (not a python frame)\n')
1687
class PyList(gdb.Command):
1688
'''List the current Python source code, if any
1692
to list at a different line number within the python source.
1696
to list a specific range of lines within the python source.
1700
gdb.Command.__init__ (self,
1706
def invoke(self, args, from_tty):
1712
m = re.match(r'\s*(\d+)\s*', args)
1714
start = int(m.group(0))
1717
m = re.match(r'\s*(\d+)\s*,\s*(\d+)\s*', args)
1719
start, end = map(int, m.groups())
1721
# py-list requires an actual PyEval_EvalFrameEx frame:
1722
frame = Frame.get_selected_bytecode_frame()
1724
print('Unable to locate gdb frame for python bytecode interpreter')
1727
pyop = frame.get_pyop()
1728
if not pyop or pyop.is_optimized_out():
1729
print(UNABLE_READ_INFO_PYTHON_FRAME)
1732
filename = pyop.filename()
1733
lineno = pyop.current_line_num()
1735
print('Unable to read python frame line number')
1746
f = open(os_fsencode(filename))
1747
except OSError as err:
1748
sys.stdout.write('Unable to open %s: %s\n'
1752
all_lines = f.readlines()
1753
# start and end are 1-based, all_lines is 0-based;
1754
# so [start-1:end] as a python slice gives us [start, end] as a
1756
for i, line in enumerate(all_lines[start-1:end]):
1757
linestr = str(i+start)
1758
# Highlight current line:
1759
if i + start == lineno:
1760
linestr = '>' + linestr
1761
sys.stdout.write('%4s %s' % (linestr, line))
1764
# ...and register the command:
1767
def move_in_stack(move_up):
1768
'''Move up or down the stack (for the py-up/py-down command)'''
1769
frame = Frame.get_selected_python_frame()
1771
print('Unable to locate python frame')
1776
iter_frame = frame.older()
1778
iter_frame = frame.newer()
1783
if iter_frame.is_python_frame():
1785
if iter_frame.select():
1786
iter_frame.print_summary()
1792
print('Unable to find an older python frame')
1794
print('Unable to find a newer python frame')
1796
class PyUp(gdb.Command):
1797
'Select and print the python stack frame that called this one (if any)'
1799
gdb.Command.__init__ (self,
1805
def invoke(self, args, from_tty):
1806
move_in_stack(move_up=True)
1808
class PyDown(gdb.Command):
1809
'Select and print the python stack frame called by this one (if any)'
1811
gdb.Command.__init__ (self,
1817
def invoke(self, args, from_tty):
1818
move_in_stack(move_up=False)
1820
# Not all builds of gdb have gdb.Frame.select
1821
if hasattr(gdb.Frame, 'select'):
1825
class PyBacktraceFull(gdb.Command):
1826
'Display the current python frame and all the frames within its call stack (if any)'
1828
gdb.Command.__init__ (self,
1834
def invoke(self, args, from_tty):
1835
frame = Frame.get_selected_python_frame()
1837
print('Unable to locate python frame')
1841
if frame.is_python_frame():
1842
frame.print_summary()
1843
frame = frame.older()
1847
class PyBacktrace(gdb.Command):
1848
'Display the current python frame and all the frames within its call stack (if any)'
1850
gdb.Command.__init__ (self,
1856
def invoke(self, args, from_tty):
1857
frame = Frame.get_selected_python_frame()
1859
print('Unable to locate python frame')
1862
sys.stdout.write('Traceback (most recent call first):\n')
1864
if frame.is_python_frame():
1865
frame.print_traceback()
1866
frame = frame.older()
1870
class PyPrint(gdb.Command):
1871
'Look up the given python variable name, and print it'
1873
gdb.Command.__init__ (self,
1879
def invoke(self, args, from_tty):
1882
frame = Frame.get_selected_python_frame()
1884
print('Unable to locate python frame')
1887
pyop_frame = frame.get_pyop()
1889
print(UNABLE_READ_INFO_PYTHON_FRAME)
1892
pyop_var, scope = pyop_frame.get_var_by_name(name)
1898
pyop_var.get_truncated_repr(MAX_OUTPUT_LEN)))
1900
print('%r not found' % name)
1904
class PyLocals(gdb.Command):
1905
'Look up the given python variable name, and print it'
1907
gdb.Command.__init__ (self,
1913
def invoke(self, args, from_tty):
1916
frame = Frame.get_selected_python_frame()
1918
print('Unable to locate python frame')
1921
pyop_frame = frame.get_pyop()
1923
print(UNABLE_READ_INFO_PYTHON_FRAME)
1926
for pyop_name, pyop_value in pyop_frame.iter_locals():
1928
pyop_name.proxyval(set()),
1929
pyop_value.get_truncated_repr(MAX_OUTPUT_LEN),
1935
##################################################################
1936
## added, not in CPython
1937
##################################################################
1948
def dont_suppress_errors(function):
1950
@functools.wraps(function)
1951
def wrapper(*args, **kwargs):
1953
return function(*args, **kwargs)
1955
traceback.print_exc()
1960
class PyGlobals(gdb.Command):
1961
'List all the globals in the currently select Python frame'
1963
gdb.Command.__init__ (self,
1968
@dont_suppress_errors
1969
def invoke(self, args, from_tty):
1972
frame = Frame.get_selected_python_frame()
1974
print('Unable to locate python frame')
1977
pyop_frame = frame.get_pyop()
1979
print(UNABLE_READ_INFO_PYTHON_FRAME)
1982
for pyop_name, pyop_value in pyop_frame.iter_locals():
1984
% (pyop_name.proxyval(set()),
1985
pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
1987
def get_namespace(self, pyop_frame):
1988
return pyop_frame.iter_globals()
1993
# This function used to be a part of CPython's libpython.py (as a member function of frame).
1994
# It isn't anymore, so I copied it.
1995
def is_evalframeex(frame):
1996
'''Is this a PyEval_EvalFrameEx frame?'''
1997
if frame._gdbframe.name() == 'PyEval_EvalFrameEx':
1999
I believe we also need to filter on the inline
2000
struct frame_id.inline_depth, only regarding frames with
2001
an inline depth of 0 as actually being this function
2003
So we reject those with type gdb.INLINE_FRAME
2005
if frame._gdbframe.type() == gdb.NORMAL_FRAME:
2006
# We have a PyEval_EvalFrameEx frame:
2011
class PyNameEquals(gdb.Function):
2013
def _get_pycurframe_attr(self, attr):
2014
frame = Frame(gdb.selected_frame())
2015
if is_evalframeex(frame):
2016
pyframe = frame.get_pyop()
2018
warnings.warn("Use a Python debug build, Python breakpoints "
2019
"won't work otherwise.")
2022
return getattr(pyframe, attr).proxyval(set())
2026
@dont_suppress_errors
2027
def invoke(self, funcname):
2028
attr = self._get_pycurframe_attr('co_name')
2029
return attr is not None and attr == funcname.string()
2031
PyNameEquals("pyname_equals")
2034
class PyModEquals(PyNameEquals):
2036
@dont_suppress_errors
2037
def invoke(self, modname):
2038
attr = self._get_pycurframe_attr('co_filename')
2039
if attr is not None:
2040
filename, ext = os.path.splitext(os.path.basename(attr))
2041
return filename == modname.string()
2044
PyModEquals("pymod_equals")
2047
class PyBreak(gdb.Command):
2049
Set a Python breakpoint. Examples:
2051
Break on any function or method named 'func' in module 'modname'
2053
py-break modname.func
2055
Break on any function or method named 'func'
2060
@dont_suppress_errors
2061
def invoke(self, funcname, from_tty):
2063
modname, dot, funcname = funcname.rpartition('.')
2064
cond = '$pyname_equals("%s") && $pymod_equals("%s")' % (funcname,
2067
cond = '$pyname_equals("%s")' % funcname
2069
gdb.execute('break PyEval_EvalFrameEx if ' + cond)
2071
PyBreak("py-break", gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE)
2076
State that helps to provide a reentrant gdb.execute() function.
2080
f = tempfile.NamedTemporaryFile('r+')
2082
self.filename = f.name
2083
self.fd = f.fileno()
2084
_execute("set logging file %s" % self.filename)
2085
self.file_position_stack = []
2087
def __enter__(self):
2088
if not self.file_position_stack:
2089
_execute("set logging redirect on")
2090
_execute("set logging on")
2091
_execute("set pagination off")
2093
self.file_position_stack.append(os.fstat(self.fd).st_size)
2096
def getoutput(self):
2098
self.file.seek(self.file_position_stack[-1])
2099
result = self.file.read()
2102
def __exit__(self, exc_type, exc_val, tb):
2103
startpos = self.file_position_stack.pop()
2104
self.file.seek(startpos)
2105
self.file.truncate()
2106
if not self.file_position_stack:
2107
_execute("set logging off")
2108
_execute("set logging redirect off")
2109
_execute("set pagination on")
2112
def execute(command, from_tty=False, to_string=False):
2114
Replace gdb.execute() with this function and have it accept a 'to_string'
2115
argument (new in 7.2). Have it properly capture stderr also. Ensure
2119
with _logging_state as state:
2120
_execute(command, from_tty)
2121
return state.getoutput()
2123
_execute(command, from_tty)
2126
_execute = gdb.execute
2127
gdb.execute = execute
2128
_logging_state = _LoggingState()
2131
def get_selected_inferior():
2133
Return the selected inferior in gdb.
2135
# Woooh, another bug in gdb! Is there an end in sight?
2136
# http://sourceware.org/bugzilla/show_bug.cgi?id=12212
2137
return gdb.inferiors()[0]
2139
selected_thread = gdb.selected_thread()
2141
for inferior in gdb.inferiors():
2142
for thread in inferior.threads():
2143
if thread == selected_thread:
2147
def source_gdb_script(script_contents, to_string=False):
2149
Source a gdb script with script_contents passed as a string. This is useful
2150
to provide defines for py-step and py-next to make them repeatable (this is
2151
not possible with gdb.execute()). See
2152
http://sourceware.org/bugzilla/show_bug.cgi?id=12216
2154
fd, filename = tempfile.mkstemp()
2155
f = os.fdopen(fd, 'w')
2156
f.write(script_contents)
2158
gdb.execute("source %s" % filename, to_string=to_string)
2162
def register_defines():
2163
source_gdb_script(textwrap.dedent("""\
2179
""") % (PyStep.__doc__, PyNext.__doc__))
2182
def stackdepth(frame):
2183
"Tells the stackdepth of a gdb frame."
2186
frame = frame.older()
2192
class ExecutionControlCommandBase(gdb.Command):
2194
Superclass for language specific execution control. Language specific
2195
features should be implemented by lang_info using the LanguageInfo
2196
interface. 'name' is the name of the command.
2199
def __init__(self, name, lang_info):
2201
name, gdb.COMMAND_RUNNING, gdb.COMPLETE_NONE)
2202
self.lang_info = lang_info
2204
def install_breakpoints(self):
2205
all_locations = itertools.chain(
2206
self.lang_info.static_break_functions(),
2207
self.lang_info.runtime_break_functions())
2209
for location in all_locations:
2210
result = gdb.execute('break %s' % location, to_string=True)
2211
yield re.search(r'Breakpoint (\d+)', result).group(1)
2213
def delete_breakpoints(self, breakpoint_list):
2214
for bp in breakpoint_list:
2215
gdb.execute("delete %s" % bp)
2217
def filter_output(self, result):
2218
reflags = re.MULTILINE
2221
(r'^Program received signal .*', reflags|re.DOTALL),
2222
(r'.*[Ww]arning.*', 0),
2223
(r'^Program exited .*', reflags),
2227
# output when halting on a watchpoint
2228
(r'^(Old|New) value = .*', reflags),
2229
# output from the 'display' command
2230
(r'^\d+: \w+ = .*', reflags),
2233
def filter_output(regexes):
2235
for regex, flags in regexes:
2236
for match in re.finditer(regex, result, flags):
2237
output.append(match.group(0))
2239
return '\n'.join(output)
2241
# Filter the return value output of the 'finish' command
2242
match_finish = re.search(r'^Value returned is \$\d+ = (.*)', result,
2245
finish_output = 'Value returned: %s\n' % match_finish.group(1)
2249
return (filter_output(output_on_halt),
2250
finish_output + filter_output(output_always))
2253
return get_selected_inferior().pid == 0
2255
def finish_executing(self, result):
2257
After doing some kind of code running in the inferior, print the line
2258
of source code or the result of the last executed gdb command (passed
2259
in as the `result` argument).
2261
output_on_halt, output_always = self.filter_output(result)
2264
print(output_always)
2265
print(output_on_halt)
2267
frame = gdb.selected_frame()
2268
source_line = self.lang_info.get_source_line(frame)
2269
if self.lang_info.is_relevant_function(frame):
2270
raised_exception = self.lang_info.exc_info(frame)
2271
if raised_exception:
2272
print(raised_exception)
2275
if output_always.rstrip():
2276
print(output_always.rstrip())
2283
Execute until the function returns (or until something else makes it
2286
if gdb.selected_frame().older() is not None:
2287
return gdb.execute('finish', to_string=True)
2289
# outermost frame, continue
2290
return gdb.execute('cont', to_string=True)
2292
def _finish_frame(self):
2294
Execute until the function returns to a relevant caller.
2297
result = self._finish()
2300
frame = gdb.selected_frame()
2301
except RuntimeError:
2304
hitbp = re.search(r'Breakpoint (\d+)', result)
2305
is_relevant = self.lang_info.is_relevant_function(frame)
2306
if hitbp or is_relevant or self.stopped():
2311
def finish(self, *args):
2312
"Implements the finish command."
2313
result = self._finish_frame()
2314
self.finish_executing(result)
2316
def step(self, stepinto, stepover_command='next'):
2318
Do a single step or step-over. Returns the result of the last gdb
2319
command that made execution stop.
2321
This implementation, for stepping, sets (conditional) breakpoints for
2322
all functions that are deemed relevant. It then does a step over until
2323
either something halts execution, or until the next line is reached.
2325
If, however, stepover_command is given, it should be a string gdb
2326
command that continues execution in some way. The idea is that the
2327
caller has set a (conditional) breakpoint or watchpoint that can work
2328
more efficiently than the step-over loop. For Python this means setting
2329
a watchpoint for f->f_lasti, which means we can then subsequently
2331
We want f->f_lasti instead of f->f_lineno, because the latter only
2332
works properly with local trace functions, see
2333
PyFrameObjectPtr.current_line_num and PyFrameObjectPtr.addr2line.
2336
breakpoint_list = list(self.install_breakpoints())
2338
beginframe = gdb.selected_frame()
2340
if self.lang_info.is_relevant_function(beginframe):
2341
# If we start in a relevant frame, initialize stuff properly. If
2342
# we don't start in a relevant frame, the loop will halt
2343
# immediately. So don't call self.lang_info.lineno() as it may
2344
# raise for irrelevant frames.
2345
beginline = self.lang_info.lineno(beginframe)
2348
depth = stackdepth(beginframe)
2350
newframe = beginframe
2353
if self.lang_info.is_relevant_function(newframe):
2354
result = gdb.execute(stepover_command, to_string=True)
2356
result = self._finish_frame()
2361
newframe = gdb.selected_frame()
2362
is_relevant_function = self.lang_info.is_relevant_function(newframe)
2364
framename = newframe.name()
2365
except RuntimeError:
2368
m = re.search(r'Breakpoint (\d+)', result)
2370
if is_relevant_function and m.group(1) in breakpoint_list:
2371
# although we hit a breakpoint, we still need to check
2372
# that the function, in case hit by a runtime breakpoint,
2373
# is in the right context
2376
if newframe != beginframe:
2380
# see if we returned to the caller
2381
newdepth = stackdepth(newframe)
2382
is_relevant_function = (newdepth < depth and
2383
is_relevant_function)
2385
if is_relevant_function:
2388
# newframe equals beginframe, check for a difference in the
2390
lineno = self.lang_info.lineno(newframe)
2391
if lineno and lineno != beginline:
2395
self.delete_breakpoints(breakpoint_list)
2397
self.finish_executing(result)
2399
def run(self, args, from_tty):
2400
self.finish_executing(gdb.execute('run ' + args, to_string=True))
2402
def cont(self, *args):
2403
self.finish_executing(gdb.execute('cont', to_string=True))
2408
This class defines the interface that ExecutionControlCommandBase needs to
2409
provide language-specific execution control.
2411
Classes that implement this interface should implement:
2414
Tells the current line number (only called for a relevant frame).
2415
If lineno is a false value it is not checked for a difference.
2417
is_relevant_function(frame)
2418
tells whether we care about frame 'frame'
2420
get_source_line(frame)
2421
get the line of source code for the current line (only called for a
2422
relevant frame). If the source code cannot be retrieved this
2423
function should return None
2425
exc_info(frame) -- optional
2426
tells whether an exception was raised, if so, it should return a
2427
string representation of the exception value, None otherwise.
2429
static_break_functions()
2430
returns an iterable of function names that are considered relevant
2431
and should halt step-into execution. This is needed to provide a
2432
performing step-into
2434
runtime_break_functions() -- optional
2435
list of functions that we should break into depending on the
2439
def exc_info(self, frame):
2440
"See this class' docstring."
2442
def runtime_break_functions(self):
2444
Implement this if the list of step-into functions depends on the
2450
class PythonInfo(LanguageInfo):
2452
def pyframe(self, frame):
2453
pyframe = Frame(frame).get_pyop()
2457
raise gdb.RuntimeError(
2458
"Unable to find the Python frame, run your code with a debug "
2459
"build (configure with --with-pydebug or compile with -g).")
2461
def lineno(self, frame):
2462
return self.pyframe(frame).current_line_num()
2464
def is_relevant_function(self, frame):
2465
return Frame(frame).is_evalframeex()
2467
def get_source_line(self, frame):
2469
pyframe = self.pyframe(frame)
2470
return '%4d %s' % (pyframe.current_line_num(),
2471
pyframe.current_line().rstrip())
2475
def exc_info(self, frame):
2477
tstate = frame.read_var('tstate').dereference()
2478
if gdb.parse_and_eval('tstate->frame == f'):
2479
# tstate local variable initialized, check for an exception
2480
if sys.version_info >= (3, 12, 0, 'alpha', 6):
2481
inf_type = inf_value = tstate['current_exception']
2483
inf_type = tstate['curexc_type']
2484
inf_value = tstate['curexc_value']
2487
return 'An exception was raised: %s' % (inf_value,)
2488
except (ValueError, RuntimeError):
2489
# Could not read the variable tstate or it's memory, it's ok
2492
def static_break_functions(self):
2493
yield 'PyEval_EvalFrameEx'
2496
class PythonStepperMixin:
2498
Make this a mixin so CyStep can also inherit from this and use a
2499
CythonCodeStepper at the same time.
2502
def python_step(self, stepinto):
2504
Set a watchpoint on the Python bytecode instruction pointer and try
2507
output = gdb.execute('watch f->f_lasti', to_string=True)
2508
watchpoint = int(re.search(r'[Ww]atchpoint (\d+):', output).group(1))
2509
self.step(stepinto=stepinto, stepover_command='finish')
2510
gdb.execute('delete %s' % watchpoint)
2513
class PyStep(ExecutionControlCommandBase, PythonStepperMixin):
2514
"Step through Python code."
2518
@dont_suppress_errors
2519
def invoke(self, args, from_tty):
2520
self.python_step(stepinto=self.stepinto)
2523
class PyNext(PyStep):
2524
"Step-over Python code."
2529
class PyFinish(ExecutionControlCommandBase):
2530
"Execute until function returns to a caller."
2532
invoke = dont_suppress_errors(ExecutionControlCommandBase.finish)
2535
class PyRun(ExecutionControlCommandBase):
2538
invoke = dont_suppress_errors(ExecutionControlCommandBase.run)
2541
class PyCont(ExecutionControlCommandBase):
2543
invoke = dont_suppress_errors(ExecutionControlCommandBase.cont)
2546
def _pointervalue(gdbval):
2548
Return the value of the pointer as a Python int.
2550
gdbval.type must be a pointer type
2552
# don't convert with int() as it will raise a RuntimeError
2553
if gdbval.address is not None:
2554
return int(gdbval.address)
2556
# the address attribute is None sometimes, in which case we can
2557
# still convert the pointer to an int
2561
def pointervalue(gdbval):
2562
pointer = _pointervalue(gdbval)
2565
raise gdb.GdbError("Negative pointer value, presumably a bug "
2566
"in gdb, aborting.")
2567
except RuntimeError:
2568
# work around yet another bug in gdb where you get random behaviour
2575
def get_inferior_unicode_postfix():
2577
gdb.parse_and_eval('PyUnicode_FromEncodedObject')
2578
except RuntimeError:
2580
gdb.parse_and_eval('PyUnicodeUCS2_FromEncodedObject')
2581
except RuntimeError:
2589
class PythonCodeExecutor:
2591
Py_single_input = 256
2595
def malloc(self, size):
2596
chunk = (gdb.parse_and_eval("(void *) malloc((size_t) %d)" % size))
2598
pointer = pointervalue(chunk)
2600
raise gdb.GdbError("No memory could be allocated in the inferior.")
2604
def alloc_string(self, string):
2605
pointer = self.malloc(len(string))
2606
get_selected_inferior().write_memory(pointer, string)
2610
def alloc_pystring(self, string):
2611
stringp = self.alloc_string(string)
2612
PyString_FromStringAndSize = 'PyString_FromStringAndSize'
2615
gdb.parse_and_eval(PyString_FromStringAndSize)
2616
except RuntimeError:
2618
PyString_FromStringAndSize = ('PyUnicode%s_FromStringAndSize' %
2619
(get_inferior_unicode_postfix(),))
2622
result = gdb.parse_and_eval(
2623
'(PyObject *) %s((char *) %d, (size_t) %d)' % (
2624
PyString_FromStringAndSize, stringp, len(string)))
2628
pointer = pointervalue(result)
2630
raise gdb.GdbError("Unable to allocate Python string in "
2635
def free(self, pointer):
2636
gdb.parse_and_eval("(void) free((void *) %d)" % pointer)
2638
def incref(self, pointer):
2639
"Increment the reference count of a Python object in the inferior."
2640
gdb.parse_and_eval('Py_IncRef((PyObject *) %d)' % pointer)
2642
def xdecref(self, pointer):
2643
"Decrement the reference count of a Python object in the inferior."
2644
# Py_DecRef is like Py_XDECREF, but a function. So we don't have
2645
# to check for NULL. This should also decref all our allocated
2647
gdb.parse_and_eval('Py_DecRef((PyObject *) %d)' % pointer)
2649
def evalcode(self, code, input_type, global_dict=None, local_dict=None):
2651
Evaluate python code `code` given as a string in the inferior and
2652
return the result as a gdb.Value. Returns a new reference in the
2655
Of course, executing any code in the inferior may be dangerous and may
2656
leave the debuggee in an unsafe state or terminate it altogether.
2659
raise gdb.GdbError("String contains NUL byte.")
2663
pointer = self.alloc_string(code)
2665
globalsp = pointervalue(global_dict)
2666
localsp = pointervalue(local_dict)
2668
if globalsp == 0 or localsp == 0:
2669
raise gdb.GdbError("Unable to obtain or create locals or globals.")
2675
(PyObject *) %(globals)s,
2676
(PyObject *) %(locals)d)
2677
""" % dict(code=pointer, start=input_type,
2678
globals=globalsp, locals=localsp)
2680
with FetchAndRestoreError():
2682
pyobject_return_value = gdb.parse_and_eval(code)
2686
return pyobject_return_value
2689
class FetchAndRestoreError(PythonCodeExecutor):
2691
Context manager that fetches the error indicator in the inferior and
2692
restores it on exit.
2696
self.sizeof_PyObjectPtr = gdb.lookup_type('PyObject').pointer().sizeof
2697
self.pointer = self.malloc(self.sizeof_PyObjectPtr * 3)
2700
value = self.pointer + self.sizeof_PyObjectPtr
2701
traceback = self.pointer + self.sizeof_PyObjectPtr * 2
2703
self.errstate = type, value, traceback
2705
def __enter__(self):
2706
gdb.parse_and_eval("PyErr_Fetch(%d, %d, %d)" % self.errstate)
2708
def __exit__(self, *args):
2709
if gdb.parse_and_eval("(int) PyErr_Occurred()"):
2710
gdb.parse_and_eval("PyErr_Print()")
2712
pyerr_restore = ("PyErr_Restore("
2715
"(PyObject *) *%d)")
2718
gdb.parse_and_eval(pyerr_restore % self.errstate)
2720
self.free(self.pointer)
2723
class FixGdbCommand(gdb.Command):
2725
def __init__(self, command, actual_command):
2726
super().__init__(command, gdb.COMMAND_DATA,
2728
self.actual_command = actual_command
2732
It seems that invoking either 'cy exec' and 'py-exec' work perfectly
2733
fine, but after this gdb's python API is entirely broken.
2734
Maybe some uncleared exception value is still set?
2735
sys.exc_clear() didn't help. A demonstration:
2737
(gdb) cy exec 'hello'
2739
(gdb) python gdb.execute('cont')
2740
RuntimeError: Cannot convert value to int.
2741
Error while executing Python code.
2742
(gdb) python gdb.execute('cont')
2745
Program exited normally.
2747
warnings.filterwarnings('ignore', r'.*', RuntimeWarning,
2748
re.escape(__name__))
2750
int(gdb.parse_and_eval("(void *) 0")) == 0
2751
except RuntimeError:
2753
# warnings.resetwarnings()
2755
@dont_suppress_errors
2756
def invoke(self, args, from_tty):
2759
gdb.execute('%s %s' % (self.actual_command, args))
2760
except RuntimeError as e:
2761
raise gdb.GdbError(str(e))
2765
def _evalcode_python(executor, code, input_type):
2767
Execute Python code in the most recent stack frame.
2769
global_dict = gdb.parse_and_eval('PyEval_GetGlobals()')
2770
local_dict = gdb.parse_and_eval('PyEval_GetLocals()')
2772
if (pointervalue(global_dict) == 0 or pointervalue(local_dict) == 0):
2773
raise gdb.GdbError("Unable to find the locals or globals of the "
2774
"most recent Python function (relative to the "
2777
return executor.evalcode(code, input_type, global_dict, local_dict)
2780
class PyExec(gdb.Command):
2782
def readcode(self, expr):
2784
return expr, PythonCodeExecutor.Py_single_input
2793
if line.rstrip() == 'end':
2798
return '\n'.join(lines), PythonCodeExecutor.Py_file_input
2800
@dont_suppress_errors
2801
def invoke(self, expr, from_tty):
2802
expr, input_type = self.readcode(expr)
2803
executor = PythonCodeExecutor()
2804
executor.xdecref(_evalcode_python(executor, input_type, global_dict, local_dict))
2807
gdb.execute('set breakpoint pending on')
2809
if hasattr(gdb, 'GdbError'):
2810
# Wrap py-step and py-next in gdb defines to make them repeatable.
2811
py_step = PyStep('-py-step', PythonInfo())
2812
py_next = PyNext('-py-next', PythonInfo())
2814
py_finish = PyFinish('py-finish', PythonInfo())
2815
py_run = PyRun('py-run', PythonInfo())
2816
py_cont = PyCont('py-cont', PythonInfo())
2818
py_exec = FixGdbCommand('py-exec', '-py-exec')
2819
_py_exec = PyExec("-py-exec", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
2821
warnings.warn("Use gdb 7.2 or higher to use the py-exec command.")