xref: /llvm-project/lldb/test/API/macosx/ignore_exceptions/TestIgnoredExceptions.py (revision 620dc1224ff9e4cb86e6e4d8e7c3941fc921887d)
1"""
2Test that by turning off EXC_BAD_ACCESS catching, we can
3debug into and out of a signal handler.
4"""
5
6import lldb
7from lldbsuite.test.decorators import *
8import lldbsuite.test.lldbutil as lldbutil
9from lldbsuite.test.lldbtest import *
10
11
12class TestDarwinSignalHandlers(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    @skipIfOutOfTreeDebugserver
16    @skipUnlessDarwin
17    def test_ignored_thread(self):
18        """It isn't possible to convert an EXC_BAD_ACCESS to a signal when
19        running under the debugger, which makes debugging SIGBUS handlers
20        and so forth difficult.  This test sends QIgnoreExceptions and that
21        should get us into the signal handler and out again."""
22        self.build()
23        self.main_source_file = lldb.SBFileSpec("main.c")
24        self.suspended_thread_test()
25
26    def suspended_thread_test(self):
27        # Make sure that we don't accept bad values:
28        self.match(
29            "settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_AXESS",
30            "EXC_BAD_AXESS",
31            error=True,
32        )
33        # Make sure that we don't accept exceptions that lldb/debugserver need:
34        self.match(
35            "settings set platform.plugin.darwin.ignored-exceptions EXC_BREAKPOINT",
36            "EXC_BREAKPOINT",
37            error=True,
38        )
39        # Make sure that we don't accept exceptions that lldb/debugserver need:
40        self.match(
41            "settings set platform.plugin.darwin.ignored-exceptions EXC_SOFT_SIGNAL",
42            "EXC_SOFT_SIGNAL",
43            error=True,
44        )
45        # Now set ourselves to ignore some exceptions.  The test depends on ignoring EXC_BAD_ACCESS, but I passed all the
46        # ones we currently accept to make sure they parse:
47        self.runCmd(
48            "settings set platform.plugin.darwin.ignored-exceptions EXC_BAD_ACCESS|EXC_BAD_INSTRUCTION|EXC_ARITHMETIC|EXC_RESOURCE|EXC_GUARD|EXC_SYSCALL"
49        )
50        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
51            self, "Stop here to get things going", self.main_source_file
52        )
53
54        sig_bkpt = target.BreakpointCreateBySourceRegex(
55            "stop here in the signal handler", self.main_source_file
56        )
57        self.assertEqual(sig_bkpt.GetNumLocations(), 1, "Found sig handler breakpoint")
58        return_bkpt = target.BreakpointCreateBySourceRegex(
59            "Break here to make sure we got past the signal handler",
60            self.main_source_file,
61        )
62        self.assertEqual(return_bkpt.GetNumLocations(), 1, "Found return breakpoint")
63        # Now continue, and we should stop with a stop reason of SIGBUS:
64        process.Continue()
65        self.assertState(
66            process.state, lldb.eStateStopped, "Stopped after continue to SIGBUS"
67        )
68        if thread.stop_reason == lldb.eStopReasonBreakpoint:
69            id = thread.GetStopReasonDataAtIndex(0)
70            name = thread.frame[0].name
71            self.fail(
72                "Hit breakpoint {0} in '{1}' rather than getting a SIGBUS".format(
73                    id, name
74                )
75            )
76
77        self.assertStopReason(thread.stop_reason, lldb.eStopReasonSignal)
78        self.assertEqual(thread.GetStopReasonDataAtIndex(0), 10, "Got a SIGBUS")
79
80        # Now when we continue, we'll find our way into the signal handler:
81        threads = lldbutil.continue_to_breakpoint(process, sig_bkpt)
82        self.assertEqual(len(threads), 1, "Stopped at sig breakpoint")
83
84        threads = lldbutil.continue_to_breakpoint(process, return_bkpt)
85        self.assertEqual(len(threads), 1, "Stopped at return breakpoint")
86
87        # Make sure we really changed the value:
88
89        process.Continue()
90        self.assertState(process.state, lldb.eStateExited, "Process exited")
91        self.assertEqual(process.exit_state, 20, "Got the right exit status")
92