brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.9 KiB · 3763fa4 Raw
259 lines · python
1# encoding: utf-82"""3Test lldb Obj-C exception support.4"""5 6 7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10from lldbsuite.test import lldbutil11 12 13class ObjCExceptionsTestCase(TestBase):14    @skipIf(compiler="clang", compiler_version=["<", "13.0"])15    def test_objc_exceptions_at_throw(self):16        self.build()17 18        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))19        self.assertTrue(target, VALID_TARGET)20 21        launch_info = lldb.SBLaunchInfo(["a.out", "0"])22        launch_info.SetLaunchFlags(lldb.eLaunchFlagInheritTCCFromParent)23        lldbutil.run_to_name_breakpoint(24            self, "objc_exception_throw", launch_info=launch_info25        )26 27        self.expect(28            "thread list",29            substrs=["stopped", "stop reason = hit Objective-C exception"],30        )31 32        self.expect(33            "thread exception",34            substrs=[35                "(NSException *) exception = ",36                '"SomeReason"',37            ],38        )39 40        target = self.dbg.GetSelectedTarget()41        thread = target.GetProcess().GetSelectedThread()42        frame = thread.GetSelectedFrame()43 44        opts = lldb.SBVariablesOptions()45        opts.SetIncludeRecognizedArguments(True)46        variables = frame.GetVariables(opts)47 48        self.assertEqual(variables.GetSize(), 1)49        self.assertEqual(variables.GetValueAtIndex(0).name, "exception")50        self.assertEqual(51            variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument52        )53 54        lldbutil.run_to_source_breakpoint(55            self,56            "// Set break point at this line.",57            lldb.SBFileSpec("main.mm"),58            launch_info=launch_info,59        )60 61        self.expect(62            "thread list",63            STOPPED_DUE_TO_BREAKPOINT,64            substrs=["stopped", "stop reason = breakpoint"],65        )66 67        target = self.dbg.GetSelectedTarget()68        thread = target.GetProcess().GetSelectedThread()69        frame = thread.GetSelectedFrame()70 71        # No exception being currently thrown/caught at this point72        self.assertFalse(thread.GetCurrentException().IsValid())73        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())74 75        self.expect(76            "frame variable e1", substrs=["(NSException *) e1 = ", '"SomeReason"']77        )78 79        self.expect(80            "frame variable *e1",81            substrs=[82                "(NSException) *e1 = ",83                "name = ",84                '"ExceptionName"',85                "reason = ",86                '"SomeReason"',87                "userInfo = ",88                "1 key/value pair",89                "reserved = ",90            ],91        )92 93        e1 = frame.FindVariable("e1")94        self.assertTrue(e1)95        self.assertEqual(e1.type.name, "NSException *")96        self.assertEqual(e1.GetSummary(), '"SomeReason"')97        self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName")98        self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason")99        userInfo = e1.GetChildMemberWithName("userInfo").dynamic100        self.assertEqual(userInfo.summary, "1 key/value pair")101        self.assertEqual(102            userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key"103        )104        self.assertEqual(105            userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value"106        )107 108        self.expect(109            "frame variable e2", substrs=["(NSException *) e2 = ", '"SomeReason"']110        )111 112        self.expect(113            "frame variable *e2",114            substrs=[115                "(NSException) *e2 = ",116                "name = ",117                '"ThrownException"',118                "reason = ",119                '"SomeReason"',120                "userInfo = ",121                "1 key/value pair",122                "reserved = ",123            ],124        )125 126        e2 = frame.FindVariable("e2")127        self.assertTrue(e2)128        self.assertEqual(e2.type.name, "NSException *")129        self.assertEqual(e2.GetSummary(), '"SomeReason"')130        self.assertEqual(131            e2.GetChildMemberWithName("name").description, "ThrownException"132        )133        self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason")134        userInfo = e2.GetChildMemberWithName("userInfo").dynamic135        self.assertEqual(userInfo.summary, "1 key/value pair")136        self.assertEqual(137            userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key"138        )139        self.assertEqual(140            userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value"141        )142        reserved = e2.GetChildMemberWithName("reserved").dynamic143        self.assertGreater(reserved.num_children, 0)144        callStackReturnAddresses = [145            reserved.GetChildAtIndex(i).GetChildAtIndex(1)146            for i in range(0, reserved.GetNumChildren())147            if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description148            == "callStackReturnAddresses"149        ][0].dynamic150        children = [151            callStackReturnAddresses.GetChildAtIndex(i)152            for i in range(0, callStackReturnAddresses.num_children)153        ]154 155        pcs = [i.unsigned for i in children]156        names = [157            target.ResolveSymbolContextForAddress(158                lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol159            )160            .GetSymbol()161            .name162            for pc in pcs163        ]164        for n in ["objc_exception_throw", "foo(int)", "main"]:165            self.assertIn(166                n, names, "%s is in the exception backtrace (%s)" % (n, names)167            )168 169    @skipIf(compiler="clang", compiler_version=["<", "13.0"])170    def test_objc_exceptions_at_abort(self):171        self.build()172 173        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))174        self.assertTrue(target, VALID_TARGET)175 176        self.runCmd("run 0")177 178        # We should be stopped at pthread_kill because of an unhandled exception179        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])180 181        self.expect(182            "thread exception",183            substrs=[184                "(NSException *) exception = ",185                '"SomeReason"',186                "libobjc.A.dylib`objc_exception_throw",187                "a.out`foo",188                "at main.mm:16",189                "a.out`rethrow",190                "at main.mm:27",191                "a.out`main",192            ],193        )194 195        process = self.dbg.GetSelectedTarget().process196        thread = process.GetSelectedThread()197 198        # There is an exception being currently processed at this point199        self.assertTrue(thread.GetCurrentException().IsValid())200        self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid())201 202        history_thread = thread.GetCurrentExceptionBacktrace()203        self.assertGreaterEqual(history_thread.num_frames, 4)204        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:205            self.assertEqual(206                len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1207            )208 209        self.runCmd("kill")210 211        self.runCmd("run 1")212        # We should be stopped at pthread_kill because of an unhandled exception213        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])214 215        self.expect(216            "thread exception",217            substrs=[218                "(MyCustomException *) exception = ",219                "libobjc.A.dylib`objc_exception_throw",220                "a.out`foo",221                "at main.mm:18",222                "a.out`rethrow",223                "at main.mm:27",224                "a.out`main",225            ],226        )227 228        process = self.dbg.GetSelectedTarget().process229        thread = process.GetSelectedThread()230 231        history_thread = thread.GetCurrentExceptionBacktrace()232        self.assertGreaterEqual(history_thread.num_frames, 4)233        for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:234            self.assertEqual(235                len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1236            )237 238    @skipIf(compiler="clang", compiler_version=["<", "13.0"])239    def test_cxx_exceptions_at_abort(self):240        self.build()241 242        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))243        self.assertTrue(target, VALID_TARGET)244 245        self.runCmd("run 2")246 247        # We should be stopped at pthread_kill because of an unhandled exception248        self.expect("thread list", substrs=["stopped", "stop reason = signal SIGABRT"])249 250        self.expect("thread exception", substrs=["exception ="])251 252        process = self.dbg.GetSelectedTarget().process253        thread = process.GetSelectedThread()254 255        self.assertTrue(thread.GetCurrentException().IsValid())256 257        # C++ exception backtraces are not exposed in the API (yet).258        self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())259