xref: /llvm-project/lldb/test/API/lang/cpp/dynamic-value/TestDynamicValue.py (revision dd5d73007240712957f2b633f795d9965afaadd6)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtUse lldb Python API to test dynamic values in C++
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprechtimport lldb
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
999451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprechtclass DynamicValueTestCase(TestBase):
1399451b44SJordan Rupprecht    def setUp(self):
1499451b44SJordan Rupprecht        # Call super's setUp().
1599451b44SJordan Rupprecht        TestBase.setUp(self)
1699451b44SJordan Rupprecht
1799451b44SJordan Rupprecht        # Find the line number to break for main.c.
1899451b44SJordan Rupprecht
1999451b44SJordan Rupprecht        self.do_something_line = line_number(
202238dcc3SJonas Devlieghere            "pass-to-base.cpp", "// Break here in doSomething."
212238dcc3SJonas Devlieghere        )
2299451b44SJordan Rupprecht        self.main_first_call_line = line_number(
232238dcc3SJonas Devlieghere            "pass-to-base.cpp",
242238dcc3SJonas Devlieghere            "// Break here and get real addresses of myB and otherB.",
252238dcc3SJonas Devlieghere        )
2699451b44SJordan Rupprecht        self.main_second_call_line = line_number(
272238dcc3SJonas Devlieghere            "pass-to-base.cpp", "// Break here and get real address of reallyA."
282238dcc3SJonas Devlieghere        )
2999451b44SJordan Rupprecht
302238dcc3SJonas Devlieghere    @add_test_categories(["pyapi"])
3199451b44SJordan Rupprecht    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663")
3299451b44SJordan Rupprecht    def test_get_dynamic_vals(self):
3399451b44SJordan Rupprecht        """Test fetching C++ dynamic values from pointers & references."""
34d7dbe2c4SPavel Labath        self.build()
3599451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
3699451b44SJordan Rupprecht
3799451b44SJordan Rupprecht        # Create a target from the debugger.
3899451b44SJordan Rupprecht
3999451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
4099451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
4199451b44SJordan Rupprecht
4299451b44SJordan Rupprecht        # Set up our breakpoints:
4399451b44SJordan Rupprecht
4499451b44SJordan Rupprecht        do_something_bpt = target.BreakpointCreateByLocation(
452238dcc3SJonas Devlieghere            "pass-to-base.cpp", self.do_something_line
462238dcc3SJonas Devlieghere        )
472238dcc3SJonas Devlieghere        self.assertTrue(do_something_bpt, VALID_BREAKPOINT)
4899451b44SJordan Rupprecht
4999451b44SJordan Rupprecht        first_call_bpt = target.BreakpointCreateByLocation(
502238dcc3SJonas Devlieghere            "pass-to-base.cpp", self.main_first_call_line
512238dcc3SJonas Devlieghere        )
522238dcc3SJonas Devlieghere        self.assertTrue(first_call_bpt, VALID_BREAKPOINT)
5399451b44SJordan Rupprecht
5499451b44SJordan Rupprecht        second_call_bpt = target.BreakpointCreateByLocation(
552238dcc3SJonas Devlieghere            "pass-to-base.cpp", self.main_second_call_line
562238dcc3SJonas Devlieghere        )
572238dcc3SJonas Devlieghere        self.assertTrue(second_call_bpt, VALID_BREAKPOINT)
5899451b44SJordan Rupprecht
5999451b44SJordan Rupprecht        # Now launch the process, and do not stop at the entry point.
602238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
6199451b44SJordan Rupprecht
622238dcc3SJonas Devlieghere        self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
6399451b44SJordan Rupprecht
642238dcc3SJonas Devlieghere        threads = lldbutil.get_threads_stopped_at_breakpoint(process, first_call_bpt)
6580fcecb1SJonas Devlieghere        self.assertEqual(len(threads), 1)
6699451b44SJordan Rupprecht        thread = threads[0]
6799451b44SJordan Rupprecht
6899451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
6999451b44SJordan Rupprecht
7099451b44SJordan Rupprecht        # Now find the dynamic addresses of myB and otherB so we can compare them
7199451b44SJordan Rupprecht        # with the dynamic values we get in doSomething:
7299451b44SJordan Rupprecht
7399451b44SJordan Rupprecht        use_dynamic = lldb.eDynamicCanRunTarget
7499451b44SJordan Rupprecht        no_dynamic = lldb.eNoDynamicValues
7599451b44SJordan Rupprecht
762238dcc3SJonas Devlieghere        myB = frame.FindVariable("myB", no_dynamic)
7799451b44SJordan Rupprecht        self.assertTrue(myB)
7899451b44SJordan Rupprecht        myB_loc = int(myB.GetLocation(), 16)
7999451b44SJordan Rupprecht
802238dcc3SJonas Devlieghere        otherB = frame.FindVariable("otherB", no_dynamic)
8199451b44SJordan Rupprecht        self.assertTrue(otherB)
8299451b44SJordan Rupprecht        otherB_loc = int(otherB.GetLocation(), 16)
8399451b44SJordan Rupprecht
8499451b44SJordan Rupprecht        # Okay now run to doSomething:
8599451b44SJordan Rupprecht
8699451b44SJordan Rupprecht        threads = lldbutil.continue_to_breakpoint(process, do_something_bpt)
8780fcecb1SJonas Devlieghere        self.assertEqual(len(threads), 1)
8899451b44SJordan Rupprecht        thread = threads[0]
8999451b44SJordan Rupprecht
9099451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
9199451b44SJordan Rupprecht
9299451b44SJordan Rupprecht        # Get "this" using FindVariable:
9399451b44SJordan Rupprecht
942238dcc3SJonas Devlieghere        this_static = frame.FindVariable("this", no_dynamic)
952238dcc3SJonas Devlieghere        this_dynamic = frame.FindVariable("this", use_dynamic)
962238dcc3SJonas Devlieghere        self.examine_value_object_of_this_ptr(this_static, this_dynamic, myB_loc)
9799451b44SJordan Rupprecht
9899451b44SJordan Rupprecht        # Now make sure that the "GetDynamicValue" works:
9999451b44SJordan Rupprecht        # This doesn't work currently because we can't get dynamic values from
10099451b44SJordan Rupprecht        # ConstResult objects.
10199451b44SJordan Rupprecht        fetched_dynamic_value = this_static.GetDynamicValue(use_dynamic)
10299451b44SJordan Rupprecht        self.examine_value_object_of_this_ptr(
1032238dcc3SJonas Devlieghere            this_static, fetched_dynamic_value, myB_loc
1042238dcc3SJonas Devlieghere        )
10599451b44SJordan Rupprecht
10699451b44SJordan Rupprecht        # And conversely that the GetDynamicValue() interface also works:
10799451b44SJordan Rupprecht        fetched_static_value = this_dynamic.GetStaticValue()
10899451b44SJordan Rupprecht        self.examine_value_object_of_this_ptr(
1092238dcc3SJonas Devlieghere            fetched_static_value, this_dynamic, myB_loc
1102238dcc3SJonas Devlieghere        )
11199451b44SJordan Rupprecht
11299451b44SJordan Rupprecht        # Get "this" using FindValue, make sure that works too:
11399451b44SJordan Rupprecht        this_static = frame.FindValue(
1142238dcc3SJonas Devlieghere            "this", lldb.eValueTypeVariableArgument, no_dynamic
1152238dcc3SJonas Devlieghere        )
11699451b44SJordan Rupprecht        this_dynamic = frame.FindValue(
1172238dcc3SJonas Devlieghere            "this", lldb.eValueTypeVariableArgument, use_dynamic
1182238dcc3SJonas Devlieghere        )
1192238dcc3SJonas Devlieghere        self.examine_value_object_of_this_ptr(this_static, this_dynamic, myB_loc)
12099451b44SJordan Rupprecht
12199451b44SJordan Rupprecht        # Get "this" using the EvaluateExpression:
1222238dcc3SJonas Devlieghere        this_static = frame.EvaluateExpression("this", False)
1232238dcc3SJonas Devlieghere        this_dynamic = frame.EvaluateExpression("this", True)
1242238dcc3SJonas Devlieghere        self.examine_value_object_of_this_ptr(this_static, this_dynamic, myB_loc)
12599451b44SJordan Rupprecht
12699451b44SJordan Rupprecht        # The "frame var" code uses another path to get into children, so let's
12799451b44SJordan Rupprecht        # make sure that works as well:
12899451b44SJordan Rupprecht
12999451b44SJordan Rupprecht        self.expect(
1302238dcc3SJonas Devlieghere            "frame var -d run-target --ptr-depth=2 --show-types anotherA.m_client_A",
1312238dcc3SJonas Devlieghere            "frame var finds its way into a child member",
1322238dcc3SJonas Devlieghere            patterns=["\(B \*\)"],
1332238dcc3SJonas Devlieghere        )
13499451b44SJordan Rupprecht
13599451b44SJordan Rupprecht        # Now make sure we also get it right for a reference as well:
13699451b44SJordan Rupprecht
1372238dcc3SJonas Devlieghere        anotherA_static = frame.FindVariable("anotherA", False)
13899451b44SJordan Rupprecht        self.assertTrue(anotherA_static)
13999451b44SJordan Rupprecht        anotherA_static_addr = int(anotherA_static.GetValue(), 16)
14099451b44SJordan Rupprecht
1412238dcc3SJonas Devlieghere        anotherA_dynamic = frame.FindVariable("anotherA", True)
14299451b44SJordan Rupprecht        self.assertTrue(anotherA_dynamic)
14399451b44SJordan Rupprecht        anotherA_dynamic_addr = int(anotherA_dynamic.GetValue(), 16)
14499451b44SJordan Rupprecht        anotherA_dynamic_typename = anotherA_dynamic.GetTypeName()
1452238dcc3SJonas Devlieghere        self.assertNotEqual(anotherA_dynamic_typename.find("B"), -1)
14699451b44SJordan Rupprecht
1479c246882SJordan Rupprecht        self.assertLess(anotherA_dynamic_addr, anotherA_static_addr)
14899451b44SJordan Rupprecht
14999451b44SJordan Rupprecht        anotherA_m_b_value_dynamic = anotherA_dynamic.GetChildMemberWithName(
1502238dcc3SJonas Devlieghere            "m_b_value", True
1512238dcc3SJonas Devlieghere        )
15299451b44SJordan Rupprecht        self.assertTrue(anotherA_m_b_value_dynamic)
15399451b44SJordan Rupprecht        anotherA_m_b_val = int(anotherA_m_b_value_dynamic.GetValue(), 10)
15480fcecb1SJonas Devlieghere        self.assertEqual(anotherA_m_b_val, 300)
15599451b44SJordan Rupprecht
15699451b44SJordan Rupprecht        anotherA_m_b_value_static = anotherA_static.GetChildMemberWithName(
1572238dcc3SJonas Devlieghere            "m_b_value", True
1582238dcc3SJonas Devlieghere        )
15999451b44SJordan Rupprecht        self.assertFalse(anotherA_m_b_value_static)
16099451b44SJordan Rupprecht
16199451b44SJordan Rupprecht        # Okay, now continue again, and when we hit the second breakpoint in
16299451b44SJordan Rupprecht        # main
16399451b44SJordan Rupprecht
16499451b44SJordan Rupprecht        threads = lldbutil.continue_to_breakpoint(process, second_call_bpt)
16580fcecb1SJonas Devlieghere        self.assertEqual(len(threads), 1)
16699451b44SJordan Rupprecht        thread = threads[0]
16799451b44SJordan Rupprecht
16899451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
1692238dcc3SJonas Devlieghere        reallyA_value = frame.FindVariable("reallyA", False)
17099451b44SJordan Rupprecht        self.assertTrue(reallyA_value)
17199451b44SJordan Rupprecht        reallyA_loc = int(reallyA_value.GetLocation(), 16)
17299451b44SJordan Rupprecht
173*dd5d7300SPavel Labath        # Continue to doSomething again, and make sure we get the right value for anotherA,
17499451b44SJordan Rupprecht        # which this time around is just an "A".
17599451b44SJordan Rupprecht
17699451b44SJordan Rupprecht        threads = lldbutil.continue_to_breakpoint(process, do_something_bpt)
17780fcecb1SJonas Devlieghere        self.assertEqual(len(threads), 1)
17899451b44SJordan Rupprecht        thread = threads[0]
17999451b44SJordan Rupprecht
18099451b44SJordan Rupprecht        frame = thread.GetFrameAtIndex(0)
1812238dcc3SJonas Devlieghere        anotherA_value = frame.FindVariable("anotherA", True)
18299451b44SJordan Rupprecht        self.assertTrue(anotherA_value)
18399451b44SJordan Rupprecht        anotherA_loc = int(anotherA_value.GetValue(), 16)
18480fcecb1SJonas Devlieghere        self.assertEqual(anotherA_loc, reallyA_loc)
18580fcecb1SJonas Devlieghere        self.assertEqual(anotherA_value.GetTypeName().find("B"), -1)
18699451b44SJordan Rupprecht
187*dd5d7300SPavel Labath        # Finally do the same with a B in an anonymous namespace.
188*dd5d7300SPavel Labath        threads = lldbutil.continue_to_breakpoint(process, do_something_bpt)
189*dd5d7300SPavel Labath        self.assertEqual(len(threads), 1)
190*dd5d7300SPavel Labath        thread = threads[0]
191*dd5d7300SPavel Labath
192*dd5d7300SPavel Labath        frame = thread.GetFrameAtIndex(0)
193*dd5d7300SPavel Labath        anotherA_value = frame.FindVariable("anotherA", use_dynamic)
194*dd5d7300SPavel Labath        self.assertTrue(anotherA_value)
195*dd5d7300SPavel Labath        self.assertIn("B", anotherA_value.GetTypeName())
196*dd5d7300SPavel Labath        anon_b_value = anotherA_value.GetChildMemberWithName("m_anon_b_value")
197*dd5d7300SPavel Labath        self.assertTrue(anon_b_value)
198*dd5d7300SPavel Labath        self.assertEqual(anon_b_value.GetValueAsSigned(), 47)
199*dd5d7300SPavel Labath
20099451b44SJordan Rupprecht    def examine_value_object_of_this_ptr(
2012238dcc3SJonas Devlieghere        self, this_static, this_dynamic, dynamic_location
2022238dcc3SJonas Devlieghere    ):
20399451b44SJordan Rupprecht        # Get "this" as its static value
20499451b44SJordan Rupprecht        self.assertTrue(this_static)
20599451b44SJordan Rupprecht        this_static_loc = int(this_static.GetValue(), 16)
20699451b44SJordan Rupprecht
20799451b44SJordan Rupprecht        # Get "this" as its dynamic value
20899451b44SJordan Rupprecht
20999451b44SJordan Rupprecht        self.assertTrue(this_dynamic)
21099451b44SJordan Rupprecht        this_dynamic_typename = this_dynamic.GetTypeName()
2112238dcc3SJonas Devlieghere        self.assertNotEqual(this_dynamic_typename.find("B"), -1)
21299451b44SJordan Rupprecht        this_dynamic_loc = int(this_dynamic.GetValue(), 16)
21399451b44SJordan Rupprecht
21499451b44SJordan Rupprecht        # Make sure we got the right address for "this"
21599451b44SJordan Rupprecht
21680fcecb1SJonas Devlieghere        self.assertEqual(this_dynamic_loc, dynamic_location)
21799451b44SJordan Rupprecht
21899451b44SJordan Rupprecht        # And that the static address is greater than the dynamic one
21999451b44SJordan Rupprecht
2209c246882SJordan Rupprecht        self.assertGreater(this_static_loc, this_dynamic_loc)
22199451b44SJordan Rupprecht
22299451b44SJordan Rupprecht        # Now read m_b_value which is only in the dynamic value:
22399451b44SJordan Rupprecht
22499451b44SJordan Rupprecht        use_dynamic = lldb.eDynamicCanRunTarget
22599451b44SJordan Rupprecht        no_dynamic = lldb.eNoDynamicValues
22699451b44SJordan Rupprecht
22799451b44SJordan Rupprecht        this_dynamic_m_b_value = this_dynamic.GetChildMemberWithName(
2282238dcc3SJonas Devlieghere            "m_b_value", use_dynamic
2292238dcc3SJonas Devlieghere        )
23099451b44SJordan Rupprecht        self.assertTrue(this_dynamic_m_b_value)
23199451b44SJordan Rupprecht
23299451b44SJordan Rupprecht        m_b_value = int(this_dynamic_m_b_value.GetValue(), 0)
23380fcecb1SJonas Devlieghere        self.assertEqual(m_b_value, 10)
23499451b44SJordan Rupprecht
23599451b44SJordan Rupprecht        # Make sure it is not in the static version
23699451b44SJordan Rupprecht
23799451b44SJordan Rupprecht        this_static_m_b_value = this_static.GetChildMemberWithName(
2382238dcc3SJonas Devlieghere            "m_b_value", no_dynamic
2392238dcc3SJonas Devlieghere        )
24099451b44SJordan Rupprecht        self.assertFalse(this_static_m_b_value)
24199451b44SJordan Rupprecht
24299451b44SJordan Rupprecht        # Okay, now let's make sure that we can get the dynamic type of a child
24399451b44SJordan Rupprecht        # element:
24499451b44SJordan Rupprecht
24599451b44SJordan Rupprecht        contained_auto_ptr = this_dynamic.GetChildMemberWithName(
2462238dcc3SJonas Devlieghere            "m_client_A", use_dynamic
2472238dcc3SJonas Devlieghere        )
24899451b44SJordan Rupprecht        self.assertTrue(contained_auto_ptr)
2492238dcc3SJonas Devlieghere        contained_b = contained_auto_ptr.GetChildMemberWithName("_M_ptr", use_dynamic)
25099451b44SJordan Rupprecht        if not contained_b:
25199451b44SJordan Rupprecht            contained_b = contained_auto_ptr.GetChildMemberWithName(
2522238dcc3SJonas Devlieghere                "__ptr_", use_dynamic
2532238dcc3SJonas Devlieghere            )
25499451b44SJordan Rupprecht        self.assertTrue(contained_b)
25599451b44SJordan Rupprecht
25699451b44SJordan Rupprecht        contained_b_static = contained_auto_ptr.GetChildMemberWithName(
2572238dcc3SJonas Devlieghere            "_M_ptr", no_dynamic
2582238dcc3SJonas Devlieghere        )
25999451b44SJordan Rupprecht        if not contained_b_static:
26099451b44SJordan Rupprecht            contained_b_static = contained_auto_ptr.GetChildMemberWithName(
2612238dcc3SJonas Devlieghere                "__ptr_", no_dynamic
2622238dcc3SJonas Devlieghere            )
26399451b44SJordan Rupprecht        self.assertTrue(contained_b_static)
26499451b44SJordan Rupprecht
26599451b44SJordan Rupprecht        contained_b_addr = int(contained_b.GetValue(), 16)
26699451b44SJordan Rupprecht        contained_b_static_addr = int(contained_b_static.GetValue(), 16)
26799451b44SJordan Rupprecht
2689c246882SJordan Rupprecht        self.assertLess(contained_b_addr, contained_b_static_addr)
269