199451b44SJordan Rupprecht# encoding: utf-8 299451b44SJordan Rupprecht""" 399451b44SJordan RupprechtTest lldb Obj-C exception support. 499451b44SJordan Rupprecht""" 599451b44SJordan Rupprecht 699451b44SJordan Rupprecht 799451b44SJordan Rupprecht 899451b44SJordan Rupprechtimport lldb 999451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 1099451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 1199451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 1299451b44SJordan Rupprecht 1399451b44SJordan Rupprecht 1499451b44SJordan Rupprechtclass ObjCExceptionsTestCase(TestBase): 1599451b44SJordan Rupprecht 1699451b44SJordan Rupprecht def test_objc_exceptions_at_throw(self): 1799451b44SJordan Rupprecht self.build() 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprecht target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 2099451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 2199451b44SJordan Rupprecht 2299451b44SJordan Rupprecht launch_info = lldb.SBLaunchInfo(["a.out", "0"]) 23254e0abfSJonas Devlieghere launch_info.SetLaunchFlags(lldb.eLaunchFlagInheritTCCFromParent) 2499451b44SJordan Rupprecht lldbutil.run_to_name_breakpoint(self, "objc_exception_throw", launch_info=launch_info) 2599451b44SJordan Rupprecht 2699451b44SJordan Rupprecht self.expect("thread list", 2799451b44SJordan Rupprecht substrs=['stopped', 'stop reason = hit Objective-C exception']) 2899451b44SJordan Rupprecht 2999451b44SJordan Rupprecht self.expect('thread exception', substrs=[ 3099451b44SJordan Rupprecht '(NSException *) exception = ', 3199451b44SJordan Rupprecht '"SomeReason"', 3299451b44SJordan Rupprecht ]) 3399451b44SJordan Rupprecht 3499451b44SJordan Rupprecht target = self.dbg.GetSelectedTarget() 3599451b44SJordan Rupprecht thread = target.GetProcess().GetSelectedThread() 3699451b44SJordan Rupprecht frame = thread.GetSelectedFrame() 3799451b44SJordan Rupprecht 3899451b44SJordan Rupprecht opts = lldb.SBVariablesOptions() 3999451b44SJordan Rupprecht opts.SetIncludeRecognizedArguments(True) 4099451b44SJordan Rupprecht variables = frame.GetVariables(opts) 4199451b44SJordan Rupprecht 4299451b44SJordan Rupprecht self.assertEqual(variables.GetSize(), 1) 4399451b44SJordan Rupprecht self.assertEqual(variables.GetValueAtIndex(0).name, "exception") 4499451b44SJordan Rupprecht self.assertEqual(variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument) 4599451b44SJordan Rupprecht 4699451b44SJordan Rupprecht lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.mm"), launch_info=launch_info) 4799451b44SJordan Rupprecht 4899451b44SJordan Rupprecht self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 4999451b44SJordan Rupprecht substrs=['stopped', 'stop reason = breakpoint']) 5099451b44SJordan Rupprecht 5199451b44SJordan Rupprecht target = self.dbg.GetSelectedTarget() 5299451b44SJordan Rupprecht thread = target.GetProcess().GetSelectedThread() 5399451b44SJordan Rupprecht frame = thread.GetSelectedFrame() 5499451b44SJordan Rupprecht 5599451b44SJordan Rupprecht # No exception being currently thrown/caught at this point 5699451b44SJordan Rupprecht self.assertFalse(thread.GetCurrentException().IsValid()) 5799451b44SJordan Rupprecht self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) 5899451b44SJordan Rupprecht 5999451b44SJordan Rupprecht self.expect( 6099451b44SJordan Rupprecht 'frame variable e1', 6199451b44SJordan Rupprecht substrs=[ 6299451b44SJordan Rupprecht '(NSException *) e1 = ', 6399451b44SJordan Rupprecht '"SomeReason"' 6499451b44SJordan Rupprecht ]) 6599451b44SJordan Rupprecht 6699451b44SJordan Rupprecht self.expect( 6799451b44SJordan Rupprecht 'frame variable --dynamic-type no-run-target *e1', 6899451b44SJordan Rupprecht substrs=[ 6999451b44SJordan Rupprecht '(NSException) *e1 = ', 7099451b44SJordan Rupprecht 'name = ', '"ExceptionName"', 7199451b44SJordan Rupprecht 'reason = ', '"SomeReason"', 7299451b44SJordan Rupprecht 'userInfo = ', '1 key/value pair', 7399451b44SJordan Rupprecht 'reserved = ', 'nil', 7499451b44SJordan Rupprecht ]) 7599451b44SJordan Rupprecht 7699451b44SJordan Rupprecht e1 = frame.FindVariable("e1") 7799451b44SJordan Rupprecht self.assertTrue(e1) 7899451b44SJordan Rupprecht self.assertEqual(e1.type.name, "NSException *") 7999451b44SJordan Rupprecht self.assertEqual(e1.GetSummary(), '"SomeReason"') 8099451b44SJordan Rupprecht self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName") 8199451b44SJordan Rupprecht self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason") 8299451b44SJordan Rupprecht userInfo = e1.GetChildMemberWithName("userInfo").dynamic 8399451b44SJordan Rupprecht self.assertEqual(userInfo.summary, "1 key/value pair") 8499451b44SJordan Rupprecht self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") 8599451b44SJordan Rupprecht self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") 8699451b44SJordan Rupprecht self.assertEqual(e1.GetChildMemberWithName("reserved").description, "<nil>") 8799451b44SJordan Rupprecht 8899451b44SJordan Rupprecht self.expect( 8999451b44SJordan Rupprecht 'frame variable e2', 9099451b44SJordan Rupprecht substrs=[ 9199451b44SJordan Rupprecht '(NSException *) e2 = ', 9299451b44SJordan Rupprecht '"SomeReason"' 9399451b44SJordan Rupprecht ]) 9499451b44SJordan Rupprecht 9599451b44SJordan Rupprecht self.expect( 9699451b44SJordan Rupprecht 'frame variable --dynamic-type no-run-target *e2', 9799451b44SJordan Rupprecht substrs=[ 9899451b44SJordan Rupprecht '(NSException) *e2 = ', 9999451b44SJordan Rupprecht 'name = ', '"ThrownException"', 10099451b44SJordan Rupprecht 'reason = ', '"SomeReason"', 10199451b44SJordan Rupprecht 'userInfo = ', '1 key/value pair', 10299451b44SJordan Rupprecht 'reserved = ', 10399451b44SJordan Rupprecht ]) 10499451b44SJordan Rupprecht 10599451b44SJordan Rupprecht e2 = frame.FindVariable("e2") 10699451b44SJordan Rupprecht self.assertTrue(e2) 10799451b44SJordan Rupprecht self.assertEqual(e2.type.name, "NSException *") 10899451b44SJordan Rupprecht self.assertEqual(e2.GetSummary(), '"SomeReason"') 10999451b44SJordan Rupprecht self.assertEqual(e2.GetChildMemberWithName("name").description, "ThrownException") 11099451b44SJordan Rupprecht self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason") 11199451b44SJordan Rupprecht userInfo = e2.GetChildMemberWithName("userInfo").dynamic 11299451b44SJordan Rupprecht self.assertEqual(userInfo.summary, "1 key/value pair") 11399451b44SJordan Rupprecht self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") 11499451b44SJordan Rupprecht self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") 11599451b44SJordan Rupprecht reserved = e2.GetChildMemberWithName("reserved").dynamic 11699451b44SJordan Rupprecht self.assertGreater(reserved.num_children, 0) 11799451b44SJordan Rupprecht callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren()) 11899451b44SJordan Rupprecht if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic 11999451b44SJordan Rupprecht children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)] 12099451b44SJordan Rupprecht 12199451b44SJordan Rupprecht pcs = [i.unsigned for i in children] 12299451b44SJordan Rupprecht names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs] 12399451b44SJordan Rupprecht for n in ["objc_exception_throw", "foo(int)", "main"]: 124*3cc37622SDave Lee self.assertIn(n, names, "%s is in the exception backtrace (%s)" % (n, names)) 12599451b44SJordan Rupprecht 12699451b44SJordan Rupprecht def test_objc_exceptions_at_abort(self): 12799451b44SJordan Rupprecht self.build() 12899451b44SJordan Rupprecht 12999451b44SJordan Rupprecht target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 13099451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 13199451b44SJordan Rupprecht 13299451b44SJordan Rupprecht self.runCmd("run 0") 13399451b44SJordan Rupprecht 13499451b44SJordan Rupprecht # We should be stopped at pthread_kill because of an unhandled exception 13599451b44SJordan Rupprecht self.expect("thread list", 13699451b44SJordan Rupprecht substrs=['stopped', 'stop reason = signal SIGABRT']) 13799451b44SJordan Rupprecht 13899451b44SJordan Rupprecht self.expect('thread exception', substrs=[ 13999451b44SJordan Rupprecht '(NSException *) exception = ', 14099451b44SJordan Rupprecht '"SomeReason"', 14199451b44SJordan Rupprecht 'libobjc.A.dylib`objc_exception_throw', 142fdea9a4eSRaphael Isemann 'a.out`foo', 'at main.mm:16', 143fdea9a4eSRaphael Isemann 'a.out`rethrow', 'at main.mm:27', 14499451b44SJordan Rupprecht 'a.out`main', 14599451b44SJordan Rupprecht ]) 14699451b44SJordan Rupprecht 14799451b44SJordan Rupprecht process = self.dbg.GetSelectedTarget().process 14899451b44SJordan Rupprecht thread = process.GetSelectedThread() 14999451b44SJordan Rupprecht 15099451b44SJordan Rupprecht # There is an exception being currently processed at this point 15199451b44SJordan Rupprecht self.assertTrue(thread.GetCurrentException().IsValid()) 15299451b44SJordan Rupprecht self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid()) 15399451b44SJordan Rupprecht 15499451b44SJordan Rupprecht history_thread = thread.GetCurrentExceptionBacktrace() 15599451b44SJordan Rupprecht self.assertGreaterEqual(history_thread.num_frames, 4) 15699451b44SJordan Rupprecht for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: 15799451b44SJordan Rupprecht self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) 15899451b44SJordan Rupprecht 15999451b44SJordan Rupprecht self.runCmd("kill") 16099451b44SJordan Rupprecht 16199451b44SJordan Rupprecht self.runCmd("run 1") 16299451b44SJordan Rupprecht # We should be stopped at pthread_kill because of an unhandled exception 16399451b44SJordan Rupprecht self.expect("thread list", 16499451b44SJordan Rupprecht substrs=['stopped', 'stop reason = signal SIGABRT']) 16599451b44SJordan Rupprecht 16699451b44SJordan Rupprecht self.expect('thread exception', substrs=[ 16799451b44SJordan Rupprecht '(MyCustomException *) exception = ', 16899451b44SJordan Rupprecht 'libobjc.A.dylib`objc_exception_throw', 169fdea9a4eSRaphael Isemann 'a.out`foo', 'at main.mm:18', 170fdea9a4eSRaphael Isemann 'a.out`rethrow', 'at main.mm:27', 17199451b44SJordan Rupprecht 'a.out`main', 17299451b44SJordan Rupprecht ]) 17399451b44SJordan Rupprecht 17499451b44SJordan Rupprecht process = self.dbg.GetSelectedTarget().process 17599451b44SJordan Rupprecht thread = process.GetSelectedThread() 17699451b44SJordan Rupprecht 17799451b44SJordan Rupprecht history_thread = thread.GetCurrentExceptionBacktrace() 17899451b44SJordan Rupprecht self.assertGreaterEqual(history_thread.num_frames, 4) 17999451b44SJordan Rupprecht for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]: 18099451b44SJordan Rupprecht self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1) 18199451b44SJordan Rupprecht 18299451b44SJordan Rupprecht def test_cxx_exceptions_at_abort(self): 18399451b44SJordan Rupprecht self.build() 18499451b44SJordan Rupprecht 18599451b44SJordan Rupprecht target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 18699451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 18799451b44SJordan Rupprecht 18899451b44SJordan Rupprecht self.runCmd("run 2") 18999451b44SJordan Rupprecht 19099451b44SJordan Rupprecht # We should be stopped at pthread_kill because of an unhandled exception 19199451b44SJordan Rupprecht self.expect("thread list", 19299451b44SJordan Rupprecht substrs=['stopped', 'stop reason = signal SIGABRT']) 19399451b44SJordan Rupprecht 19499451b44SJordan Rupprecht self.expect('thread exception', substrs=['exception =']) 19599451b44SJordan Rupprecht 19699451b44SJordan Rupprecht process = self.dbg.GetSelectedTarget().process 19799451b44SJordan Rupprecht thread = process.GetSelectedThread() 19899451b44SJordan Rupprecht 19999451b44SJordan Rupprecht self.assertTrue(thread.GetCurrentException().IsValid()) 20099451b44SJordan Rupprecht 20199451b44SJordan Rupprecht # C++ exception backtraces are not exposed in the API (yet). 20299451b44SJordan Rupprecht self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) 203