Author: Stefan Gränitz
Date: 2026-03-06T10:07:22+01:00
New Revision: 454eb8bc0ac2a3a3e843440c7f45f3fdb32b40b3

URL: 
https://github.com/llvm/llvm-project/commit/454eb8bc0ac2a3a3e843440c7f45f3fdb32b40b3
DIFF: 
https://github.com/llvm/llvm-project/commit/454eb8bc0ac2a3a3e843440c7f45f3fdb32b40b3.diff

LOG: [lldb] Initial plugin and test for SymbolLocatorSymStore (#183302)

Minimal infrastructure for a the SymbolLocator plugin that fetches debug
info from Microsoft SymStore repositories. More features will follow.

SymbolVendorPECOFF was tailored towards DWARF debug info so far. This
patch adds code to load the PDB path from the executable and not bail
out if DWARF sections are missing, so that in the PDB case we still
call `AddSymbolFileRepresentation()` in the very end of
`CreateInstance()`.

The API test in this patch mocks the directory layout from SymStore, so
it doesn't depend on `SymStore.exe` from the Windows SDK. It runs on all
platforms that link debug info in a PDB file, which is still just
Windows, but it could be cross-platform in principle.

Added: 
    lldb/source/Plugins/SymbolLocator/SymStore/CMakeLists.txt
    lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
    lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
    
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
    lldb/test/API/symstore/Makefile
    lldb/test/API/symstore/TestSymStoreLocal.py
    lldb/test/API/symstore/main.c

Modified: 
    lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
    lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
    lldb/source/Plugins/SymbolLocator/CMakeLists.txt
    lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp 
b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 3a17b4c46a788..cec47d96b33d2 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -1108,6 +1108,27 @@ std::optional<FileSpec> ObjectFilePECOFF::GetDebugLink() 
{
   return std::nullopt;
 }
 
+std::optional<FileSpec> ObjectFilePECOFF::GetPDBPath() {
+  llvm::StringRef pdb_file;
+  const llvm::codeview::DebugInfo *pdb_info = nullptr;
+  if (llvm::Error Err = m_binary->getDebugPDBInfo(pdb_info, pdb_file)) {
+    // DebugInfo section is corrupt.
+    Log *log = GetLog(LLDBLog::Object);
+    llvm::StringRef file = m_binary->getFileName();
+    LLDB_LOG_ERROR(
+        log, std::move(Err),
+        "Failed to read Codeview record for PDB debug info file ({1}): {0}",
+        file);
+    return std::nullopt;
+  }
+  if (pdb_file.empty()) {
+    // No DebugInfo section present.
+    return std::nullopt;
+  }
+  return FileSpec(pdb_file, FileSpec::GuessPathStyle(pdb_file).value_or(
+                                FileSpec::Style::native));
+}
+
 uint32_t ObjectFilePECOFF::ParseDependentModules() {
   ModuleSP module_sp(GetModule());
   if (!module_sp)

diff  --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h 
b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index 8002e70e604bb..30bd672dc68f8 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -130,6 +130,8 @@ class ObjectFilePECOFF : public lldb_private::ObjectFile {
   /// contains it.
   std::optional<lldb_private::FileSpec> GetDebugLink();
 
+  std::optional<lldb_private::FileSpec> GetPDBPath();
+
   uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
 
   lldb_private::Address GetEntryPointAddress() override;

diff  --git a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt 
b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
index 3b466f71dca58..9b9ec470b86a9 100644
--- a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
@@ -6,6 +6,7 @@ set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND SymbolLocator)
 # prevents an unstripped binary from being requested from the Debuginfod
 # provider.
 add_subdirectory(Debuginfod)
+add_subdirectory(SymStore)
 add_subdirectory(Default)
 if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
   add_subdirectory(DebugSymbols)

diff  --git a/lldb/source/Plugins/SymbolLocator/SymStore/CMakeLists.txt 
b/lldb/source/Plugins/SymbolLocator/SymStore/CMakeLists.txt
new file mode 100644
index 0000000000000..b0da27f26c6a8
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/CMakeLists.txt
@@ -0,0 +1,20 @@
+lldb_tablegen(SymbolLocatorSymStoreProperties.inc -gen-lldb-property-defs
+  SOURCE SymbolLocatorSymStoreProperties.td
+  TARGET LLDBPluginSymbolLocatorSymStorePropertiesGen)
+
+lldb_tablegen(SymbolLocatorSymStorePropertiesEnum.inc 
-gen-lldb-property-enum-defs
+  SOURCE SymbolLocatorSymStoreProperties.td
+  TARGET LLDBPluginSymbolLocatorSymStorePropertiesEnumGen)
+
+add_lldb_library(lldbPluginSymbolLocatorSymStore PLUGIN
+  SymbolLocatorSymStore.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+  )
+
+add_dependencies(lldbPluginSymbolLocatorSymStore
+  LLDBPluginSymbolLocatorSymStorePropertiesGen
+  LLDBPluginSymbolLocatorSymStorePropertiesEnumGen)

diff  --git 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
new file mode 100644
index 0000000000000..d008a7d3e8e9a
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -0,0 +1,147 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolLocatorSymStore.h"
+
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/UUID.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(SymbolLocatorSymStore)
+
+namespace {
+
+#define LLDB_PROPERTIES_symbollocatorsymstore
+#include "SymbolLocatorSymStoreProperties.inc"
+
+enum {
+#define LLDB_PROPERTIES_symbollocatorsymstore
+#include "SymbolLocatorSymStorePropertiesEnum.inc"
+};
+
+class PluginProperties : public Properties {
+public:
+  static llvm::StringRef GetSettingName() {
+    return SymbolLocatorSymStore::GetPluginNameStatic();
+  }
+
+  PluginProperties() {
+    m_collection_sp = 
std::make_shared<OptionValueProperties>(GetSettingName());
+    m_collection_sp->Initialize(g_symbollocatorsymstore_properties_def);
+  }
+
+  Args GetURLs() const {
+    Args urls;
+    m_collection_sp->GetPropertyAtIndexAsArgs(ePropertySymStoreURLs, urls);
+    return urls;
+  }
+};
+
+} // namespace
+
+static PluginProperties &GetGlobalPluginProperties() {
+  static PluginProperties g_settings;
+  return g_settings;
+}
+
+SymbolLocatorSymStore::SymbolLocatorSymStore() : SymbolLocator() {}
+
+void SymbolLocatorSymStore::Initialize() {
+  // First version can only locate PDB in local SymStore (no download yet).
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+      nullptr, LocateExecutableSymbolFile, nullptr, nullptr,
+      SymbolLocatorSymStore::DebuggerInitialize);
+}
+
+void SymbolLocatorSymStore::DebuggerInitialize(Debugger &debugger) {
+  if (!PluginManager::GetSettingForSymbolLocatorPlugin(
+          debugger, PluginProperties::GetSettingName())) {
+    constexpr bool is_global_setting = true;
+    PluginManager::CreateSettingForSymbolLocatorPlugin(
+        debugger, GetGlobalPluginProperties().GetValueProperties(),
+        "Properties for the SymStore Symbol Locator plug-in.",
+        is_global_setting);
+  }
+}
+
+void SymbolLocatorSymStore::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef SymbolLocatorSymStore::GetPluginDescriptionStatic() {
+  return "Symbol locator for PDB in SymStore";
+}
+
+SymbolLocator *SymbolLocatorSymStore::CreateInstance() {
+  return new SymbolLocatorSymStore();
+}
+
+// RSDS entries store identity as a 20-byte UUID composed of 16-byte GUID and
+// 4-byte age:
+//   12345678-1234-5678-9ABC-DEF012345678-00000001
+//
+// SymStore key is a string with no separators and age as decimal:
+//   12345678123456789ABCDEF0123456781
+//
+static std::string formatSymStoreKey(const UUID &uuid) {
+  llvm::ArrayRef<uint8_t> bytes = uuid.GetBytes();
+  uint32_t age = llvm::support::endian::read32be(bytes.data() + 16);
+  constexpr bool LowerCase = false;
+  return llvm::toHex(bytes.slice(0, 16), LowerCase) + std::to_string(age);
+}
+
+std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
+    const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+  const UUID &uuid = module_spec.GetUUID();
+  if (!uuid.IsValid() ||
+      !ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup())
+    return {};
+
+  Log *log = GetLog(LLDBLog::Symbols);
+  std::string pdb_name =
+      module_spec.GetSymbolFileSpec().GetFilename().GetStringRef().str();
+  if (pdb_name.empty()) {
+    LLDB_LOGV(log, "Failed to resolve symbol PDB module: PDB name empty");
+    return {};
+  }
+
+  LLDB_LOGV(log, "LocateExecutableSymbolFile {0} with UUID {1}", pdb_name,
+            uuid.GetAsString());
+  if (uuid.GetBytes().size() != 20) {
+    LLDB_LOGV(log, "Failed to resolve symbol PDB module: UUID invalid");
+    return {};
+  }
+
+  std::string key = formatSymStoreKey(uuid);
+  Args sym_store_urls = GetGlobalPluginProperties().GetURLs();
+  for (const Args::ArgEntry &url : sym_store_urls) {
+    llvm::SmallString<256> path;
+    llvm::sys::path::append(path, url.ref(), pdb_name, key, pdb_name);
+    FileSpec spec(path);
+    if (FileSystem::Instance().Exists(spec)) {
+      LLDB_LOGV(log, "Found {0} in SymStore {1}", pdb_name, url.ref());
+      return spec;
+    }
+  }
+
+  return {};
+}

