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