Commit e325fbee authored by Mark Florisson's avatar Mark Florisson

Detect Python exceptions

parent da24fe31
...@@ -835,7 +835,7 @@ class CyBreak(CythonCommand): ...@@ -835,7 +835,7 @@ class CyBreak(CythonCommand):
return compl return compl
class CythonInfo(CythonBase, libpython.LanguageInfo): class CythonInfo(CythonBase, libpython.PythonInfo):
""" """
Implementation of the interface dictated by libpython.LanguageInfo. Implementation of the interface dictated by libpython.LanguageInfo.
""" """
...@@ -847,8 +847,7 @@ class CythonInfo(CythonBase, libpython.LanguageInfo): ...@@ -847,8 +847,7 @@ class CythonInfo(CythonBase, libpython.LanguageInfo):
# related code. The C level should be dispatched to the 'step' command. # related code. The C level should be dispatched to the 'step' command.
if self.is_cython_function(frame): if self.is_cython_function(frame):
return self.get_cython_lineno(frame) return self.get_cython_lineno(frame)
else: return super(CythonInfo, self).lineno(frame)
return libpython.py_step.lang_info.lineno(frame)
def get_source_line(self, frame): def get_source_line(self, frame):
try: try:
...@@ -858,6 +857,10 @@ class CythonInfo(CythonBase, libpython.LanguageInfo): ...@@ -858,6 +857,10 @@ class CythonInfo(CythonBase, libpython.LanguageInfo):
else: else:
return line.strip() or None return line.strip() or None
def exc_info(self, frame):
if self.is_python_function:
return super(CythonInfo, self).exc_info(frame)
def runtime_break_functions(self): def runtime_break_functions(self):
if self.is_cython_function(): if self.is_cython_function():
return self.get_cython_function().step_into_functions return self.get_cython_function().step_into_functions
......
...@@ -369,8 +369,8 @@ class PyObjectPtr(object): ...@@ -369,8 +369,8 @@ class PyObjectPtr(object):
if tp_name in name_map: if tp_name in name_map:
return name_map[tp_name] return name_map[tp_name]
if tp_flags & Py_TPFLAGS_HEAPTYPE: if tp_flags & (Py_TPFLAGS_HEAPTYPE|Py_TPFLAGS_TYPE_SUBCLASS):
return HeapTypeObjectPtr return PyTypeObjectPtr
if tp_flags & Py_TPFLAGS_INT_SUBCLASS: if tp_flags & Py_TPFLAGS_INT_SUBCLASS:
return PyIntObjectPtr return PyIntObjectPtr
...@@ -392,8 +392,6 @@ class PyObjectPtr(object): ...@@ -392,8 +392,6 @@ class PyObjectPtr(object):
return PyDictObjectPtr return PyDictObjectPtr
if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS: if tp_flags & Py_TPFLAGS_BASE_EXC_SUBCLASS:
return PyBaseExceptionObjectPtr return PyBaseExceptionObjectPtr
#if tp_flags & Py_TPFLAGS_TYPE_SUBCLASS:
# return PyTypeObjectPtr
# Use the base class: # Use the base class:
return cls return cls
...@@ -484,8 +482,8 @@ def _PyObject_VAR_SIZE(typeobj, nitems): ...@@ -484,8 +482,8 @@ def _PyObject_VAR_SIZE(typeobj, nitems):
) & ~(SIZEOF_VOID_P - 1) ) & ~(SIZEOF_VOID_P - 1)
).cast(gdb.lookup_type('size_t')) ).cast(gdb.lookup_type('size_t'))
class HeapTypeObjectPtr(PyObjectPtr): class PyTypeObjectPtr(PyObjectPtr):
_typename = 'PyObject' _typename = 'PyTypeObject'
def get_attr_dict(self): def get_attr_dict(self):
''' '''
...@@ -546,9 +544,16 @@ class HeapTypeObjectPtr(PyObjectPtr): ...@@ -546,9 +544,16 @@ class HeapTypeObjectPtr(PyObjectPtr):
return return
visited.add(self.as_address()) visited.add(self.as_address())
pyop_attrdict = self.get_attr_dict() try:
_write_instance_repr(out, visited, tp_name = self.field('tp_name').string()
self.safe_tp_name(), pyop_attrdict, self.as_address()) except RuntimeError:
tp_name = 'unknown'
out.write('<type %s at remote 0x%x>' % (tp_name,
self.as_address()))
# pyop_attrdict = self.get_attr_dict()
# _write_instance_repr(out, visited,
# self.safe_tp_name(), pyop_attrdict, self.as_address())
class ProxyException(Exception): class ProxyException(Exception):
def __init__(self, tp_name, args): def __init__(self, tp_name, args):
...@@ -1136,9 +1141,6 @@ class PyTupleObjectPtr(PyObjectPtr): ...@@ -1136,9 +1141,6 @@ class PyTupleObjectPtr(PyObjectPtr):
else: else:
out.write(')') out.write(')')
class PyTypeObjectPtr(PyObjectPtr):
_typename = 'PyTypeObject'
def _unichr_is_printable(char): def _unichr_is_printable(char):
# Logic adapted from Python 3's Tools/unicode/makeunicodedata.py # Logic adapted from Python 3's Tools/unicode/makeunicodedata.py
...@@ -2171,6 +2173,20 @@ class PythonInfo(LanguageInfo): ...@@ -2171,6 +2173,20 @@ class PythonInfo(LanguageInfo):
except IOError, e: except IOError, e:
return None return None
def exc_info(self, frame):
try:
tstate = frame.read_var('tstate').dereference()
if gdb.parse_and_eval('tstate->frame == f'):
# tstate local variable initialized
inf_type = tstate['curexc_type']
inf_value = tstate['curexc_value']
if inf_type:
return 'An exception was raised: %s(%s)' % (inf_type,
inf_value)
except (ValueError, RuntimeError), e:
# Could not read the variable tstate or it's memory, it's ok
pass
def static_break_functions(self): def static_break_functions(self):
yield 'PyEval_EvalFrameEx' yield 'PyEval_EvalFrameEx'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment