1""" 2Use lldb Python API to test dynamic values in C++ 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class DynamicValueTestCase(TestBase): 14 15 mydir = TestBase.compute_mydir(__file__) 16 17 def setUp(self): 18 # Call super's setUp(). 19 TestBase.setUp(self) 20 21 # Find the line number to break for main.c. 22 23 self.do_something_line = line_number( 24 'pass-to-base.cpp', '// Break here in doSomething.') 25 self.main_first_call_line = line_number( 26 'pass-to-base.cpp', 27 '// Break here and get real addresses of myB and otherB.') 28 self.main_second_call_line = line_number( 29 'pass-to-base.cpp', '// Break here and get real address of reallyA.') 30 31 @add_test_categories(['pyapi']) 32 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") 33 def test_get_dynamic_vals(self): 34 """Test fetching C++ dynamic values from pointers & references.""" 35 self.build(dictionary=self.getBuildFlags()) 36 exe = self.getBuildArtifact("a.out") 37 38 # Create a target from the debugger. 39 40 target = self.dbg.CreateTarget(exe) 41 self.assertTrue(target, VALID_TARGET) 42 43 # Set up our breakpoints: 44 45 do_something_bpt = target.BreakpointCreateByLocation( 46 'pass-to-base.cpp', self.do_something_line) 47 self.assertTrue(do_something_bpt, 48 VALID_BREAKPOINT) 49 50 first_call_bpt = target.BreakpointCreateByLocation( 51 'pass-to-base.cpp', self.main_first_call_line) 52 self.assertTrue(first_call_bpt, 53 VALID_BREAKPOINT) 54 55 second_call_bpt = target.BreakpointCreateByLocation( 56 'pass-to-base.cpp', self.main_second_call_line) 57 self.assertTrue(second_call_bpt, 58 VALID_BREAKPOINT) 59 60 # Now launch the process, and do not stop at the entry point. 61 process = target.LaunchSimple( 62 None, None, self.get_process_working_directory()) 63 64 self.assertEquals(process.GetState(), lldb.eStateStopped, 65 PROCESS_STOPPED) 66 67 threads = lldbutil.get_threads_stopped_at_breakpoint( 68 process, first_call_bpt) 69 self.assertEquals(len(threads), 1) 70 thread = threads[0] 71 72 frame = thread.GetFrameAtIndex(0) 73 74 # Now find the dynamic addresses of myB and otherB so we can compare them 75 # with the dynamic values we get in doSomething: 76 77 use_dynamic = lldb.eDynamicCanRunTarget 78 no_dynamic = lldb.eNoDynamicValues 79 80 myB = frame.FindVariable('myB', no_dynamic) 81 self.assertTrue(myB) 82 myB_loc = int(myB.GetLocation(), 16) 83 84 otherB = frame.FindVariable('otherB', no_dynamic) 85 self.assertTrue(otherB) 86 otherB_loc = int(otherB.GetLocation(), 16) 87 88 # Okay now run to doSomething: 89 90 threads = lldbutil.continue_to_breakpoint(process, do_something_bpt) 91 self.assertEquals(len(threads), 1) 92 thread = threads[0] 93 94 frame = thread.GetFrameAtIndex(0) 95 96 # Get "this" using FindVariable: 97 98 this_static = frame.FindVariable('this', no_dynamic) 99 this_dynamic = frame.FindVariable('this', use_dynamic) 100 self.examine_value_object_of_this_ptr( 101 this_static, this_dynamic, myB_loc) 102 103 # Now make sure that the "GetDynamicValue" works: 104 # This doesn't work currently because we can't get dynamic values from 105 # ConstResult objects. 106 fetched_dynamic_value = this_static.GetDynamicValue(use_dynamic) 107 self.examine_value_object_of_this_ptr( 108 this_static, fetched_dynamic_value, myB_loc) 109 110 # And conversely that the GetDynamicValue() interface also works: 111 fetched_static_value = this_dynamic.GetStaticValue() 112 self.examine_value_object_of_this_ptr( 113 fetched_static_value, this_dynamic, myB_loc) 114 115 # Get "this" using FindValue, make sure that works too: 116 this_static = frame.FindValue( 117 'this', lldb.eValueTypeVariableArgument, no_dynamic) 118 this_dynamic = frame.FindValue( 119 'this', lldb.eValueTypeVariableArgument, use_dynamic) 120 self.examine_value_object_of_this_ptr( 121 this_static, this_dynamic, myB_loc) 122 123 # Get "this" using the EvaluateExpression: 124 this_static = frame.EvaluateExpression('this', False) 125 this_dynamic = frame.EvaluateExpression('this', True) 126 self.examine_value_object_of_this_ptr( 127 this_static, this_dynamic, myB_loc) 128 129 # The "frame var" code uses another path to get into children, so let's 130 # make sure that works as well: 131 132 self.expect( 133 'frame var -d run-target --ptr-depth=2 --show-types anotherA.m_client_A', 134 'frame var finds its way into a child member', 135 patterns=['\(B \*\)']) 136 137 # Now make sure we also get it right for a reference as well: 138 139 anotherA_static = frame.FindVariable('anotherA', False) 140 self.assertTrue(anotherA_static) 141 anotherA_static_addr = int(anotherA_static.GetValue(), 16) 142 143 anotherA_dynamic = frame.FindVariable('anotherA', True) 144 self.assertTrue(anotherA_dynamic) 145 anotherA_dynamic_addr = int(anotherA_dynamic.GetValue(), 16) 146 anotherA_dynamic_typename = anotherA_dynamic.GetTypeName() 147 self.assertNotEqual(anotherA_dynamic_typename.find('B'), -1) 148 149 self.assertTrue(anotherA_dynamic_addr < anotherA_static_addr) 150 151 anotherA_m_b_value_dynamic = anotherA_dynamic.GetChildMemberWithName( 152 'm_b_value', True) 153 self.assertTrue(anotherA_m_b_value_dynamic) 154 anotherA_m_b_val = int(anotherA_m_b_value_dynamic.GetValue(), 10) 155 self.assertEquals(anotherA_m_b_val, 300) 156 157 anotherA_m_b_value_static = anotherA_static.GetChildMemberWithName( 158 'm_b_value', True) 159 self.assertFalse(anotherA_m_b_value_static) 160 161 # Okay, now continue again, and when we hit the second breakpoint in 162 # main 163 164 threads = lldbutil.continue_to_breakpoint(process, second_call_bpt) 165 self.assertEquals(len(threads), 1) 166 thread = threads[0] 167 168 frame = thread.GetFrameAtIndex(0) 169 reallyA_value = frame.FindVariable('reallyA', False) 170 self.assertTrue(reallyA_value) 171 reallyA_loc = int(reallyA_value.GetLocation(), 16) 172 173 # Finally continue to doSomething again, and make sure we get the right value for anotherA, 174 # which this time around is just an "A". 175 176 threads = lldbutil.continue_to_breakpoint(process, do_something_bpt) 177 self.assertEquals(len(threads), 1) 178 thread = threads[0] 179 180 frame = thread.GetFrameAtIndex(0) 181 anotherA_value = frame.FindVariable('anotherA', True) 182 self.assertTrue(anotherA_value) 183 anotherA_loc = int(anotherA_value.GetValue(), 16) 184 self.assertEquals(anotherA_loc, reallyA_loc) 185 self.assertEquals(anotherA_value.GetTypeName().find('B'), -1) 186 187 def examine_value_object_of_this_ptr( 188 self, this_static, this_dynamic, dynamic_location): 189 # Get "this" as its static value 190 self.assertTrue(this_static) 191 this_static_loc = int(this_static.GetValue(), 16) 192 193 # Get "this" as its dynamic value 194 195 self.assertTrue(this_dynamic) 196 this_dynamic_typename = this_dynamic.GetTypeName() 197 self.assertNotEqual(this_dynamic_typename.find('B'), -1) 198 this_dynamic_loc = int(this_dynamic.GetValue(), 16) 199 200 # Make sure we got the right address for "this" 201 202 self.assertEquals(this_dynamic_loc, dynamic_location) 203 204 # And that the static address is greater than the dynamic one 205 206 self.assertTrue(this_static_loc > this_dynamic_loc) 207 208 # Now read m_b_value which is only in the dynamic value: 209 210 use_dynamic = lldb.eDynamicCanRunTarget 211 no_dynamic = lldb.eNoDynamicValues 212 213 this_dynamic_m_b_value = this_dynamic.GetChildMemberWithName( 214 'm_b_value', use_dynamic) 215 self.assertTrue(this_dynamic_m_b_value) 216 217 m_b_value = int(this_dynamic_m_b_value.GetValue(), 0) 218 self.assertEquals(m_b_value, 10) 219 220 # Make sure it is not in the static version 221 222 this_static_m_b_value = this_static.GetChildMemberWithName( 223 'm_b_value', no_dynamic) 224 self.assertFalse(this_static_m_b_value) 225 226 # Okay, now let's make sure that we can get the dynamic type of a child 227 # element: 228 229 contained_auto_ptr = this_dynamic.GetChildMemberWithName( 230 'm_client_A', use_dynamic) 231 self.assertTrue(contained_auto_ptr) 232 contained_b = contained_auto_ptr.GetChildMemberWithName( 233 '_M_ptr', use_dynamic) 234 if not contained_b: 235 contained_b = contained_auto_ptr.GetChildMemberWithName( 236 '__ptr_', use_dynamic) 237 self.assertTrue(contained_b) 238 239 contained_b_static = contained_auto_ptr.GetChildMemberWithName( 240 '_M_ptr', no_dynamic) 241 if not contained_b_static: 242 contained_b_static = contained_auto_ptr.GetChildMemberWithName( 243 '__ptr_', no_dynamic) 244 self.assertTrue(contained_b_static) 245 246 contained_b_addr = int(contained_b.GetValue(), 16) 247 contained_b_static_addr = int(contained_b_static.GetValue(), 16) 248 249 self.assertTrue(contained_b_addr < contained_b_static_addr) 250