2 Use lldb Python API to test dynamic values in C++
7 from lldbsuite
.test
.decorators
import *
8 from lldbsuite
.test
.lldbtest
import *
9 from lldbsuite
.test
import lldbutil
12 class DynamicValueTestCase(TestBase
):
14 # Call super's setUp().
17 # Find the line number to break for main.c.
19 self
.do_something_line
= line_number(
20 "pass-to-base.cpp", "// Break here in doSomething."
22 self
.main_first_call_line
= line_number(
24 "// 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."
30 @add_test_categories(["pyapi"])
31 @expectedFailureAll(oslist
=["windows"], bugnumber
="llvm.org/pr24663")
32 def test_get_dynamic_vals(self
):
33 """Test fetching C++ dynamic values from pointers & references."""
35 exe
= self
.getBuildArtifact("a.out")
37 # Create a target from the debugger.
39 target
= self
.dbg
.CreateTarget(exe
)
40 self
.assertTrue(target
, VALID_TARGET
)
42 # Set up our breakpoints:
44 do_something_bpt
= target
.BreakpointCreateByLocation(
45 "pass-to-base.cpp", self
.do_something_line
47 self
.assertTrue(do_something_bpt
, VALID_BREAKPOINT
)
49 first_call_bpt
= target
.BreakpointCreateByLocation(
50 "pass-to-base.cpp", self
.main_first_call_line
52 self
.assertTrue(first_call_bpt
, VALID_BREAKPOINT
)
54 second_call_bpt
= target
.BreakpointCreateByLocation(
55 "pass-to-base.cpp", self
.main_second_call_line
57 self
.assertTrue(second_call_bpt
, VALID_BREAKPOINT
)
59 # Now launch the process, and do not stop at the entry point.
60 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
62 self
.assertState(process
.GetState(), lldb
.eStateStopped
, PROCESS_STOPPED
)
64 threads
= lldbutil
.get_threads_stopped_at_breakpoint(process
, first_call_bpt
)
65 self
.assertEquals(len(threads
), 1)
68 frame
= thread
.GetFrameAtIndex(0)
70 # Now find the dynamic addresses of myB and otherB so we can compare them
71 # with the dynamic values we get in doSomething:
73 use_dynamic
= lldb
.eDynamicCanRunTarget
74 no_dynamic
= lldb
.eNoDynamicValues
76 myB
= frame
.FindVariable("myB", no_dynamic
)
78 myB_loc
= int(myB
.GetLocation(), 16)
80 otherB
= frame
.FindVariable("otherB", no_dynamic
)
81 self
.assertTrue(otherB
)
82 otherB_loc
= int(otherB
.GetLocation(), 16)
84 # Okay now run to doSomething:
86 threads
= lldbutil
.continue_to_breakpoint(process
, do_something_bpt
)
87 self
.assertEquals(len(threads
), 1)
90 frame
= thread
.GetFrameAtIndex(0)
92 # Get "this" using FindVariable:
94 this_static
= frame
.FindVariable("this", no_dynamic
)
95 this_dynamic
= frame
.FindVariable("this", use_dynamic
)
96 self
.examine_value_object_of_this_ptr(this_static
, this_dynamic
, myB_loc
)
98 # Now make sure that the "GetDynamicValue" works:
99 # This doesn't work currently because we can't get dynamic values from
100 # ConstResult objects.
101 fetched_dynamic_value
= this_static
.GetDynamicValue(use_dynamic
)
102 self
.examine_value_object_of_this_ptr(
103 this_static
, fetched_dynamic_value
, myB_loc
106 # And conversely that the GetDynamicValue() interface also works:
107 fetched_static_value
= this_dynamic
.GetStaticValue()
108 self
.examine_value_object_of_this_ptr(
109 fetched_static_value
, this_dynamic
, myB_loc
112 # Get "this" using FindValue, make sure that works too:
113 this_static
= frame
.FindValue(
114 "this", lldb
.eValueTypeVariableArgument
, no_dynamic
116 this_dynamic
= frame
.FindValue(
117 "this", lldb
.eValueTypeVariableArgument
, use_dynamic
119 self
.examine_value_object_of_this_ptr(this_static
, this_dynamic
, myB_loc
)
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(this_static
, this_dynamic
, myB_loc
)
126 # The "frame var" code uses another path to get into children, so let's
127 # make sure that works as well:
130 "frame var -d run-target --ptr-depth=2 --show-types anotherA.m_client_A",
131 "frame var finds its way into a child member",
132 patterns
=["\(B \*\)"],
135 # Now make sure we also get it right for a reference as well:
137 anotherA_static
= frame
.FindVariable("anotherA", False)
138 self
.assertTrue(anotherA_static
)
139 anotherA_static_addr
= int(anotherA_static
.GetValue(), 16)
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)
147 self
.assertTrue(anotherA_dynamic_addr
< anotherA_static_addr
)
149 anotherA_m_b_value_dynamic
= anotherA_dynamic
.GetChildMemberWithName(
152 self
.assertTrue(anotherA_m_b_value_dynamic
)
153 anotherA_m_b_val
= int(anotherA_m_b_value_dynamic
.GetValue(), 10)
154 self
.assertEquals(anotherA_m_b_val
, 300)
156 anotherA_m_b_value_static
= anotherA_static
.GetChildMemberWithName(
159 self
.assertFalse(anotherA_m_b_value_static
)
161 # Okay, now continue again, and when we hit the second breakpoint in
164 threads
= lldbutil
.continue_to_breakpoint(process
, second_call_bpt
)
165 self
.assertEquals(len(threads
), 1)
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)
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".
176 threads
= lldbutil
.continue_to_breakpoint(process
, do_something_bpt
)
177 self
.assertEquals(len(threads
), 1)
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)
187 def examine_value_object_of_this_ptr(
188 self
, this_static
, this_dynamic
, dynamic_location
190 # Get "this" as its static value
191 self
.assertTrue(this_static
)
192 this_static_loc
= int(this_static
.GetValue(), 16)
194 # Get "this" as its dynamic value
196 self
.assertTrue(this_dynamic
)
197 this_dynamic_typename
= this_dynamic
.GetTypeName()
198 self
.assertNotEqual(this_dynamic_typename
.find("B"), -1)
199 this_dynamic_loc
= int(this_dynamic
.GetValue(), 16)
201 # Make sure we got the right address for "this"
203 self
.assertEquals(this_dynamic_loc
, dynamic_location
)
205 # And that the static address is greater than the dynamic one
207 self
.assertTrue(this_static_loc
> this_dynamic_loc
)
209 # Now read m_b_value which is only in the dynamic value:
211 use_dynamic
= lldb
.eDynamicCanRunTarget
212 no_dynamic
= lldb
.eNoDynamicValues
214 this_dynamic_m_b_value
= this_dynamic
.GetChildMemberWithName(
215 "m_b_value", use_dynamic
217 self
.assertTrue(this_dynamic_m_b_value
)
219 m_b_value
= int(this_dynamic_m_b_value
.GetValue(), 0)
220 self
.assertEquals(m_b_value
, 10)
222 # Make sure it is not in the static version
224 this_static_m_b_value
= this_static
.GetChildMemberWithName(
225 "m_b_value", no_dynamic
227 self
.assertFalse(this_static_m_b_value
)
229 # Okay, now let's make sure that we can get the dynamic type of a child
232 contained_auto_ptr
= this_dynamic
.GetChildMemberWithName(
233 "m_client_A", use_dynamic
235 self
.assertTrue(contained_auto_ptr
)
236 contained_b
= contained_auto_ptr
.GetChildMemberWithName("_M_ptr", use_dynamic
)
238 contained_b
= contained_auto_ptr
.GetChildMemberWithName(
239 "__ptr_", use_dynamic
241 self
.assertTrue(contained_b
)
243 contained_b_static
= contained_auto_ptr
.GetChildMemberWithName(
246 if not contained_b_static
:
247 contained_b_static
= contained_auto_ptr
.GetChildMemberWithName(
250 self
.assertTrue(contained_b_static
)
252 contained_b_addr
= int(contained_b
.GetValue(), 16)
253 contained_b_static_addr
= int(contained_b_static
.GetValue(), 16)
255 self
.assertTrue(contained_b_addr
< contained_b_static_addr
)