[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 13 04:02:07 PDT 2025


================
@@ -0,0 +1,64 @@
+"""
+Make sure 'frame var' using DIL parser/evaultor works for local variables.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+import os
+import shutil
+import time
+
+
+class TestFrameVarDILLocalVars(TestBase):
+    # If your test case doesn't stress debug info, then
+    # set this to true.  That way it won't be run once for
+    # each debug info format.
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_frame_var(self):
+        self.build()
+        self.do_test()
+
+    def do_test(self):
+        target = self.createTestTarget()
+
+        # Now create a breakpoint in main.c at the source matching
+        # "Set a breakpoint here"
+        breakpoint = target.BreakpointCreateBySourceRegex(
+            "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
+        self.assertTrue(
+            breakpoint and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT
+        )
+
+        error = lldb.SBError()
+        # This is the launch info.  If you want to launch with arguments or
+        # environment variables, add them using SetArguments or
+        # SetEnvironmentEntries
+
+        launch_info = target.GetLaunchInfo()
+        process = target.Launch(launch_info, error)
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # Did we hit our breakpoint?
+        from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint
+
+        threads = get_threads_stopped_at_breakpoint(process, breakpoint)
+        self.assertEqual(
+            len(threads), 1, "There should be a thread stopped at our breakpoint"
+        )
+        # The hit count for the breakpoint should be 1.
+        self.assertEqual(breakpoint.GetHitCount(), 1)
+
+        frame = threads[0].GetFrameAtIndex(0)
+        command_result = lldb.SBCommandReturnObject()
+        interp = self.dbg.GetCommandInterpreter()
+
+        self.expect("settings set target.experimental.use-DIL true", substrs=[""])
+        self.expect("frame variable a", substrs=["1"])
+        self.expect("frame variable b", substrs=["2"])
+        self.expect("frame variable c", substrs=["\\xfd"])
+        self.expect("frame variable s", substrs=["4"])
----------------
labath wrote:

Looking at the error message,  I think `"'\xfd'"` should work for the \xfd case.

Using `expect` for the failure tests is fine. My main problem is with the success tests, because substring (and regex) matches can easily match the wrong thing (for example `substrs=["2"]` would match `4294967295` (aka `0xffffffff`) because it really does "2" as a substring).

As for pointers, it depends on what exactly you want to assert. You can match regular expressions if you explicitly request that. However, `expect_var_path("globalPtr", result_value=re.compile("0x[0-9]+"))` is not a particularly strong assertion, as it will basically match any (hex) integer, so it might be actually better to match the result type instead (`expect_var_path("globalPtr", result_type="int *")`) and trust that general value printing logic (which you're not modifying) works fine. Or you may actually want to check that the result points to the right place, in which case it may be better to avoid expect_var_path entirely and do something like
```
assertEqual(frame.GetValueForVariablePath("globalPtr").GetValueAsUnsigned(),
  frame.FindVariable("globalVar").GetLoadAddress())
```

(Btw, `expect_var_path` actually returns the SBValue it used for matching, so you can even combine these approaches -- e.g., use expect_var_path to find a value and match its type, and then save the result and to some additional checks on it on your own)

https://github.com/llvm/llvm-project/pull/120971


More information about the lldb-commits mailing list