xref: /llvm-project/lldb/test/API/python_api/value/TestValueAPI.py (revision 53fd724b256e1ccfcb04c90f7740f54e1801986d)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest some SBValue APIs.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprechtimport lldb
6710276a2SWalter Erquinigofrom lldbsuite.test import lldbutil
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
999451b44SJordan Rupprecht
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprechtclass ValueAPITestCase(TestBase):
1299451b44SJordan Rupprecht    def setUp(self):
1399451b44SJordan Rupprecht        # Call super's setUp().
1499451b44SJordan Rupprecht        TestBase.setUp(self)
1599451b44SJordan Rupprecht        # We'll use the test method name as the exe_name.
1699451b44SJordan Rupprecht        self.exe_name = self.testMethodName
1799451b44SJordan Rupprecht        # Find the line number to of function 'c'.
182238dcc3SJonas Devlieghere        self.line = line_number("main.c", "// Break at this line")
1999451b44SJordan Rupprecht
20ab05d913Stcwg    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772")
2199451b44SJordan Rupprecht    def test(self):
2299451b44SJordan Rupprecht        """Exercise some SBValue APIs."""
232238dcc3SJonas Devlieghere        d = {"EXE": self.exe_name}
2499451b44SJordan Rupprecht        self.build(dictionary=d)
2599451b44SJordan Rupprecht        self.setTearDownCleanup(dictionary=d)
2699451b44SJordan Rupprecht        exe = self.getBuildArtifact(self.exe_name)
2799451b44SJordan Rupprecht
2899451b44SJordan Rupprecht        # Create a target by the debugger.
2999451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
3099451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
3199451b44SJordan Rupprecht
3299451b44SJordan Rupprecht        # Create the breakpoint inside function 'main'.
332238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByLocation("main.c", self.line)
3499451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
3599451b44SJordan Rupprecht
3699451b44SJordan Rupprecht        # Now launch the process, and do not stop at entry point.
372238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
3899451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
3999451b44SJordan Rupprecht
4099451b44SJordan Rupprecht        # Get Frame #0.
4147c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped)
422238dcc3SJonas Devlieghere        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
4399451b44SJordan Rupprecht        self.assertTrue(
4499451b44SJordan Rupprecht            thread.IsValid(),
452238dcc3SJonas Devlieghere            "There should be a thread stopped due to breakpoint condition",
462238dcc3SJonas Devlieghere        )
4799451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
4899451b44SJordan Rupprecht
4999451b44SJordan Rupprecht        # Get global variable 'days_of_week'.
502238dcc3SJonas Devlieghere        list = target.FindGlobalVariables("days_of_week", 1)
5199451b44SJordan Rupprecht        days_of_week = list.GetValueAtIndex(0)
5299451b44SJordan Rupprecht        self.assertTrue(days_of_week, VALID_VARIABLE)
5399451b44SJordan Rupprecht        self.assertEqual(days_of_week.GetNumChildren(), 7, VALID_VARIABLE)
5499451b44SJordan Rupprecht        self.DebugSBValue(days_of_week)
5599451b44SJordan Rupprecht
5699451b44SJordan Rupprecht        # Use this to test the "child" and "children" accessors:
5799451b44SJordan Rupprecht        children = days_of_week.children
5899451b44SJordan Rupprecht        self.assertEqual(len(children), 7, VALID_VARIABLE)
5999451b44SJordan Rupprecht        for i in range(0, len(children)):
6099451b44SJordan Rupprecht            day = days_of_week.child[i]
6199451b44SJordan Rupprecht            list_day = children[i]
6299451b44SJordan Rupprecht            self.assertNotEqual(day, None)
6399451b44SJordan Rupprecht            self.assertNotEqual(list_day, None)
6499451b44SJordan Rupprecht            self.assertEqual(day.GetSummary(), list_day.GetSummary(), VALID_VARIABLE)
6599451b44SJordan Rupprecht
6699451b44SJordan Rupprecht        # Spot check the actual value:
6799451b44SJordan Rupprecht        first_day = days_of_week.child[1]
6899451b44SJordan Rupprecht        self.assertEqual(first_day.GetSummary(), '"Monday"', VALID_VARIABLE)
6999451b44SJordan Rupprecht
7099451b44SJordan Rupprecht        # Get global variable 'weekdays'.
712238dcc3SJonas Devlieghere        list = target.FindGlobalVariables("weekdays", 1)
7299451b44SJordan Rupprecht        weekdays = list.GetValueAtIndex(0)
7399451b44SJordan Rupprecht        self.assertTrue(weekdays, VALID_VARIABLE)
74619e2e09SDave Lee        self.assertEqual(weekdays.GetNumChildren(), 5, VALID_VARIABLE)
7599451b44SJordan Rupprecht        self.DebugSBValue(weekdays)
7699451b44SJordan Rupprecht
7799451b44SJordan Rupprecht        # Get global variable 'g_table'.
782238dcc3SJonas Devlieghere        list = target.FindGlobalVariables("g_table", 1)
7999451b44SJordan Rupprecht        g_table = list.GetValueAtIndex(0)
8099451b44SJordan Rupprecht        self.assertTrue(g_table, VALID_VARIABLE)
81619e2e09SDave Lee        self.assertEqual(g_table.GetNumChildren(), 2, VALID_VARIABLE)
8299451b44SJordan Rupprecht        self.DebugSBValue(g_table)
8399451b44SJordan Rupprecht
8499451b44SJordan Rupprecht        fmt = lldbutil.BasicFormatter()
8599451b44SJordan Rupprecht        cvf = lldbutil.ChildVisitingFormatter(indent_child=2)
8699451b44SJordan Rupprecht        rdf = lldbutil.RecursiveDecentFormatter(indent_child=2)
8799451b44SJordan Rupprecht        if self.TraceOn():
8899451b44SJordan Rupprecht            print(fmt.format(days_of_week))
8999451b44SJordan Rupprecht            print(cvf.format(days_of_week))
9099451b44SJordan Rupprecht            print(cvf.format(weekdays))
9199451b44SJordan Rupprecht            print(rdf.format(g_table))
9299451b44SJordan Rupprecht
9399451b44SJordan Rupprecht        # Get variable 'my_int_ptr'.
942238dcc3SJonas Devlieghere        value = frame0.FindVariable("my_int_ptr")
9599451b44SJordan Rupprecht        self.assertTrue(value, VALID_VARIABLE)
9699451b44SJordan Rupprecht        self.DebugSBValue(value)
9799451b44SJordan Rupprecht
9899451b44SJordan Rupprecht        # Get what 'my_int_ptr' points to.
9999451b44SJordan Rupprecht        pointed = value.GetChildAtIndex(0)
10099451b44SJordan Rupprecht        self.assertTrue(pointed, VALID_VARIABLE)
10199451b44SJordan Rupprecht        self.DebugSBValue(pointed)
10299451b44SJordan Rupprecht
10399451b44SJordan Rupprecht        # While we are at it, verify that 'my_int_ptr' points to 'g_my_int'.
1042238dcc3SJonas Devlieghere        symbol = target.ResolveLoadAddress(int(pointed.GetLocation(), 0)).GetSymbol()
10599451b44SJordan Rupprecht        self.assertTrue(symbol)
1062238dcc3SJonas Devlieghere        self.expect(symbol.GetName(), exe=False, startstr="g_my_int")
10799451b44SJordan Rupprecht
10899451b44SJordan Rupprecht        # Get variable 'str_ptr'.
1092238dcc3SJonas Devlieghere        value = frame0.FindVariable("str_ptr")
11099451b44SJordan Rupprecht        self.assertTrue(value, VALID_VARIABLE)
11199451b44SJordan Rupprecht        self.DebugSBValue(value)
11299451b44SJordan Rupprecht
11399451b44SJordan Rupprecht        # SBValue::TypeIsPointerType() should return true.
11499451b44SJordan Rupprecht        self.assertTrue(value.TypeIsPointerType())
11599451b44SJordan Rupprecht
11699451b44SJordan Rupprecht        # Verify the SBValue::GetByteSize() API is working correctly.
11799451b44SJordan Rupprecht        arch = self.getArchitecture()
1182238dcc3SJonas Devlieghere        if arch == "i386":
119619e2e09SDave Lee            self.assertEqual(value.GetByteSize(), 4)
1202238dcc3SJonas Devlieghere        elif arch == "x86_64":
121619e2e09SDave Lee            self.assertEqual(value.GetByteSize(), 8)
12299451b44SJordan Rupprecht
12399451b44SJordan Rupprecht        # Get child at index 5 => 'Friday'.
12499451b44SJordan Rupprecht        child = value.GetChildAtIndex(5, lldb.eNoDynamicValues, True)
12599451b44SJordan Rupprecht        self.assertTrue(child, VALID_VARIABLE)
12699451b44SJordan Rupprecht        self.DebugSBValue(child)
12799451b44SJordan Rupprecht
1282238dcc3SJonas Devlieghere        self.expect(child.GetSummary(), exe=False, substrs=["Friday"])
12999451b44SJordan Rupprecht
13099451b44SJordan Rupprecht        # Now try to get at the same variable using GetValueForExpressionPath().
13199451b44SJordan Rupprecht        # These two SBValue objects should have the same value.
1322238dcc3SJonas Devlieghere        val2 = value.GetValueForExpressionPath("[5]")
13399451b44SJordan Rupprecht        self.assertTrue(val2, VALID_VARIABLE)
13499451b44SJordan Rupprecht        self.DebugSBValue(val2)
1352238dcc3SJonas Devlieghere        self.assertTrue(
1362238dcc3SJonas Devlieghere            child.GetValue() == val2.GetValue()
1372238dcc3SJonas Devlieghere            and child.GetSummary() == val2.GetSummary()
1382238dcc3SJonas Devlieghere        )
13999451b44SJordan Rupprecht
1402238dcc3SJonas Devlieghere        val_i = target.EvaluateExpression("i")
1412238dcc3SJonas Devlieghere        val_s = target.EvaluateExpression("s")
1422238dcc3SJonas Devlieghere        val_a = target.EvaluateExpression("a")
143*53fd724bSDave Lee        self.assertTrue(val_s.member["a"].GetAddress().IsValid(), VALID_VARIABLE)
144*53fd724bSDave Lee        self.assertTrue(val_s.member["a"].AddressOf(), VALID_VARIABLE)
1452238dcc3SJonas Devlieghere        self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE)
14699451b44SJordan Rupprecht
147f05e2fb0SJim Ingham        # Test some other cases of the Cast API.  We allow casts from one struct type
148f05e2fb0SJim Ingham        # to another, which is a little weird, but we don't support casting from a
1493707c540Sjimingham        # smaller type to a larger when the underlying data is not in the inferior,
1503707c540Sjimingham        # since then we have no way to fetch the out-of-bounds values.
1513707c540Sjimingham        # For an expression that references a variable, or a FindVariable result,
1523707c540Sjimingham        # or an SBValue made from an address and a type, we can get back to the target,
1533707c540Sjimingham        # so those will work.  Make sure they do and get the right extra values as well.
1543707c540Sjimingham
1553707c540Sjimingham        # We're casting everything to the type of "f", so get that first:
1563707c540Sjimingham        f_var = frame0.FindVariable("f")
1573707c540Sjimingham        self.assertSuccess(f_var.error, "Got f")
1583707c540Sjimingham        bigger_type = f_var.GetType()
1593707c540Sjimingham
1603707c540Sjimingham        # First try a value that we got from FindVariable
1613707c540Sjimingham        container = frame0.FindVariable("my_container")
1623707c540Sjimingham        self.assertSuccess(container.error, "Found my_container")
1633707c540Sjimingham        fv_small = container.GetValueForExpressionPath(".data.small")
1643707c540Sjimingham        self.assertSuccess(fv_small.error, "Found small in my_container")
1653707c540Sjimingham        fv_cast = fv_small.Cast(bigger_type)
1663707c540Sjimingham        self.assertSuccess(fv_cast.error, "Can cast up from FindVariable")
1673707c540Sjimingham        child_checks = [
1683707c540Sjimingham            ValueCheck(name="a", value="33", type="int"),
1693707c540Sjimingham            ValueCheck(name="b", value="44", type="int"),
1703707c540Sjimingham            ValueCheck(name="c", value="55", type="int"),
1713707c540Sjimingham        ]
1723707c540Sjimingham        cast_check = ValueCheck(type=bigger_type.name, children=child_checks)
1733707c540Sjimingham
1743707c540Sjimingham        # Now try one we made with expr.  This one should fail, because expr
1753707c540Sjimingham        # stores the "canonical value" in host memory, and doesn't know how
1763707c540Sjimingham        # to augment that from the live address.
1773707c540Sjimingham        expr_cont = frame0.EvaluateExpression("my_container")
1783707c540Sjimingham        self.assertSuccess(expr_cont.error, "Got my_container by expr")
1793707c540Sjimingham        expr_small = expr_cont.GetValueForExpressionPath(".data.small")
1803707c540Sjimingham        self.assertSuccess(expr_small.error, "Got small by expr")
1813707c540Sjimingham        expr_cast = expr_small.Cast(bigger_type)
1823707c540Sjimingham        self.assertFailure(expr_cast.error, msg="Cannot cast expr result")
1833707c540Sjimingham
1843707c540Sjimingham        # Now try one we made with CreateValueFromAddress.  That will succeed
1853707c540Sjimingham        # because this directly tracks the inferior memory.
1863707c540Sjimingham        small_addr = fv_small.addr
1873707c540Sjimingham        self.assertTrue(small_addr.IsValid())
1883707c540Sjimingham        small_type = fv_small.GetType()
1893707c540Sjimingham        vfa_small = target.CreateValueFromAddress(
1903707c540Sjimingham            "small_from_addr", small_addr, small_type
191ecbe78c1SJonas Devlieghere        )
1923707c540Sjimingham        self.assertSuccess(vfa_small.error, "Made small from address")
1933707c540Sjimingham        vfa_cast = vfa_small.Cast(bigger_type)
1943707c540Sjimingham        self.assertSuccess(vfa_cast.error, "Made a cast from vfa_small")
1953707c540Sjimingham        cast_check.check_value(self, vfa_cast, "Cast of ValueFromAddress succeeds")
1963707c540Sjimingham
1973707c540Sjimingham        # Next try ValueObject created from data.  They should fail as there's no
1983707c540Sjimingham        # way to grow the data:
1993707c540Sjimingham        data_small = target.CreateValueFromData(
2003707c540Sjimingham            "small_from_data", fv_small.data, fv_small.type
2013707c540Sjimingham        )
2023707c540Sjimingham        self.assertSuccess(data_small.error, "Made a valid object from data")
2033707c540Sjimingham        data_cast = data_small.Cast(bigger_type)
2043707c540Sjimingham        self.assertFailure(data_cast.error, msg="Cannot cast data backed SBValue")
2053707c540Sjimingham
2063707c540Sjimingham        # Now check casting from a larger type to a smaller, we can always do this,
2073707c540Sjimingham        # so just test one case:
2083707c540Sjimingham        weird_cast = f_var.Cast(val_s.GetType())
209ecbe78c1SJonas Devlieghere        self.assertSuccess(weird_cast.GetError(), "Can cast from a larger to a smaller")
210ecbe78c1SJonas Devlieghere        self.assertEqual(
211*53fd724bSDave Lee            weird_cast.member["a"].GetValueAsSigned(0),
212ecbe78c1SJonas Devlieghere            33,
213ecbe78c1SJonas Devlieghere            "Got the right value",
214ecbe78c1SJonas Devlieghere        )
215f05e2fb0SJim Ingham
21699451b44SJordan Rupprecht        # Check that lldb.value implements truth testing.
2172238dcc3SJonas Devlieghere        self.assertFalse(lldb.value(frame0.FindVariable("bogus")))
2182238dcc3SJonas Devlieghere        self.assertTrue(lldb.value(frame0.FindVariable("uinthex")))
21999451b44SJordan Rupprecht
2202238dcc3SJonas Devlieghere        self.assertEqual(
2212238dcc3SJonas Devlieghere            int(lldb.value(frame0.FindVariable("uinthex"))),
2222238dcc3SJonas Devlieghere            3768803088,
2232238dcc3SJonas Devlieghere            "uinthex == 3768803088",
2242238dcc3SJonas Devlieghere        )
2252238dcc3SJonas Devlieghere        self.assertEqual(
2262238dcc3SJonas Devlieghere            int(lldb.value(frame0.FindVariable("sinthex"))),
2272238dcc3SJonas Devlieghere            -526164208,
2282238dcc3SJonas Devlieghere            "sinthex == -526164208",
2292238dcc3SJonas Devlieghere        )
23099451b44SJordan Rupprecht
23199451b44SJordan Rupprecht        # Check value_iter works correctly.
23299451b44SJordan Rupprecht        for v in [
2332238dcc3SJonas Devlieghere            lldb.value(frame0.FindVariable("uinthex")),
2342238dcc3SJonas Devlieghere            lldb.value(frame0.FindVariable("sinthex")),
23599451b44SJordan Rupprecht        ]:
23699451b44SJordan Rupprecht            self.assertTrue(v)
23799451b44SJordan Rupprecht
2380ed758b2SDave Lee        self.assertEqual(
2392238dcc3SJonas Devlieghere            frame0.FindVariable("uinthex").GetValueAsUnsigned(),
2402238dcc3SJonas Devlieghere            3768803088,
2412238dcc3SJonas Devlieghere            "unsigned uinthex == 3768803088",
2422238dcc3SJonas Devlieghere        )
2430ed758b2SDave Lee        self.assertEqual(
2442238dcc3SJonas Devlieghere            frame0.FindVariable("sinthex").GetValueAsUnsigned(),
2452238dcc3SJonas Devlieghere            3768803088,
2462238dcc3SJonas Devlieghere            "unsigned sinthex == 3768803088",
2472238dcc3SJonas Devlieghere        )
24899451b44SJordan Rupprecht
2491fb5c7a2SDave Lee        self.assertEqual(
2502238dcc3SJonas Devlieghere            frame0.FindVariable("uinthex").GetValueAsSigned(),
2512238dcc3SJonas Devlieghere            -526164208,
2522238dcc3SJonas Devlieghere            "signed uinthex == -526164208",
2532238dcc3SJonas Devlieghere        )
2541fb5c7a2SDave Lee        self.assertEqual(
2552238dcc3SJonas Devlieghere            frame0.FindVariable("sinthex").GetValueAsSigned(),
2562238dcc3SJonas Devlieghere            -526164208,
2572238dcc3SJonas Devlieghere            "signed sinthex == -526164208",
2582238dcc3SJonas Devlieghere        )
259710276a2SWalter Erquinigo
260710276a2SWalter Erquinigo        # Check that hex value printing works as expected.
261710276a2SWalter Erquinigo        self.assertEqual(
262710276a2SWalter Erquinigo            frame0.FindVariable("fixed_int_ptr").GetValue(),
26395686016SDavid Spickett            "0x000000aa" if target.addr_size == 4 else "0x00000000000000aa",
264710276a2SWalter Erquinigo        )
265096c530aSJonas Devlieghere        self.runCmd(
266096c530aSJonas Devlieghere            "settings set target.show-hex-variable-values-with-leading-zeroes false"
267096c530aSJonas Devlieghere        )
268710276a2SWalter Erquinigo        self.assertEqual(
269710276a2SWalter Erquinigo            frame0.FindVariable("another_fixed_int_ptr").GetValue(),
270710276a2SWalter Erquinigo            "0xaa",
271710276a2SWalter Erquinigo        )
272710276a2SWalter Erquinigo        self.assertEqual(
273710276a2SWalter Erquinigo            frame0.FindVariable("a_null_int_ptr").GetValue(),
274710276a2SWalter Erquinigo            "0x0",
275710276a2SWalter Erquinigo        )
276