Add some more tests of what exceptions we accept and don't accept. Differential Revision: https://reviews.llvm.org/D151843
92 lines
3.8 KiB
Python
92 lines
3.8 KiB
Python
"""
|
|
Test that by turning off EXC_BAD_ACCESS catching, we can
|
|
debug into and out of a signal handler.
|
|
"""
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
import lldbsuite.test.lldbutil as lldbutil
|
|
from lldbsuite.test.lldbtest import *
|
|
|
|
|
|
class TestDarwinSignalHandlers(TestBase):
|
|
NO_DEBUG_INFO_TESTCASE = True
|
|
|
|
@skipIfOutOfTreeDebugserver
|
|
@skipUnlessDarwin
|
|
def test_ignored_thread(self):
|
|
"""It isn't possible to convert an EXC_BAD_ACCESS to a signal when
|
|
running under the debugger, which makes debugging SIGBUS handlers
|
|
and so forth difficult. This test sends QIgnoreExceptions and that
|
|
should get us into the signal handler and out again."""
|
|
self.build()
|
|
self.main_source_file = lldb.SBFileSpec("main.c")
|
|
self.suspended_thread_test()
|
|
|
|
def suspended_thread_test(self):
|
|
# Make sure that we don't accept bad values:
|
|
self.match(
|
|
"settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_AXESS",
|
|
"EXC_BAD_AXESS",
|
|
error=True,
|
|
)
|
|
# Make sure that we don't accept exceptions that lldb/debugserver need:
|
|
self.match(
|
|
"settings set platform.plugin.darwin.ignored-exceptions EXC_BREAKPOINT",
|
|
"EXC_BREAKPOINT",
|
|
error=True,
|
|
)
|
|
# Make sure that we don't accept exceptions that lldb/debugserver need:
|
|
self.match(
|
|
"settings set platform.plugin.darwin.ignored-exceptions EXC_SOFT_SIGNAL",
|
|
"EXC_SOFT_SIGNAL",
|
|
error=True,
|
|
)
|
|
# Now set ourselves to ignore some exceptions. The test depends on ignoring EXC_BAD_ACCESS, but I passed all the
|
|
# ones we currently accept to make sure they parse:
|
|
self.runCmd(
|
|
"settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_ACCESS|EXC_BAD_INSTRUCTION|EXC_ARITHMETIC|EXC_RESOURCE|EXC_GUARD|EXC_SYSCALL"
|
|
)
|
|
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
|
self, "Stop here to get things going", self.main_source_file
|
|
)
|
|
|
|
sig_bkpt = target.BreakpointCreateBySourceRegex(
|
|
"stop here in the signal handler", self.main_source_file
|
|
)
|
|
self.assertEqual(sig_bkpt.GetNumLocations(), 1, "Found sig handler breakpoint")
|
|
return_bkpt = target.BreakpointCreateBySourceRegex(
|
|
"Break here to make sure we got past the signal handler",
|
|
self.main_source_file,
|
|
)
|
|
self.assertEqual(return_bkpt.GetNumLocations(), 1, "Found return breakpoint")
|
|
# Now continue, and we should stop with a stop reason of SIGBUS:
|
|
process.Continue()
|
|
self.assertState(
|
|
process.state, lldb.eStateStopped, "Stopped after continue to SIGBUS"
|
|
)
|
|
if thread.stop_reason == lldb.eStopReasonBreakpoint:
|
|
id = thread.GetStopReasonDataAtIndex(0)
|
|
name = thread.frame[0].name
|
|
self.fail(
|
|
"Hit breakpoint {0} in '{1}' rather than getting a SIGBUS".format(
|
|
id, name
|
|
)
|
|
)
|
|
|
|
self.assertStopReason(thread.stop_reason, lldb.eStopReasonSignal)
|
|
self.assertEqual(thread.GetStopReasonDataAtIndex(0), 10, "Got a SIGBUS")
|
|
|
|
# Now when we continue, we'll find our way into the signal handler:
|
|
threads = lldbutil.continue_to_breakpoint(process, sig_bkpt)
|
|
self.assertEqual(len(threads), 1, "Stopped at sig breakpoint")
|
|
|
|
threads = lldbutil.continue_to_breakpoint(process, return_bkpt)
|
|
self.assertEqual(len(threads), 1, "Stopped at return breakpoint")
|
|
|
|
# Make sure we really changed the value:
|
|
|
|
process.Continue()
|
|
self.assertState(process.state, lldb.eStateExited, "Process exited")
|
|
self.assertEqual(process.exit_state, 20, "Got the right exit status")
|