1*99451b44SJordan Rupprecht""" 2*99451b44SJordan RupprechtUse lldb Python API to test dynamic values in ObjC 3*99451b44SJordan Rupprecht""" 4*99451b44SJordan Rupprecht 5*99451b44SJordan Rupprecht 6*99451b44SJordan Rupprecht 7*99451b44SJordan Rupprechtimport lldb 8*99451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 9*99451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 10*99451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 11*99451b44SJordan Rupprecht 12*99451b44SJordan Rupprecht 13*99451b44SJordan Rupprechtclass ObjCDynamicValueTestCase(TestBase): 14*99451b44SJordan Rupprecht 15*99451b44SJordan Rupprecht mydir = TestBase.compute_mydir(__file__) 16*99451b44SJordan Rupprecht 17*99451b44SJordan Rupprecht def setUp(self): 18*99451b44SJordan Rupprecht # Call super's setUp(). 19*99451b44SJordan Rupprecht TestBase.setUp(self) 20*99451b44SJordan Rupprecht 21*99451b44SJordan Rupprecht # Find the line number to break for main.c. 22*99451b44SJordan Rupprecht 23*99451b44SJordan Rupprecht self.source_name = 'dynamic-value.m' 24*99451b44SJordan Rupprecht self.set_property_line = line_number( 25*99451b44SJordan Rupprecht self.source_name, 26*99451b44SJordan Rupprecht '// This is the line in setProperty, make sure we step to here.') 27*99451b44SJordan Rupprecht self.handle_SourceBase = line_number( 28*99451b44SJordan Rupprecht self.source_name, '// Break here to check dynamic values.') 29*99451b44SJordan Rupprecht self.main_before_setProperty_line = line_number( 30*99451b44SJordan Rupprecht self.source_name, '// Break here to see if we can step into real method.') 31*99451b44SJordan Rupprecht 32*99451b44SJordan Rupprecht @skipUnlessDarwin 33*99451b44SJordan Rupprecht @add_test_categories(['pyapi']) 34*99451b44SJordan Rupprecht @expectedFailureDarwin("llvm.org/pr20271 rdar://18684107") 35*99451b44SJordan Rupprecht def test_get_objc_dynamic_vals(self): 36*99451b44SJordan Rupprecht """Test fetching ObjC dynamic values.""" 37*99451b44SJordan Rupprecht if self.getArchitecture() == 'i386': 38*99451b44SJordan Rupprecht # rdar://problem/9946499 39*99451b44SJordan Rupprecht self.skipTest("Dynamic types for ObjC V1 runtime not implemented") 40*99451b44SJordan Rupprecht 41*99451b44SJordan Rupprecht self.build() 42*99451b44SJordan Rupprecht exe = self.getBuildArtifact("a.out") 43*99451b44SJordan Rupprecht 44*99451b44SJordan Rupprecht # Create a target from the debugger. 45*99451b44SJordan Rupprecht 46*99451b44SJordan Rupprecht target = self.dbg.CreateTarget(exe) 47*99451b44SJordan Rupprecht self.assertTrue(target, VALID_TARGET) 48*99451b44SJordan Rupprecht 49*99451b44SJordan Rupprecht # Set up our breakpoints: 50*99451b44SJordan Rupprecht 51*99451b44SJordan Rupprecht handle_SourceBase_bkpt = target.BreakpointCreateByLocation( 52*99451b44SJordan Rupprecht self.source_name, self.handle_SourceBase) 53*99451b44SJordan Rupprecht self.assertTrue(handle_SourceBase_bkpt and 54*99451b44SJordan Rupprecht handle_SourceBase_bkpt.GetNumLocations() == 1, 55*99451b44SJordan Rupprecht VALID_BREAKPOINT) 56*99451b44SJordan Rupprecht 57*99451b44SJordan Rupprecht main_before_setProperty_bkpt = target.BreakpointCreateByLocation( 58*99451b44SJordan Rupprecht self.source_name, self.main_before_setProperty_line) 59*99451b44SJordan Rupprecht self.assertTrue(main_before_setProperty_bkpt and 60*99451b44SJordan Rupprecht main_before_setProperty_bkpt.GetNumLocations() == 1, 61*99451b44SJordan Rupprecht VALID_BREAKPOINT) 62*99451b44SJordan Rupprecht 63*99451b44SJordan Rupprecht # Now launch the process, and do not stop at the entry point. 64*99451b44SJordan Rupprecht process = target.LaunchSimple( 65*99451b44SJordan Rupprecht None, None, self.get_process_working_directory()) 66*99451b44SJordan Rupprecht 67*99451b44SJordan Rupprecht self.assertTrue(process.GetState() == lldb.eStateStopped, 68*99451b44SJordan Rupprecht PROCESS_STOPPED) 69*99451b44SJordan Rupprecht 70*99451b44SJordan Rupprecht threads = lldbutil.get_threads_stopped_at_breakpoint( 71*99451b44SJordan Rupprecht process, main_before_setProperty_bkpt) 72*99451b44SJordan Rupprecht self.assertTrue(len(threads) == 1) 73*99451b44SJordan Rupprecht thread = threads[0] 74*99451b44SJordan Rupprecht 75*99451b44SJordan Rupprecht # 76*99451b44SJordan Rupprecht # At this point, myObserver has a Source pointer that is actually a KVO swizzled SourceDerived 77*99451b44SJordan Rupprecht # make sure we can get that properly: 78*99451b44SJordan Rupprecht 79*99451b44SJordan Rupprecht frame = thread.GetFrameAtIndex(0) 80*99451b44SJordan Rupprecht myObserver = frame.FindVariable( 81*99451b44SJordan Rupprecht 'myObserver', lldb.eDynamicCanRunTarget) 82*99451b44SJordan Rupprecht self.assertTrue(myObserver) 83*99451b44SJordan Rupprecht myObserver_source = myObserver.GetChildMemberWithName( 84*99451b44SJordan Rupprecht '_source', lldb.eDynamicCanRunTarget) 85*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(myObserver_source) 86*99451b44SJordan Rupprecht 87*99451b44SJordan Rupprecht # 88*99451b44SJordan Rupprecht # Make sure a static value can be correctly turned into a dynamic 89*99451b44SJordan Rupprecht # value. 90*99451b44SJordan Rupprecht 91*99451b44SJordan Rupprecht frame = thread.GetFrameAtIndex(0) 92*99451b44SJordan Rupprecht myObserver_static = frame.FindVariable( 93*99451b44SJordan Rupprecht 'myObserver', lldb.eNoDynamicValues) 94*99451b44SJordan Rupprecht self.assertTrue(myObserver_static) 95*99451b44SJordan Rupprecht myObserver = myObserver_static.GetDynamicValue( 96*99451b44SJordan Rupprecht lldb.eDynamicCanRunTarget) 97*99451b44SJordan Rupprecht myObserver_source = myObserver.GetChildMemberWithName( 98*99451b44SJordan Rupprecht '_source', lldb.eDynamicCanRunTarget) 99*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(myObserver_source) 100*99451b44SJordan Rupprecht 101*99451b44SJordan Rupprecht # The "frame var" code uses another path to get into children, so let's 102*99451b44SJordan Rupprecht # make sure that works as well: 103*99451b44SJordan Rupprecht 104*99451b44SJordan Rupprecht result = lldb.SBCommandReturnObject() 105*99451b44SJordan Rupprecht 106*99451b44SJordan Rupprecht self.expect( 107*99451b44SJordan Rupprecht 'frame var -d run-target myObserver->_source', 108*99451b44SJordan Rupprecht 'frame var finds its way into a child member', 109*99451b44SJordan Rupprecht patterns=['\(SourceDerived \*\)']) 110*99451b44SJordan Rupprecht 111*99451b44SJordan Rupprecht # check that our ObjC GetISA() does a good job at hiding KVO swizzled 112*99451b44SJordan Rupprecht # classes 113*99451b44SJordan Rupprecht 114*99451b44SJordan Rupprecht self.expect( 115*99451b44SJordan Rupprecht 'frame var -d run-target myObserver->_source -T', 116*99451b44SJordan Rupprecht 'the KVO-ed class is hidden', 117*99451b44SJordan Rupprecht substrs=['SourceDerived']) 118*99451b44SJordan Rupprecht 119*99451b44SJordan Rupprecht self.expect( 120*99451b44SJordan Rupprecht 'frame var -d run-target myObserver->_source -T', 121*99451b44SJordan Rupprecht 'the KVO-ed class is hidden', 122*99451b44SJordan Rupprecht matching=False, 123*99451b44SJordan Rupprecht substrs=['NSKVONotify']) 124*99451b44SJordan Rupprecht 125*99451b44SJordan Rupprecht # This test is not entirely related to the main thrust of this test case, but since we're here, 126*99451b44SJordan Rupprecht # try stepping into setProperty, and make sure we get into the version 127*99451b44SJordan Rupprecht # in Source: 128*99451b44SJordan Rupprecht 129*99451b44SJordan Rupprecht thread.StepInto() 130*99451b44SJordan Rupprecht 131*99451b44SJordan Rupprecht threads = lldbutil.get_stopped_threads( 132*99451b44SJordan Rupprecht process, lldb.eStopReasonPlanComplete) 133*99451b44SJordan Rupprecht self.assertTrue(len(threads) == 1) 134*99451b44SJordan Rupprecht line_entry = threads[0].GetFrameAtIndex(0).GetLineEntry() 135*99451b44SJordan Rupprecht 136*99451b44SJordan Rupprecht self.assertEqual(line_entry.GetLine(), self.set_property_line) 137*99451b44SJordan Rupprecht self.assertEqual( 138*99451b44SJordan Rupprecht line_entry.GetFileSpec().GetFilename(), 139*99451b44SJordan Rupprecht self.source_name) 140*99451b44SJordan Rupprecht 141*99451b44SJordan Rupprecht # Okay, back to the main business. Continue to the handle_SourceBase 142*99451b44SJordan Rupprecht # and make sure we get the correct dynamic value. 143*99451b44SJordan Rupprecht 144*99451b44SJordan Rupprecht threads = lldbutil.continue_to_breakpoint( 145*99451b44SJordan Rupprecht process, handle_SourceBase_bkpt) 146*99451b44SJordan Rupprecht self.assertTrue(len(threads) == 1) 147*99451b44SJordan Rupprecht thread = threads[0] 148*99451b44SJordan Rupprecht 149*99451b44SJordan Rupprecht frame = thread.GetFrameAtIndex(0) 150*99451b44SJordan Rupprecht 151*99451b44SJordan Rupprecht # Get "object" using FindVariable: 152*99451b44SJordan Rupprecht 153*99451b44SJordan Rupprecht noDynamic = lldb.eNoDynamicValues 154*99451b44SJordan Rupprecht useDynamic = lldb.eDynamicCanRunTarget 155*99451b44SJordan Rupprecht 156*99451b44SJordan Rupprecht object_static = frame.FindVariable('object', noDynamic) 157*99451b44SJordan Rupprecht object_dynamic = frame.FindVariable('object', useDynamic) 158*99451b44SJordan Rupprecht 159*99451b44SJordan Rupprecht # Delete this object to make sure that this doesn't cause havoc with 160*99451b44SJordan Rupprecht # the dynamic object that depends on it. 161*99451b44SJordan Rupprecht del (object_static) 162*99451b44SJordan Rupprecht 163*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(object_dynamic) 164*99451b44SJordan Rupprecht 165*99451b44SJordan Rupprecht # Get "this" using FindValue, make sure that works too: 166*99451b44SJordan Rupprecht object_static = frame.FindValue( 167*99451b44SJordan Rupprecht 'object', lldb.eValueTypeVariableArgument, noDynamic) 168*99451b44SJordan Rupprecht object_dynamic = frame.FindValue( 169*99451b44SJordan Rupprecht 'object', lldb.eValueTypeVariableArgument, useDynamic) 170*99451b44SJordan Rupprecht del (object_static) 171*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(object_dynamic) 172*99451b44SJordan Rupprecht 173*99451b44SJordan Rupprecht # Get "this" using the EvaluateExpression: 174*99451b44SJordan Rupprecht object_static = frame.EvaluateExpression('object', noDynamic) 175*99451b44SJordan Rupprecht object_dynamic = frame.EvaluateExpression('object', useDynamic) 176*99451b44SJordan Rupprecht del (object_static) 177*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(object_dynamic) 178*99451b44SJordan Rupprecht 179*99451b44SJordan Rupprecht # Continue again to the handle_SourceBase and make sure we get the correct dynamic value. 180*99451b44SJordan Rupprecht # This one looks exactly the same, but in fact this is an "un-KVO'ed" version of SourceBase, so 181*99451b44SJordan Rupprecht # its isa pointer points to SourceBase not NSKVOSourceBase or 182*99451b44SJordan Rupprecht # whatever... 183*99451b44SJordan Rupprecht 184*99451b44SJordan Rupprecht threads = lldbutil.continue_to_breakpoint( 185*99451b44SJordan Rupprecht process, handle_SourceBase_bkpt) 186*99451b44SJordan Rupprecht self.assertTrue(len(threads) == 1) 187*99451b44SJordan Rupprecht thread = threads[0] 188*99451b44SJordan Rupprecht 189*99451b44SJordan Rupprecht frame = thread.GetFrameAtIndex(0) 190*99451b44SJordan Rupprecht 191*99451b44SJordan Rupprecht # Get "object" using FindVariable: 192*99451b44SJordan Rupprecht 193*99451b44SJordan Rupprecht object_static = frame.FindVariable('object', noDynamic) 194*99451b44SJordan Rupprecht object_dynamic = frame.FindVariable('object', useDynamic) 195*99451b44SJordan Rupprecht 196*99451b44SJordan Rupprecht # Delete this object to make sure that this doesn't cause havoc with 197*99451b44SJordan Rupprecht # the dynamic object that depends on it. 198*99451b44SJordan Rupprecht del (object_static) 199*99451b44SJordan Rupprecht 200*99451b44SJordan Rupprecht self.examine_SourceDerived_ptr(object_dynamic) 201*99451b44SJordan Rupprecht 202*99451b44SJordan Rupprecht def examine_SourceDerived_ptr(self, object): 203*99451b44SJordan Rupprecht self.assertTrue(object) 204*99451b44SJordan Rupprecht self.assertTrue(object.GetTypeName().find('SourceDerived') != -1) 205*99451b44SJordan Rupprecht derivedValue = object.GetChildMemberWithName('_derivedValue') 206*99451b44SJordan Rupprecht self.assertTrue(derivedValue) 207*99451b44SJordan Rupprecht self.assertTrue(int(derivedValue.GetValue(), 0) == 30) 208