xref: /llvm-project/lldb/test/API/lang/objc/exceptions/TestObjCExceptions.py (revision 28fb39f16af1003e53008b75c11127b3288742f8)
199451b44SJordan Rupprecht# encoding: utf-8
299451b44SJordan Rupprecht"""
399451b44SJordan RupprechtTest lldb Obj-C exception support.
499451b44SJordan Rupprecht"""
599451b44SJordan Rupprecht
699451b44SJordan Rupprecht
799451b44SJordan Rupprechtimport lldb
899451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
999451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
1099451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprecht
1399451b44SJordan Rupprechtclass ObjCExceptionsTestCase(TestBase):
14*2238dcc3SJonas Devlieghere    @skipIf(compiler="clang", compiler_version=["<", "13.0"])
1599451b44SJordan Rupprecht    def test_objc_exceptions_at_throw(self):
1699451b44SJordan Rupprecht        self.build()
1799451b44SJordan Rupprecht
1899451b44SJordan Rupprecht        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
1999451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
2099451b44SJordan Rupprecht
2199451b44SJordan Rupprecht        launch_info = lldb.SBLaunchInfo(["a.out", "0"])
22254e0abfSJonas Devlieghere        launch_info.SetLaunchFlags(lldb.eLaunchFlagInheritTCCFromParent)
23*2238dcc3SJonas Devlieghere        lldbutil.run_to_name_breakpoint(
24*2238dcc3SJonas Devlieghere            self, "objc_exception_throw", launch_info=launch_info
25*2238dcc3SJonas Devlieghere        )
2699451b44SJordan Rupprecht
27*2238dcc3SJonas Devlieghere        self.expect(
28*2238dcc3SJonas Devlieghere            "thread list",
29*2238dcc3SJonas Devlieghere            substrs=["stopped", "stop reason = hit Objective-C exception"],
30*2238dcc3SJonas Devlieghere        )
3199451b44SJordan Rupprecht
32*2238dcc3SJonas Devlieghere        self.expect(
33*2238dcc3SJonas Devlieghere            "thread exception",
34*2238dcc3SJonas Devlieghere            substrs=[
35*2238dcc3SJonas Devlieghere                "(NSException *) exception = ",
3699451b44SJordan Rupprecht                '"SomeReason"',
37*2238dcc3SJonas Devlieghere            ],
38*2238dcc3SJonas Devlieghere        )
3999451b44SJordan Rupprecht
4099451b44SJordan Rupprecht        target = self.dbg.GetSelectedTarget()
4199451b44SJordan Rupprecht        thread = target.GetProcess().GetSelectedThread()
4299451b44SJordan Rupprecht        frame = thread.GetSelectedFrame()
4399451b44SJordan Rupprecht
4499451b44SJordan Rupprecht        opts = lldb.SBVariablesOptions()
4599451b44SJordan Rupprecht        opts.SetIncludeRecognizedArguments(True)
4699451b44SJordan Rupprecht        variables = frame.GetVariables(opts)
4799451b44SJordan Rupprecht
4899451b44SJordan Rupprecht        self.assertEqual(variables.GetSize(), 1)
4999451b44SJordan Rupprecht        self.assertEqual(variables.GetValueAtIndex(0).name, "exception")
50*2238dcc3SJonas Devlieghere        self.assertEqual(
51*2238dcc3SJonas Devlieghere            variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument
52*2238dcc3SJonas Devlieghere        )
5399451b44SJordan Rupprecht
54*2238dcc3SJonas Devlieghere        lldbutil.run_to_source_breakpoint(
55*2238dcc3SJonas Devlieghere            self,
56*2238dcc3SJonas Devlieghere            "// Set break point at this line.",
57*2238dcc3SJonas Devlieghere            lldb.SBFileSpec("main.mm"),
58*2238dcc3SJonas Devlieghere            launch_info=launch_info,
59*2238dcc3SJonas Devlieghere        )
6099451b44SJordan Rupprecht
61*2238dcc3SJonas Devlieghere        self.expect(
62*2238dcc3SJonas Devlieghere            "thread list",
63*2238dcc3SJonas Devlieghere            STOPPED_DUE_TO_BREAKPOINT,
64*2238dcc3SJonas Devlieghere            substrs=["stopped", "stop reason = breakpoint"],
65*2238dcc3SJonas Devlieghere        )
6699451b44SJordan Rupprecht
6799451b44SJordan Rupprecht        target = self.dbg.GetSelectedTarget()
6899451b44SJordan Rupprecht        thread = target.GetProcess().GetSelectedThread()
6999451b44SJordan Rupprecht        frame = thread.GetSelectedFrame()
7099451b44SJordan Rupprecht
7199451b44SJordan Rupprecht        # No exception being currently thrown/caught at this point
7299451b44SJordan Rupprecht        self.assertFalse(thread.GetCurrentException().IsValid())
7399451b44SJordan Rupprecht        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())
7499451b44SJordan Rupprecht
7599451b44SJordan Rupprecht        self.expect(
76*2238dcc3SJonas Devlieghere            "frame variable e1", substrs=["(NSException *) e1 = ", '"SomeReason"']
77*2238dcc3SJonas Devlieghere        )
7899451b44SJordan Rupprecht
7999451b44SJordan Rupprecht        self.expect(
80*2238dcc3SJonas Devlieghere            "frame variable *e1",
8199451b44SJordan Rupprecht            substrs=[
82*2238dcc3SJonas Devlieghere                "(NSException) *e1 = ",
83*2238dcc3SJonas Devlieghere                "name = ",
84*2238dcc3SJonas Devlieghere                '"ExceptionName"',
85*2238dcc3SJonas Devlieghere                "reason = ",
86*2238dcc3SJonas Devlieghere                '"SomeReason"',
87*2238dcc3SJonas Devlieghere                "userInfo = ",
88*2238dcc3SJonas Devlieghere                "1 key/value pair",
89*2238dcc3SJonas Devlieghere                "reserved = ",
90*2238dcc3SJonas Devlieghere            ],
91*2238dcc3SJonas Devlieghere        )
9299451b44SJordan Rupprecht
9399451b44SJordan Rupprecht        e1 = frame.FindVariable("e1")
9499451b44SJordan Rupprecht        self.assertTrue(e1)
9599451b44SJordan Rupprecht        self.assertEqual(e1.type.name, "NSException *")
9699451b44SJordan Rupprecht        self.assertEqual(e1.GetSummary(), '"SomeReason"')
9799451b44SJordan Rupprecht        self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName")
9899451b44SJordan Rupprecht        self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason")
9999451b44SJordan Rupprecht        userInfo = e1.GetChildMemberWithName("userInfo").dynamic
10099451b44SJordan Rupprecht        self.assertEqual(userInfo.summary, "1 key/value pair")
101*2238dcc3SJonas Devlieghere        self.assertEqual(
102*2238dcc3SJonas Devlieghere            userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key"
103*2238dcc3SJonas Devlieghere        )
104*2238dcc3SJonas Devlieghere        self.assertEqual(
105*2238dcc3SJonas Devlieghere            userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value"
106*2238dcc3SJonas Devlieghere        )
10799451b44SJordan Rupprecht
10899451b44SJordan Rupprecht        self.expect(
109*2238dcc3SJonas Devlieghere            "frame variable e2", substrs=["(NSException *) e2 = ", '"SomeReason"']
110*2238dcc3SJonas Devlieghere        )
11199451b44SJordan Rupprecht
11299451b44SJordan Rupprecht        self.expect(
113*2238dcc3SJonas Devlieghere            "frame variable *e2",
11499451b44SJordan Rupprecht            substrs=[
115*2238dcc3SJonas Devlieghere                "(NSException) *e2 = ",
116*2238dcc3SJonas Devlieghere                "name = ",
117*2238dcc3SJonas Devlieghere                '"ThrownException"',
118*2238dcc3SJonas Devlieghere                "reason = ",
119*2238dcc3SJonas Devlieghere                '"SomeReason"',
120*2238dcc3SJonas Devlieghere                "userInfo = ",
121*2238dcc3SJonas Devlieghere                "1 key/value pair",
122*2238dcc3SJonas Devlieghere                "reserved = ",
123*2238dcc3SJonas Devlieghere            ],
124*2238dcc3SJonas Devlieghere        )
12599451b44SJordan Rupprecht
12699451b44SJordan Rupprecht        e2 = frame.FindVariable("e2")
12799451b44SJordan Rupprecht        self.assertTrue(e2)
12899451b44SJordan Rupprecht        self.assertEqual(e2.type.name, "NSException *")
12999451b44SJordan Rupprecht        self.assertEqual(e2.GetSummary(), '"SomeReason"')
130*2238dcc3SJonas Devlieghere        self.assertEqual(
131*2238dcc3SJonas Devlieghere            e2.GetChildMemberWithName("name").description, "ThrownException"
132*2238dcc3SJonas Devlieghere        )
13399451b44SJordan Rupprecht        self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason")
13499451b44SJordan Rupprecht        userInfo = e2.GetChildMemberWithName("userInfo").dynamic
13599451b44SJordan Rupprecht        self.assertEqual(userInfo.summary, "1 key/value pair")
136*2238dcc3SJonas Devlieghere        self.assertEqual(
137*2238dcc3SJonas Devlieghere            userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key"
138*2238dcc3SJonas Devlieghere        )
139*2238dcc3SJonas Devlieghere        self.assertEqual(
140*2238dcc3SJonas Devlieghere            userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value"
141*2238dcc3SJonas Devlieghere        )
14299451b44SJordan Rupprecht        reserved = e2.GetChildMemberWithName("reserved").dynamic
14399451b44SJordan Rupprecht        self.assertGreater(reserved.num_children, 0)
144*2238dcc3SJonas Devlieghere        callStackReturnAddresses = [
145*2238dcc3SJonas Devlieghere            reserved.GetChildAtIndex(i).GetChildAtIndex(1)
146*2238dcc3SJonas Devlieghere            for i in range(0, reserved.GetNumChildren())
147*2238dcc3SJonas Devlieghere            if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description
148*2238dcc3SJonas Devlieghere            == "callStackReturnAddresses"
149*2238dcc3SJonas Devlieghere        ][0].dynamic
150*2238dcc3SJonas Devlieghere        children = [
151*2238dcc3SJonas Devlieghere            callStackReturnAddresses.GetChildAtIndex(i)
152*2238dcc3SJonas Devlieghere            for i in range(0, callStackReturnAddresses.num_children)
153*2238dcc3SJonas Devlieghere        ]
15499451b44SJordan Rupprecht
15599451b44SJordan Rupprecht        pcs = [i.unsigned for i in children]
156*2238dcc3SJonas Devlieghere        names = [
157*2238dcc3SJonas Devlieghere            target.ResolveSymbolContextForAddress(
158*2238dcc3SJonas Devlieghere                lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol
159*2238dcc3SJonas Devlieghere            )
160*2238dcc3SJonas Devlieghere            .GetSymbol()
161*2238dcc3SJonas Devlieghere            .name
162*2238dcc3SJonas Devlieghere            for pc in pcs
163*2238dcc3SJonas Devlieghere        ]
16499451b44SJordan Rupprecht        for n in ["objc_exception_throw", "foo(int)", "main"]:
165*2238dcc3SJonas Devlieghere            self.assertIn(
166*2238dcc3SJonas Devlieghere                n, names, "%s is in the exception backtrace (%s)" % (n, names)
167*2238dcc3SJonas Devlieghere            )
16899451b44SJordan Rupprecht
169*2238dcc3SJonas Devlieghere    @skipIf(compiler="clang", compiler_version=["<", "13.0"])
17099451b44SJordan Rupprecht    def test_objc_exceptions_at_abort(self):
17199451b44SJordan Rupprecht        self.build()
17299451b44SJordan Rupprecht
17399451b44SJordan Rupprecht        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
17499451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
17599451b44SJordan Rupprecht
17699451b44SJordan Rupprecht        self.runCmd("run 0")
17799451b44SJordan Rupprecht
17899451b44SJordan Rupprecht        # We should be stopped at pthread_kill because of an unhandled exception
179*2238dcc3SJonas Devlieghere        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])
18099451b44SJordan Rupprecht
181*2238dcc3SJonas Devlieghere        self.expect(
182*2238dcc3SJonas Devlieghere            "thread exception",
183*2238dcc3SJonas Devlieghere            substrs=[
184*2238dcc3SJonas Devlieghere                "(NSException *) exception = ",
18599451b44SJordan Rupprecht                '"SomeReason"',
186*2238dcc3SJonas Devlieghere                "libobjc.A.dylib`objc_exception_throw",
187*2238dcc3SJonas Devlieghere                "a.out`foo",
188*2238dcc3SJonas Devlieghere                "at main.mm:16",
189*2238dcc3SJonas Devlieghere                "a.out`rethrow",
190*2238dcc3SJonas Devlieghere                "at main.mm:27",
191*2238dcc3SJonas Devlieghere                "a.out`main",
192*2238dcc3SJonas Devlieghere            ],
193*2238dcc3SJonas Devlieghere        )
19499451b44SJordan Rupprecht
19599451b44SJordan Rupprecht        process = self.dbg.GetSelectedTarget().process
19699451b44SJordan Rupprecht        thread = process.GetSelectedThread()
19799451b44SJordan Rupprecht
19899451b44SJordan Rupprecht        # There is an exception being currently processed at this point
19999451b44SJordan Rupprecht        self.assertTrue(thread.GetCurrentException().IsValid())
20099451b44SJordan Rupprecht        self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid())
20199451b44SJordan Rupprecht
20299451b44SJordan Rupprecht        history_thread = thread.GetCurrentExceptionBacktrace()
20399451b44SJordan Rupprecht        self.assertGreaterEqual(history_thread.num_frames, 4)
20499451b44SJordan Rupprecht        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:
205*2238dcc3SJonas Devlieghere            self.assertEqual(
206*2238dcc3SJonas Devlieghere                len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1
207*2238dcc3SJonas Devlieghere            )
20899451b44SJordan Rupprecht
20999451b44SJordan Rupprecht        self.runCmd("kill")
21099451b44SJordan Rupprecht
21199451b44SJordan Rupprecht        self.runCmd("run 1")
21299451b44SJordan Rupprecht        # We should be stopped at pthread_kill because of an unhandled exception
213*2238dcc3SJonas Devlieghere        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])
21499451b44SJordan Rupprecht
215*2238dcc3SJonas Devlieghere        self.expect(
216*2238dcc3SJonas Devlieghere            "thread exception",
217*2238dcc3SJonas Devlieghere            substrs=[
218*2238dcc3SJonas Devlieghere                "(MyCustomException *) exception = ",
219*2238dcc3SJonas Devlieghere                "libobjc.A.dylib`objc_exception_throw",
220*2238dcc3SJonas Devlieghere                "a.out`foo",
221*2238dcc3SJonas Devlieghere                "at main.mm:18",
222*2238dcc3SJonas Devlieghere                "a.out`rethrow",
223*2238dcc3SJonas Devlieghere                "at main.mm:27",
224*2238dcc3SJonas Devlieghere                "a.out`main",
225*2238dcc3SJonas Devlieghere            ],
226*2238dcc3SJonas Devlieghere        )
22799451b44SJordan Rupprecht
22899451b44SJordan Rupprecht        process = self.dbg.GetSelectedTarget().process
22999451b44SJordan Rupprecht        thread = process.GetSelectedThread()
23099451b44SJordan Rupprecht
23199451b44SJordan Rupprecht        history_thread = thread.GetCurrentExceptionBacktrace()
23299451b44SJordan Rupprecht        self.assertGreaterEqual(history_thread.num_frames, 4)
23399451b44SJordan Rupprecht        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:
234*2238dcc3SJonas Devlieghere            self.assertEqual(
235*2238dcc3SJonas Devlieghere                len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1
236*2238dcc3SJonas Devlieghere            )
23799451b44SJordan Rupprecht
238*2238dcc3SJonas Devlieghere    @skipIf(compiler="clang", compiler_version=["<", "13.0"])
23999451b44SJordan Rupprecht    def test_cxx_exceptions_at_abort(self):
24099451b44SJordan Rupprecht        self.build()
24199451b44SJordan Rupprecht
24299451b44SJordan Rupprecht        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
24399451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
24499451b44SJordan Rupprecht
24599451b44SJordan Rupprecht        self.runCmd("run 2")
24699451b44SJordan Rupprecht
24799451b44SJordan Rupprecht        # We should be stopped at pthread_kill because of an unhandled exception
248*2238dcc3SJonas Devlieghere        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])
24999451b44SJordan Rupprecht
250*2238dcc3SJonas Devlieghere        self.expect("thread exception", substrs=["exception ="])
25199451b44SJordan Rupprecht
25299451b44SJordan Rupprecht        process = self.dbg.GetSelectedTarget().process
25399451b44SJordan Rupprecht        thread = process.GetSelectedThread()
25499451b44SJordan Rupprecht
25599451b44SJordan Rupprecht        self.assertTrue(thread.GetCurrentException().IsValid())
25699451b44SJordan Rupprecht
25799451b44SJordan Rupprecht        # C++ exception backtraces are not exposed in the API (yet).
25899451b44SJordan Rupprecht        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())
259