diff options
author | Victor Stinner <victor.stinner@haypocalc.com> | 2011-12-19 12:59:58 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@haypocalc.com> | 2011-12-19 12:59:58 (GMT) |
commit | 99cff3f1825e70027b2fa170fdc4723c57723b5d (patch) | |
tree | bc560b22004341028bd0bbe054f3c5ea20488c89 /Tools | |
parent | 52aa260387e2de3ddf96cc0006867241cd3d3667 (diff) | |
download | cpython-99cff3f1825e70027b2fa170fdc4723c57723b5d.zip cpython-99cff3f1825e70027b2fa170fdc4723c57723b5d.tar.gz cpython-99cff3f1825e70027b2fa170fdc4723c57723b5d.tar.bz2 |
Issue #13628: python-gdb.py is now able to retrieve more frames in the Python
traceback if Python is optimized.
* delay the lookup of the size_t type, it is not available at startup
* The second argument of the PyFrameObjectPtr constructor is optional, as
done in other constructors
* iter_builtins() and iter_globals() methods of PyFrameObjectPtr returns
an empty tuple instead of None if Python is optimized
* Fix py-bt to handle correctly "optimized" frames
* Frame.get_pyop() tries to get the frame pointer from PyEval_EvalCodeEx()
if the pointer is optimized out in PyEval_EvalFrameEx()
Diffstat (limited to 'Tools')
-rw-r--r-- | Tools/gdb/libpython.py | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 21e74d8..e12769d 100644 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -47,7 +47,6 @@ import sys _type_char_ptr = gdb.lookup_type('char').pointer() # char* _type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char* _type_void_ptr = gdb.lookup_type('void').pointer() # void* -_type_size_t = gdb.lookup_type('size_t') SIZEOF_VOID_P = _type_void_ptr.sizeof @@ -410,11 +409,15 @@ class InstanceProxy(object): self.address) def _PyObject_VAR_SIZE(typeobj, nitems): + if _PyObject_VAR_SIZE._type_size_t is None: + _PyObject_VAR_SIZE._type_size_t = gdb.lookup_type('size_t') + return ( ( typeobj.field('tp_basicsize') + nitems * typeobj.field('tp_itemsize') + (SIZEOF_VOID_P - 1) ) & ~(SIZEOF_VOID_P - 1) - ).cast(_type_size_t) + ).cast(_PyObject_VAR_SIZE._type_size_t) +_PyObject_VAR_SIZE._type_size_t = None class HeapTypeObjectPtr(PyObjectPtr): _typename = 'PyObject' @@ -786,7 +789,7 @@ class PyNoneStructPtr(PyObjectPtr): class PyFrameObjectPtr(PyObjectPtr): _typename = 'PyFrameObject' - def __init__(self, gdbval, cast_to): + def __init__(self, gdbval, cast_to=None): PyObjectPtr.__init__(self, gdbval, cast_to) if not self.is_optimized_out(): @@ -820,7 +823,7 @@ class PyFrameObjectPtr(PyObjectPtr): the global variables of this frame ''' if self.is_optimized_out(): - return + return () pyop_globals = self.pyop_field('f_globals') return pyop_globals.iteritems() @@ -831,7 +834,7 @@ class PyFrameObjectPtr(PyObjectPtr): the builtin variables ''' if self.is_optimized_out(): - return + return () pyop_builtins = self.pyop_field('f_builtins') return pyop_builtins.iteritems() @@ -1205,7 +1208,20 @@ class Frame(object): def get_pyop(self): try: f = self._gdbframe.read_var('f') - return PyFrameObjectPtr.from_pyobject_ptr(f) + frame = PyFrameObjectPtr.from_pyobject_ptr(f) + if not frame.is_optimized_out(): + return frame + # gdb is unable to get the "f" argument of PyEval_EvalFrameEx() + # because it was "optimized out". Try to get "f" from the frame + # of the caller, PyEval_EvalCodeEx(). + orig_frame = frame + caller = self._gdbframe.older() + if caller: + f = caller.read_var('f') + frame = PyFrameObjectPtr.from_pyobject_ptr(f) + if not frame.is_optimized_out(): + return frame + return orig_frame except ValueError: return None @@ -1235,7 +1251,9 @@ class Frame(object): pyop = self.get_pyop() if pyop: sys.stdout.write('#%i %s\n' % (self.get_index(), pyop.get_truncated_repr(MAX_OUTPUT_LEN))) - sys.stdout.write(pyop.current_line()) + if not pyop.is_optimized_out(): + line = pyop.current_line() + sys.stdout.write(' %s\n' % line.strip()) else: sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index()) else: @@ -1281,7 +1299,7 @@ class PyList(gdb.Command): return pyop = frame.get_pyop() - if not pyop: + if not pyop or pyop.is_optimized_out(): print 'Unable to read information on python frame' return |