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