[Lldb-commits] [lldb] [lldb] Initial plugin and test for SymbolLocatorSymStore (PR #183302)

Stefan Gränitz via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 5 06:40:29 PST 2026


================
@@ -0,0 +1,113 @@
+import glob
+import os
+import shutil
+import tempfile
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+"""
+Test debug symbol acquisition from a local SymStore repository.
+"""
+
+
+class MockedSymStore:
+    """
+    Populate a file structure equivalent to SymStore.exe in a temporary directory.
+    This can work cross-platform and for arbitrary debug info formats. Right now,
+    we support only PDB.
+    """
+
+    def __init__(self, test, exe, pdb):
+        self._test = test
+        self._exe = exe
+        self._pdb = pdb
+        self._tmp = None
+
+    def get_key_pdb(self, exe):
+        """
+        Module UUID: 12345678-1234-5678-9ABC-DEF012345678-00000001
+        To SymStore key: 12345678123456789ABCDEF0123456781
+        """
+        try:
+            spec = lldb.SBModuleSpec()
+            spec.SetFileSpec(lldb.SBFileSpec(self._test.getBuildArtifact(exe)))
+            module = lldb.SBModule(spec)
+            raw = module.GetUUIDString().replace("-", "").upper()
+            if len(raw) != 40:
+                return None
+            guid_hex = raw[:32]
+            age = int(raw[32:], 16)
+            return guid_hex + str(age)
+        except Exception:
+            return None
+
+    def __enter__(self):
+        """
+        Mock local symstore directory tree, move PDB there and report path.
+        """
+        key = None
+        if self._test.getDebugInfo() == "pdb":
+            key = self.get_key_pdb(self._exe)
+        self._test.assertIsNotNone(key)
+        self._tmp = tempfile.mkdtemp()
+        pdb_dir = os.path.join(self._tmp, self._pdb, key)
+        os.makedirs(pdb_dir)
+        shutil.move(
+            self._test.getBuildArtifact(self._pdb),
+            os.path.join(pdb_dir, self._pdb),
+        )
+        return self._tmp.replace("\\", "/")
+
+    def __exit__(self, *exc_info):
+        """
+        Clean up and delete original exe so next make won't skip link command.
+        """
+        shutil.rmtree(self._tmp)
+        self._test.runCmd("settings clear plugin.symbol-locator.symstore")
+        os.remove(self._test.getBuildArtifact(self._exe))
+        return False  # do not suppress exceptions
+
+
+class SymStoreLocalTests(TestBase):
+    TEST_WITH_PDB_DEBUG_INFO = True
+
+    def build_inferior(self):
+        self.build()
+        exe_file = "a.out"
+        if self.getDebugInfo() == "pdb":
+            sym_file = "a.pdb"
+        else:
+            self.skipTest("Non-PDB debug info variants not yet supported")
+        self.assertTrue(os.path.isfile(self.getBuildArtifact(exe_file)))
+        self.assertTrue(os.path.isfile(self.getBuildArtifact(sym_file)))
+        return exe_file, sym_file
+
+    def try_breakpoint(self, exe, should_have_loc):
+        self.runCmd("settings set symbols.enable-external-lookup true")
----------------
weliveindetail wrote:

This doesn't work indeed, because within one session we locate the symbol file only once. This is the case even if we delete the respective target and re-create it, because the `Module` remains cached and the `m_did_load_symfile` prevents re-evaluation in [Module::GetSymbolFile()](https://github.com/llvm/llvm-project/blob/release/22.x/lldb/source/Core/Module.cpp#L1007).

The setting that was active during the first location attempt wins. Thus, the following session is expected behavior (as well as the inverse that switches from `false` to `true`):
```
S:\LLVM\build-msvc>bin\lldb.exe
(lldb) settings set plugin.symbol-locator.symstore.urls S:/brwsrcmp/06/cw08/MySymbolServer
(lldb) settings show symbols.enable-external-lookup
symbols.enable-external-lookup (boolean) = true
(lldb) target create S:\brwsrcmp\06\cw08\hello-symbols.exe
Current executable set to 'S:\brwsrcmp\06\cw08\hello-symbols.exe' (x86_64).
(lldb) b main
Breakpoint 1: where = hello-symbols.exe`main + 4 at hello-symbols.c:4, address = 0x0000000140001404
(lldb) target delete 0
1 targets deleted.
(lldb) settings set symbols.enable-external-lookup false
(lldb) target create S:\brwsrcmp\06\cw08\hello-symbols.exe
Current executable set to 'S:\brwsrcmp\06\cw08\hello-symbols.exe' (x86_64).
(lldb) b main
Breakpoint 1: where = hello-symbols.exe`main + 4 at hello-symbols.c:4, address = 0x0000000140001404
(lldb) exit
```

I agree that this is no intuitive behavior. I don't know how to invalidate the cached module or if it is possible at all, but this is a matter of the foundations of lazy evaluation in LLDB and out of reach for a plugin like `SymbolLocatorSymStore`.

I added a test case that sets `symbols.enable-external-lookup false` initially and checks that the breakpoint won't resolve. Hope it's fine.

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


More information about the lldb-commits mailing list