Commit 476af996 authored by mark's avatar mark

Choose PyString/PyBytesObjectPtr according to python version + support signals...

Choose PyString/PyBytesObjectPtr according to python version + support signals terminating the inferior.
parent 7c6598c1
...@@ -70,6 +70,8 @@ class DebugTestCase(unittest.TestCase): ...@@ -70,6 +70,8 @@ class DebugTestCase(unittest.TestCase):
except RuntimeError: except RuntimeError:
pass pass
gdb.execute('set args -c "import codefile"')
libcython.cy.step.static_breakpoints.clear() libcython.cy.step.static_breakpoints.clear()
libcython.cy.step.runtime_breakpoints.clear() libcython.cy.step.runtime_breakpoints.clear()
libcython.cy.step.init_breakpoints() libcython.cy.step.init_breakpoints()
...@@ -140,6 +142,13 @@ class TestBreak(DebugTestCase): ...@@ -140,6 +142,13 @@ class TestBreak(DebugTestCase):
assert 'def join(' in gdb.execute('cy run', to_string=True) assert 'def join(' in gdb.execute('cy run', to_string=True)
class TestKilled(DebugTestCase):
def test_abort(self):
gdb.execute("set args -c 'import os; os.abort()'")
output = gdb.execute('cy run', to_string=True)
assert 'abort' in output.lower()
class DebugStepperTestCase(DebugTestCase): class DebugStepperTestCase(DebugTestCase):
def step(self, varnames_and_values, source_line=None, lineno=None): def step(self, varnames_and_values, source_line=None, lineno=None):
...@@ -291,6 +300,7 @@ def _main(): ...@@ -291,6 +300,7 @@ def _main():
"debugging information. Either compile python with " "debugging information. Either compile python with "
"-g or get a debug build (configure with --with-pydebug).") "-g or get a debug build (configure with --with-pydebug).")
warnings.warn(msg) warnings.warn(msg)
os._exit(1)
else: else:
m = __import__(__name__, fromlist=['']) m = __import__(__name__, fromlist=[''])
tests = inspect.getmembers(m, inspect.isclass) tests = inspect.getmembers(m, inspect.isclass)
...@@ -311,4 +321,6 @@ def main(trace_code=False): ...@@ -311,4 +321,6 @@ def main(trace_code=False):
ignoredirs=[sys.prefix, sys.exec_prefix]) ignoredirs=[sys.prefix, sys.exec_prefix])
tracer.runfunc(_main) tracer.runfunc(_main)
else: else:
_main() _main()
\ No newline at end of file
main()
\ No newline at end of file
...@@ -390,8 +390,9 @@ class CythonBase(object): ...@@ -390,8 +390,9 @@ class CythonBase(object):
def is_initialized(self, cython_func, local_name): def is_initialized(self, cython_func, local_name):
cur_lineno = self.get_cython_lineno() cur_lineno = self.get_cython_lineno()
return (local_name in cython_func.arguments or return (local_name in cython_func.arguments or
cur_lineno > cython_func.locals[local_name].lineno) (local_name in cython_func.locals and
cur_lineno > cython_func.locals[local_name].lineno))
class SourceFileDescriptor(object): class SourceFileDescriptor(object):
def __init__(self, filename, lexer, formatter=None): def __init__(self, filename, lexer, formatter=None):
...@@ -1077,18 +1078,16 @@ class CyLocals(CythonCommand): ...@@ -1077,18 +1078,16 @@ class CyLocals(CythonCommand):
command_class = gdb.COMMAND_STACK command_class = gdb.COMMAND_STACK
completer_class = gdb.COMPLETE_NONE completer_class = gdb.COMPLETE_NONE
def _print_if_initialized(self, cyvar, max_name_length, prefix=''):
if self.is_initialized(self.get_cython_function(), cyvar.name):
value = gdb.parse_and_eval(cyvar.cname)
if not value.is_optimized_out:
self.print_gdb_value(cyvar.name, value, max_name_length, prefix)
@dispatch_on_frame(c_command='info locals', python_command='py-locals') @dispatch_on_frame(c_command='info locals', python_command='py-locals')
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
local_cython_vars = self.get_cython_function().locals local_cython_vars = self.get_cython_function().locals
max_name_length = len(max(local_cython_vars, key=len)) max_name_length = len(max(local_cython_vars, key=len))
for name, cyvar in sorted(local_cython_vars.iteritems(), key=sortkey): for name, cyvar in sorted(local_cython_vars.iteritems(), key=sortkey):
self._print_if_initialized(cyvar, max_name_length) if self.is_initialized(self.get_cython_function(), cyvar.name):
value = gdb.parse_and_eval(cyvar.cname)
if not value.is_optimized_out:
self.print_gdb_value(cyvar.name, value,
max_name_length, '')
class CyGlobals(CyLocals): class CyGlobals(CyLocals):
...@@ -1124,8 +1123,14 @@ class CyGlobals(CyLocals): ...@@ -1124,8 +1123,14 @@ class CyGlobals(CyLocals):
print 'C globals:' print 'C globals:'
for name, cyvar in sorted(module_globals.iteritems(), key=sortkey): for name, cyvar in sorted(module_globals.iteritems(), key=sortkey):
if name not in seen: if name not in seen:
self._print_if_initialized(cyvar, max_name_length, try:
prefix=' ') value = gdb.parse_and_eval(cyvar.cname)
except RuntimeError:
pass
else:
if not value.is_optimized_out:
self.print_gdb_value(cyvar.name, value,
max_name_length, ' ')
class CyExec(CythonCommand, libpython.PyExec): class CyExec(CythonCommand, libpython.PyExec):
...@@ -1284,14 +1289,14 @@ class CyCValue(CyCName): ...@@ -1284,14 +1289,14 @@ class CyCValue(CyCName):
try: try:
cname = super(CyCValue, self).invoke(cyname, frame=frame) cname = super(CyCValue, self).invoke(cyname, frame=frame)
return gdb.parse_and_eval(cname) return gdb.parse_and_eval(cname)
except (gdb.GdbError, RuntimeError): except (gdb.GdbError, RuntimeError), e:
# variable exists but may not have been initialized yet, or may be # variable exists but may not have been initialized yet, or may be
# in the globals dict of the Cython module # in the globals dict of the Cython module
d = self.get_cython_globals_dict() d = self.get_cython_globals_dict()
if cyname in d: if cyname in d:
return d[cyname]._gdbval return d[cyname]._gdbval
raise gdb.GdbError("Variable %s not initialized yet." % cyname) raise gdb.GdbError(str(e))
class CyLine(gdb.Function, CythonBase): class CyLine(gdb.Function, CythonBase):
......
...@@ -332,7 +332,7 @@ class PyObjectPtr(object): ...@@ -332,7 +332,7 @@ class PyObjectPtr(object):
#print 'tp_flags = 0x%08x' % tp_flags #print 'tp_flags = 0x%08x' % tp_flags
#print 'tp_name = %r' % tp_name #print 'tp_name = %r' % tp_name
name_map = {'bool': PyBoolObjectPtr, name_map = {'bool': PyBoolObjectPtr,
'classobj': PyClassObjectPtr, 'classobj': PyClassObjectPtr,
'instance': PyInstanceObjectPtr, 'instance': PyInstanceObjectPtr,
...@@ -357,7 +357,11 @@ class PyObjectPtr(object): ...@@ -357,7 +357,11 @@ class PyObjectPtr(object):
if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS: if tp_flags & Py_TPFLAGS_TUPLE_SUBCLASS:
return PyTupleObjectPtr return PyTupleObjectPtr
if tp_flags & Py_TPFLAGS_STRING_SUBCLASS: if tp_flags & Py_TPFLAGS_STRING_SUBCLASS:
return PyStringObjectPtr try:
gdb.lookup_type('PyBytesObject')
return PyBytesObject
except RuntimeError:
return PyStringObjectPtr
if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS: if tp_flags & Py_TPFLAGS_UNICODE_SUBCLASS:
return PyUnicodeObjectPtr return PyUnicodeObjectPtr
if tp_flags & Py_TPFLAGS_DICT_SUBCLASS: if tp_flags & Py_TPFLAGS_DICT_SUBCLASS:
...@@ -380,7 +384,7 @@ class PyObjectPtr(object): ...@@ -380,7 +384,7 @@ class PyObjectPtr(object):
p = PyObjectPtr(gdbval) p = PyObjectPtr(gdbval)
cls = cls.subclass_from_type(p.type()) cls = cls.subclass_from_type(p.type())
return cls(gdbval, cast_to=cls.get_gdb_type()) return cls(gdbval, cast_to=cls.get_gdb_type())
except RuntimeError: except RuntimeError, exc:
# Handle any kind of error e.g. NULL ptrs by simply using the base # Handle any kind of error e.g. NULL ptrs by simply using the base
# class # class
pass pass
...@@ -555,19 +559,6 @@ class PyBaseExceptionObjectPtr(PyObjectPtr): ...@@ -555,19 +559,6 @@ class PyBaseExceptionObjectPtr(PyObjectPtr):
out.write(self.safe_tp_name()) out.write(self.safe_tp_name())
self.write_field_repr('args', out, visited) self.write_field_repr('args', out, visited)
class PyBoolObjectPtr(PyObjectPtr):
"""
Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
<bool> instances (Py_True/Py_False) within the process being debugged.
"""
_typename = 'PyBoolObject'
def proxyval(self, visited):
if int_from_int(self.field('ob_ival')):
return True
else:
return False
class PyClassObjectPtr(PyObjectPtr): class PyClassObjectPtr(PyObjectPtr):
""" """
...@@ -821,11 +812,10 @@ class PyBoolObjectPtr(PyLongObjectPtr): ...@@ -821,11 +812,10 @@ class PyBoolObjectPtr(PyLongObjectPtr):
Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two Class wrapping a gdb.Value that's a PyBoolObject* i.e. one of the two
<bool> instances (Py_True/Py_False) within the process being debugged. <bool> instances (Py_True/Py_False) within the process being debugged.
""" """
def proxyval(self, visited): def proxyval(self, visited):
if PyLongObjectPtr.proxyval(self, visited): return bool(PyLongObjectPtr.proxyval(self, visited))
return True
else:
return False
class PyNoneStructPtr(PyObjectPtr): class PyNoneStructPtr(PyObjectPtr):
""" """
...@@ -1073,6 +1063,10 @@ class PyBytesObjectPtr(PyObjectPtr): ...@@ -1073,6 +1063,10 @@ class PyBytesObjectPtr(PyObjectPtr):
out.write(byte) out.write(byte)
out.write(quote) out.write(quote)
class PyStringObjectPtr(PyBytesObjectPtr):
_typename = 'PyStringObject'
class PyTupleObjectPtr(PyObjectPtr): class PyTupleObjectPtr(PyObjectPtr):
_typename = 'PyTupleObject' _typename = 'PyTupleObject'
...@@ -1691,7 +1685,8 @@ class PyNameEquals(gdb.Function): ...@@ -1691,7 +1685,8 @@ class PyNameEquals(gdb.Function):
pyframe = frame.get_pyop() pyframe = frame.get_pyop()
if pyframe is None: if pyframe is None:
return None return None
val = str(getattr(pyframe, attr)); print val, val.proxyval(set()); return val
return str(getattr(pyframe, attr))
return None return None
...@@ -1924,8 +1919,14 @@ class GenericCodeStepper(gdb.Command): ...@@ -1924,8 +1919,14 @@ class GenericCodeStepper(gdb.Command):
context. context.
""" """
def stopped(self): def stopped(self, result):
return get_selected_inferior().pid == 0 match = re.search('^Program received signal .*', result, re.MULTILINE)
if match:
return match.group(0)
elif get_selected_inferior().pid == 0:
return result
else:
return None
def _stackdepth(self, frame): def _stackdepth(self, frame):
depth = 0 depth = 0
...@@ -1941,8 +1942,17 @@ class GenericCodeStepper(gdb.Command): ...@@ -1941,8 +1942,17 @@ class GenericCodeStepper(gdb.Command):
of source code or the result of the last executed gdb command (passed of source code or the result of the last executed gdb command (passed
in as the `result` argument). in as the `result` argument).
""" """
if self.stopped(): result = self.stopped(result)
if result:
print result.strip() print result.strip()
# check whether the program was killed by a signal, it should still
# have a stack.
try:
frame = gdb.selected_frame()
except RuntimeError:
pass
else:
print self.get_source_line(frame)
else: else:
frame = gdb.selected_frame() frame = gdb.selected_frame()
output = None output = None
...@@ -1985,7 +1995,7 @@ class GenericCodeStepper(gdb.Command): ...@@ -1985,7 +1995,7 @@ class GenericCodeStepper(gdb.Command):
hitbp = re.search(r'Breakpoint (\d+)', result) hitbp = re.search(r'Breakpoint (\d+)', result)
is_relavant = self.is_relevant_function(frame) is_relavant = self.is_relevant_function(frame)
if hitbp or is_relavant or self.stopped(): if hitbp or is_relavant or self.stopped(result):
break break
self.finish_executing(result) self.finish_executing(result)
...@@ -2012,7 +2022,7 @@ class GenericCodeStepper(gdb.Command): ...@@ -2012,7 +2022,7 @@ class GenericCodeStepper(gdb.Command):
else: else:
result = self._finish() result = self._finish()
if self.stopped(): if self.stopped(result):
break break
newframe = gdb.selected_frame() newframe = gdb.selected_frame()
......
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