diff  --git 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
new file mode 100644
index 0000000000000..52ec04cae387b
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_SYMSTORE_SYMBOLLOCATORSYMSTORE_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_SYMSTORE_SYMBOLLOCATORSYMSTORE_H
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Symbol/SymbolLocator.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+/// This plugin implements lookup in Microsoft SymStore instances. This can 
work
+/// cross-platform and for arbitrary debug info formats, but the focus is on 
PDB
+/// with PE/COFF binaries on Windows.
+class SymbolLocatorSymStore : public SymbolLocator {
+public:
+  SymbolLocatorSymStore();
+
+  static void Initialize();
+  static void Terminate();
+  static void DebuggerInitialize(Debugger &debugger);
+
+  static llvm::StringRef GetPluginNameStatic() { return "symstore"; }
+  static llvm::StringRef GetPluginDescriptionStatic();
+
+  static lldb_private::SymbolLocator *CreateInstance();
+
+  /// PluginInterface protocol.
+  /// \{
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+  /// \}
+
+  // Locate the symbol file given a module specification.
+  //
+  // Locating the file should happen only on the local computer or using the
+  // current computers global settings.
+  static std::optional<FileSpec>
+  LocateExecutableSymbolFile(const ModuleSpec &module_spec,
+                             const FileSpecList &default_search_paths);
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_SYMSTORE_SYMBOLLOCATORSYMSTORE_H

diff  --git 
a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
new file mode 100644
index 0000000000000..0cd631a80b90b
--- /dev/null
+++ 
b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
@@ -0,0 +1,7 @@
+include "../../../../include/lldb/Core/PropertiesBase.td"
+
+let Definition = "symbollocatorsymstore", Path = 
"plugin.symbol-locator.symstore" in {
+  def SymStoreURLs : Property<"urls", "Array">,
+    ElementType<"String">,
+    Desc<"List of local symstore directories to query for symbols">;
+}

diff  --git a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp 
b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
index 20ccfa54a106c..1797e5b7677ee 100644
--- a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
@@ -71,6 +71,9 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP 
&module_sp,
 
   // If the module specified a filespec, use that.
   FileSpec fspec = module_sp->GetSymbolFileFileSpec();
+  // Otherwise, use the PDB path from CodeView.
+  if (!fspec)
+    fspec = obj_file->GetPDBPath().value_or(FileSpec());
   // Otherwise, try gnu_debuglink, if one exists.
   if (!fspec)
     fspec = obj_file->GetDebugLink().value_or(FileSpec());
@@ -101,31 +104,30 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP 
&module_sp,
   // This objfile is for debugging purposes.
   dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
 
-  // Get the module unified section list and add our debug sections to
-  // that.
+  // For DWARF get the module unified section list and add our debug sections
+  // to that.
   SectionList *module_section_list = module_sp->GetSectionList();
   SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
-  if (!objfile_section_list || !module_section_list)
-    return nullptr;
-
-  static const SectionType g_sections[] = {
-      eSectionTypeDWARFDebugAbbrev,   eSectionTypeDWARFDebugAranges,
-      eSectionTypeDWARFDebugFrame,    eSectionTypeDWARFDebugInfo,
-      eSectionTypeDWARFDebugLine,     eSectionTypeDWARFDebugLoc,
-      eSectionTypeDWARFDebugLocLists, eSectionTypeDWARFDebugMacInfo,
-      eSectionTypeDWARFDebugNames,    eSectionTypeDWARFDebugPubNames,
-      eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
-      eSectionTypeDWARFDebugStr,      eSectionTypeDWARFDebugTypes,
-  };
-  for (SectionType section_type : g_sections) {
-    if (SectionSP section_sp =
-            objfile_section_list->FindSectionByType(section_type, true)) {
-      if (SectionSP module_section_sp =
-              module_section_list->FindSectionByType(section_type, true))
-        module_section_list->ReplaceSection(module_section_sp->GetID(),
-                                            section_sp);
-      else
-        module_section_list->AddSection(section_sp);
+  if (objfile_section_list && module_section_list) {
+    static const SectionType g_sections[] = {
+        eSectionTypeDWARFDebugAbbrev,   eSectionTypeDWARFDebugAranges,
+        eSectionTypeDWARFDebugFrame,    eSectionTypeDWARFDebugInfo,
+        eSectionTypeDWARFDebugLine,     eSectionTypeDWARFDebugLoc,
+        eSectionTypeDWARFDebugLocLists, eSectionTypeDWARFDebugMacInfo,
+        eSectionTypeDWARFDebugNames,    eSectionTypeDWARFDebugPubNames,
+        eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
+        eSectionTypeDWARFDebugStr,      eSectionTypeDWARFDebugTypes,
+    };
+    for (SectionType section_type : g_sections) {
+      if (SectionSP section_sp =
+              objfile_section_list->FindSectionByType(section_type, true)) {
+        if (SectionSP module_section_sp =
+                module_section_list->FindSectionByType(section_type, true))
+          module_section_list->ReplaceSection(module_section_sp->GetID(),
+                                              section_sp);
+        else
+          module_section_list->AddSection(section_sp);
+      }
     }
   }
 

diff  --git a/lldb/test/API/symstore/Makefile b/lldb/test/API/symstore/Makefile
new file mode 100644
index 0000000000000..6279aee698dad
--- /dev/null
+++ b/lldb/test/API/symstore/Makefile
@@ -0,0 +1,4 @@
+MAKE_PDB := YES
+
+C_SOURCES := main.c
+include Makefile.rules

diff  --git a/lldb/test/API/symstore/TestSymStoreLocal.py 
b/lldb/test/API/symstore/TestSymStoreLocal.py
new file mode 100644
index 0000000000000..f45e368613847
--- /dev/null
+++ b/lldb/test/API/symstore/TestSymStoreLocal.py
@@ -0,0 +1,122 @@
+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. This can work
+cross-platform and for arbitrary debug info formats. We only support PDB
+currently.
+"""
+
+
+class MockedSymStore:
+    """
+    Context Manager to populate a file structure equivalent to SymStore.exe in 
a
+    temporary directory.
+    """
+
+    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
+        """
+        spec = lldb.SBModuleSpec()
+        spec.SetFileSpec(lldb.SBFileSpec(self._test.getBuildArtifact(exe)))
+        module = lldb.SBModule(spec)
+        raw = module.GetUUIDString().replace("-", "").upper()
+        if len(raw) != 40:
+            raise RuntimeError("Unexpected number of bytes in embedded UUID")
+        guid_hex = raw[:32]
+        age = int(raw[32:], 16)
+        return guid_hex + str(age)
+
+    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
+
+    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))
+
+
+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, ext_lookup=True):
+        enable = "true" if ext_lookup else "false"
+        self.runCmd(f"settings set symbols.enable-external-lookup {enable}")
+        target = self.dbg.CreateTarget(self.getBuildArtifact(exe))
+        self.assertTrue(target and target.IsValid(), "Target is valid")
+        bp = target.BreakpointCreateByName("func")
+        self.assertTrue(bp and bp.IsValid(), "Breakpoint is valid")
+        self.assertEqual(bp.GetNumLocations(), 1 if should_have_loc else 0)
+        self.dbg.DeleteTarget(target)
+
+    def test_no_symstore_url(self):
+        """
+        Check that breakpoint doesn't resolve without SymStore.
+        """
+        exe, sym = self.build_inferior()
+        with MockedSymStore(self, exe, sym):
+            self.try_breakpoint(exe, should_have_loc=False)
+
+    def test_external_lookup_off(self):
+        """
+        Check that breakpoint doesn't resolve with external lookup disabled.
+        """
+        exe, sym = self.build_inferior()
+        with MockedSymStore(self, exe, sym) as symstore_dir:
+            self.runCmd(
+                f"settings set plugin.symbol-locator.symstore.urls 
{symstore_dir}"
+            )
+            self.try_breakpoint(exe, ext_lookup=False, should_have_loc=False)
+
+    def test_basic(self):
+        """
+        Check that breakpoint resolves with local SymStore.
+        """
+        exe, sym = self.build_inferior()
+        with MockedSymStore(self, exe, sym) as symstore_dir:
+            self.runCmd(
+                f"settings set plugin.symbol-locator.symstore.urls 
{symstore_dir}"
+            )
+            self.try_breakpoint(exe, should_have_loc=True)

diff  --git a/lldb/test/API/symstore/main.c b/lldb/test/API/symstore/main.c
new file mode 100644
index 0000000000000..a95762e80ea44
--- /dev/null
+++ b/lldb/test/API/symstore/main.c
@@ -0,0 +1,5 @@
+int func(int argc, const char *argv[]) {
+  return (argc + 1) * (argv[argc][0] + 2);
+}
+
+int main(int argc, const char *argv[]) { return func(0, argv); }


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to