[Lldb-commits] [lldb] [lldb] Initial plugin and test for SymbolLocatorSymStore (PR #183302)
Stefan Gränitz via lldb-commits
lldb-commits at lists.llvm.org
Mon Mar 2 00:54:00 PST 2026
https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/183302
>From 776d3b8434144a00abce25073fd137d195c200de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 23 Feb 2026 13:52:42 +0100
Subject: [PATCH 01/12] Initial infra for SymbolLocator plugin and test
---
.../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 15 ++
.../ObjectFile/PECOFF/ObjectFilePECOFF.h | 2 +
.../Plugins/SymbolLocator/CMakeLists.txt | 1 +
.../SymbolLocator/Microsoft/CMakeLists.txt | 20 +++
.../Microsoft/SymbolLocatorMicrosoft.cpp | 156 ++++++++++++++++++
.../Microsoft/SymbolLocatorMicrosoft.h | 47 ++++++
.../SymbolLocatorMicrosoftProperties.td | 7 +
.../PECOFF/SymbolVendorPECOFF.cpp | 3 +
lldb/test/API/microsoft_symsrv/Makefile | 2 +
.../microsoft_symsrv/TestMicrosoftSymSrv.py | 105 ++++++++++++
lldb/test/API/microsoft_symsrv/main.c | 5 +
11 files changed, 363 insertions(+)
create mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
create mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp
create mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h
create mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
create mode 100644 lldb/test/API/microsoft_symsrv/Makefile
create mode 100644 lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py
create mode 100644 lldb/test/API/microsoft_symsrv/main.c
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 3a17b4c46a788..2e169bb6e8a53 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -1108,6 +1108,21 @@ 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)) {
+ // Ignore corrupt DebugInfo sections
+ llvm::consumeError(std::move(Err));
+ return std::nullopt;
+ }
+ if (pdb_file.empty()) {
+ // No DebugInfo section
+ return std::nullopt;
+ }
+ return FileSpec(pdb_file);
+}
+
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..818a2e18fe4fb 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(Microsoft)
add_subdirectory(Default)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(DebugSymbols)
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
new file mode 100644
index 0000000000000..a27ce8aa9978e
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
@@ -0,0 +1,20 @@
+lldb_tablegen(SymbolLocatorMicrosoftProperties.inc -gen-lldb-property-defs
+ SOURCE SymbolLocatorMicrosoftProperties.td
+ TARGET LLDBPluginSymbolLocatorMicrosoftPropertiesGen)
+
+lldb_tablegen(SymbolLocatorMicrosoftPropertiesEnum.inc -gen-lldb-property-enum-defs
+ SOURCE SymbolLocatorMicrosoftProperties.td
+ TARGET LLDBPluginSymbolLocatorMicrosoftPropertiesEnumGen)
+
+add_lldb_library(lldbPluginSymbolLocatorMicrosoft PLUGIN
+ SymbolLocatorMicrosoft.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ )
+
+add_dependencies(lldbPluginSymbolLocatorMicrosoft
+ LLDBPluginSymbolLocatorMicrosoftPropertiesGen
+ LLDBPluginSymbolLocatorMicrosoftPropertiesEnumGen)
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp
new file mode 100644
index 0000000000000..9d8a018639673
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp
@@ -0,0 +1,156 @@
+//===-- SymbolLocatorMicrosoft.cpp ---------------------------------------===//
+//
+// 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 "SymbolLocatorMicrosoft.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(SymbolLocatorMicrosoft)
+
+namespace {
+
+#define LLDB_PROPERTIES_symbollocatormicrosoft
+#include "SymbolLocatorMicrosoftProperties.inc"
+
+enum {
+#define LLDB_PROPERTIES_symbollocatormicrosoft
+#include "SymbolLocatorMicrosoftPropertiesEnum.inc"
+};
+
+class PluginProperties : public Properties {
+public:
+ static llvm::StringRef GetSettingName() {
+ return SymbolLocatorMicrosoft::GetPluginNameStatic();
+ }
+
+ PluginProperties() {
+ m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
+ m_collection_sp->Initialize(g_symbollocatormicrosoft_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;
+}
+
+SymbolLocatorMicrosoft::SymbolLocatorMicrosoft() : SymbolLocator() {}
+
+void SymbolLocatorMicrosoft::Initialize() {
+ // First version can only locate PDB in local SymStore (no download yet)
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+ nullptr, LocateExecutableSymbolFile, nullptr, nullptr,
+ SymbolLocatorMicrosoft::DebuggerInitialize);
+}
+
+void SymbolLocatorMicrosoft::DebuggerInitialize(Debugger &debugger) {
+ if (!PluginManager::GetSettingForSymbolLocatorPlugin(
+ debugger, PluginProperties::GetSettingName())) {
+ constexpr bool is_global_setting = true;
+ PluginManager::CreateSettingForSymbolLocatorPlugin(
+ debugger, GetGlobalPluginProperties().GetValueProperties(),
+ "Properties for the Microsoft Symbol Locator plug-in.",
+ is_global_setting);
+ }
+}
+
+void SymbolLocatorMicrosoft::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+llvm::StringRef SymbolLocatorMicrosoft::GetPluginDescriptionStatic() {
+ return "Symbol locator for PDB in Microsoft SymStore";
+}
+
+SymbolLocator *SymbolLocatorMicrosoft::CreateInstance() {
+ return new SymbolLocatorMicrosoft();
+}
+
+// LLDB stores PDB 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> SymbolLocatorMicrosoft::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 {};
+ }
+
+ // FIXME: We need this for the test executable, because it is loaded as DWARF
+ if (!llvm::StringRef(pdb_name).ends_with(".pdb")) {
+ auto last_dot = pdb_name.find_last_of('.');
+ if (last_dot != llvm::StringRef::npos) {
+ pdb_name = pdb_name.substr(0, last_dot);
+ }
+ pdb_name += ".pdb";
+ }
+
+ 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/Microsoft/SymbolLocatorMicrosoft.h b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h
new file mode 100644
index 0000000000000..36bdfd4d67d9a
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h
@@ -0,0 +1,47 @@
+//===-- SymbolLocatorMicrosoft.h -------------------------------*- C++ -*-===//
+//
+// 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_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Symbol/SymbolLocator.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+class SymbolLocatorMicrosoft : public SymbolLocator {
+public:
+ SymbolLocatorMicrosoft();
+
+ static void Initialize();
+ static void Terminate();
+ static void DebuggerInitialize(Debugger &debugger);
+
+ static llvm::StringRef GetPluginNameStatic() { return "microsoft"; }
+ 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_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
new file mode 100644
index 0000000000000..d02098536689d
--- /dev/null
+++ b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
@@ -0,0 +1,7 @@
+include "../../../../include/lldb/Core/PropertiesBase.td"
+
+let Definition = "symbollocatormicrosoft", Path = "plugin.symbol-locator.microsoft" in {
+ def SymStoreURLs : Property<"symstore-urls", "Array">,
+ ElementType<"String">,
+ Desc<"An ordered list of symstore URLs to query for symbols. This is prepended to the contents of the _NT_SYMBOL_PATH environment variable.">;
+}
diff --git a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
index 20ccfa54a106c..94c3548b80e4a 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());
diff --git a/lldb/test/API/microsoft_symsrv/Makefile b/lldb/test/API/microsoft_symsrv/Makefile
new file mode 100644
index 0000000000000..c9319d6e6888a
--- /dev/null
+++ b/lldb/test/API/microsoft_symsrv/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := main.c
+include Makefile.rules
diff --git a/lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py b/lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py
new file mode 100644
index 0000000000000..f69d4cc9791be
--- /dev/null
+++ b/lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py
@@ -0,0 +1,105 @@
+import glob
+import os
+import shutil
+import tempfile
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class MicrosoftSymSrvTests(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def try_breakpoint(self, should_have_loc):
+ target = self.dbg.CreateTarget(self.aout)
+ 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)
+
+ loc = bp.GetLocationAtIndex(0)
+ self.assertTrue(loc and loc.IsValid(), "Location is valid")
+ addr = loc.GetAddress()
+ self.assertTrue(addr and addr.IsValid(), "Loc address is valid")
+ line_entry = addr.GetLineEntry()
+ self.assertEqual(
+ should_have_loc,
+ line_entry is not None and line_entry.IsValid(),
+ "Loc line entry validity",
+ )
+ if should_have_loc:
+ self.assertEqual(line_entry.GetLine(), 2)
+ self.assertEqual(
+ line_entry.GetFileSpec().GetFilename(),
+ self.main_source_file.GetFilename(),
+ )
+ self.dbg.DeleteTarget(target)
+
+ def populate_symstore(self, tmp):
+ """
+ Build test binary and mock local symstore directory tree:
+ tmp/test/a.out binary (no PDB in search path)
+ tmp/server/<pdb>/<key>/<pdb> PDB in symstore
+ """
+ self.build()
+ pdbs = glob.glob(os.path.join(self.getBuildDir(), "*.pdb"))
+ if len(pdbs) == 0:
+ self.skipTest("Build did not produce a PDB file")
+
+ self.main_source_file = lldb.SBFileSpec("main.c")
+
+ binary_name = "a.out"
+ pdb_name = "a.pdb"
+ key = self.symstore_key(binary_name)
+ if key is None:
+ self.skipTest("Could not obtain a 20-byte PDB UUID from the binary")
+
+ # Set up test directory with just the binary (no PDB).
+ test_dir = os.path.join(tmp, "test")
+ os.makedirs(test_dir)
+ shutil.move(self.getBuildArtifact(binary_name), test_dir)
+ self.aout = os.path.join(test_dir, binary_name)
+
+ # SymStore directory tree: <pdb>/<key>/<pdb>
+ server_dir = os.path.join(tmp, "server")
+ pdb_key_dir = os.path.join(server_dir, pdb_name, key)
+ os.makedirs(pdb_key_dir)
+ shutil.move(
+ self.getBuildArtifact(pdb_name),
+ os.path.join(pdb_key_dir, pdb_name),
+ )
+
+ return server_dir
+
+ def symstore_key(self, exe):
+ """Load module UUID like: 12345678-1234-5678-9ABC-DEF012345678-00000001
+ and transform to SymStore key: 12345678123456789ABCDEF0123456781"""
+ try:
+ spec = lldb.SBModuleSpec()
+ spec.SetFileSpec(lldb.SBFileSpec(self.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
+
+ # TODO: Check on other platforms, it should work in theory
+ @skipUnlessPlatform(["windows"])
+ def test_local_folder(self):
+ """Check that LLDB can fetch PDB from local SymStore directory"""
+ tmp_dir = tempfile.mkdtemp()
+ symstore_dir = self.populate_symstore(tmp_dir)
+
+ self.runCmd(
+ "settings set plugin.symbol-locator.microsoft.symstore-urls %s"
+ % symstore_dir.replace("\\", "/")
+ )
+
+ self.try_breakpoint(should_have_loc=True)
+ shutil.rmtree(tmp_dir)
diff --git a/lldb/test/API/microsoft_symsrv/main.c b/lldb/test/API/microsoft_symsrv/main.c
new file mode 100644
index 0000000000000..a95762e80ea44
--- /dev/null
+++ b/lldb/test/API/microsoft_symsrv/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); }
>From 2b3ff76cd168a5f816115fc17a7f19d02093c2c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 12:09:28 +0100
Subject: [PATCH 02/12] Fix SymbolVendorPECOFF: Don't exit early if symbol file
has no DWARF sections
---
.../PECOFF/SymbolVendorPECOFF.cpp | 45 +++++++++----------
1 file changed, 22 insertions(+), 23 deletions(-)
diff --git a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
index 94c3548b80e4a..1797e5b7677ee 100644
--- a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
@@ -104,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);
+ }
}
}
>From 113adf839b18d1a903c2f3b5ea3ccb9da7d31b51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 12:57:58 +0100
Subject: [PATCH 03/12] Rename Microsoft -> SymStore (NFC)
---
.../Plugins/SymbolLocator/CMakeLists.txt | 2 +-
.../SymbolLocator/Microsoft/CMakeLists.txt | 20 --------
.../SymbolLocatorMicrosoftProperties.td | 7 ---
.../SymbolLocator/SymStore/CMakeLists.txt | 20 ++++++++
.../SymbolLocatorSymStore.cpp} | 40 ++++++++--------
.../SymbolLocatorSymStore.h} | 14 +++---
.../SymbolLocatorSymStoreProperties.td | 7 +++
.../PDB}/Makefile | 0
.../PDB/TestSymStoreLocalPDB.py} | 47 +++++++++++--------
.../{microsoft_symsrv => symstore/PDB}/main.c | 0
10 files changed, 82 insertions(+), 75 deletions(-)
delete mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
delete mode 100644 lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
create mode 100644 lldb/source/Plugins/SymbolLocator/SymStore/CMakeLists.txt
rename lldb/source/Plugins/SymbolLocator/{Microsoft/SymbolLocatorMicrosoft.cpp => SymStore/SymbolLocatorSymStore.cpp} (77%)
rename lldb/source/Plugins/SymbolLocator/{Microsoft/SymbolLocatorMicrosoft.h => SymStore/SymbolLocatorSymStore.h} (71%)
create mode 100644 lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
rename lldb/test/API/{microsoft_symsrv => symstore/PDB}/Makefile (100%)
rename lldb/test/API/{microsoft_symsrv/TestMicrosoftSymSrv.py => symstore/PDB/TestSymStoreLocalPDB.py} (75%)
rename lldb/test/API/{microsoft_symsrv => symstore/PDB}/main.c (100%)
diff --git a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
index 818a2e18fe4fb..9b9ec470b86a9 100644
--- a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt
@@ -6,7 +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(Microsoft)
+add_subdirectory(SymStore)
add_subdirectory(Default)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(DebugSymbols)
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
deleted file mode 100644
index a27ce8aa9978e..0000000000000
--- a/lldb/source/Plugins/SymbolLocator/Microsoft/CMakeLists.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-lldb_tablegen(SymbolLocatorMicrosoftProperties.inc -gen-lldb-property-defs
- SOURCE SymbolLocatorMicrosoftProperties.td
- TARGET LLDBPluginSymbolLocatorMicrosoftPropertiesGen)
-
-lldb_tablegen(SymbolLocatorMicrosoftPropertiesEnum.inc -gen-lldb-property-enum-defs
- SOURCE SymbolLocatorMicrosoftProperties.td
- TARGET LLDBPluginSymbolLocatorMicrosoftPropertiesEnumGen)
-
-add_lldb_library(lldbPluginSymbolLocatorMicrosoft PLUGIN
- SymbolLocatorMicrosoft.cpp
-
- LINK_LIBS
- lldbCore
- lldbHost
- lldbSymbol
- )
-
-add_dependencies(lldbPluginSymbolLocatorMicrosoft
- LLDBPluginSymbolLocatorMicrosoftPropertiesGen
- LLDBPluginSymbolLocatorMicrosoftPropertiesEnumGen)
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td b/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
deleted file mode 100644
index d02098536689d..0000000000000
--- a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoftProperties.td
+++ /dev/null
@@ -1,7 +0,0 @@
-include "../../../../include/lldb/Core/PropertiesBase.td"
-
-let Definition = "symbollocatormicrosoft", Path = "plugin.symbol-locator.microsoft" in {
- def SymStoreURLs : Property<"symstore-urls", "Array">,
- ElementType<"String">,
- Desc<"An ordered list of symstore URLs to query for symbols. This is prepended to the contents of the _NT_SYMBOL_PATH environment variable.">;
-}
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/Microsoft/SymbolLocatorMicrosoft.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
similarity index 77%
rename from lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp
rename to lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 9d8a018639673..0341249f0da0e 100644
--- a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolLocatorMicrosoft.cpp ---------------------------------------===//
+//===-- SymbolLocatorSymStore.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "SymbolLocatorMicrosoft.h"
+#include "SymbolLocatorSymStore.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/PluginManager.h"
@@ -25,27 +25,27 @@
using namespace lldb;
using namespace lldb_private;
-LLDB_PLUGIN_DEFINE(SymbolLocatorMicrosoft)
+LLDB_PLUGIN_DEFINE(SymbolLocatorSymStore)
namespace {
-#define LLDB_PROPERTIES_symbollocatormicrosoft
-#include "SymbolLocatorMicrosoftProperties.inc"
+#define LLDB_PROPERTIES_symbollocatorsymstore
+#include "SymbolLocatorSymStoreProperties.inc"
enum {
-#define LLDB_PROPERTIES_symbollocatormicrosoft
-#include "SymbolLocatorMicrosoftPropertiesEnum.inc"
+#define LLDB_PROPERTIES_symbollocatorsymstore
+#include "SymbolLocatorSymStorePropertiesEnum.inc"
};
class PluginProperties : public Properties {
public:
static llvm::StringRef GetSettingName() {
- return SymbolLocatorMicrosoft::GetPluginNameStatic();
+ return SymbolLocatorSymStore::GetPluginNameStatic();
}
PluginProperties() {
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
- m_collection_sp->Initialize(g_symbollocatormicrosoft_properties_def);
+ m_collection_sp->Initialize(g_symbollocatorsymstore_properties_def);
}
Args GetURLs() const {
@@ -62,37 +62,37 @@ static PluginProperties &GetGlobalPluginProperties() {
return g_settings;
}
-SymbolLocatorMicrosoft::SymbolLocatorMicrosoft() : SymbolLocator() {}
+SymbolLocatorSymStore::SymbolLocatorSymStore() : SymbolLocator() {}
-void SymbolLocatorMicrosoft::Initialize() {
+void SymbolLocatorSymStore::Initialize() {
// First version can only locate PDB in local SymStore (no download yet)
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
nullptr, LocateExecutableSymbolFile, nullptr, nullptr,
- SymbolLocatorMicrosoft::DebuggerInitialize);
+ SymbolLocatorSymStore::DebuggerInitialize);
}
-void SymbolLocatorMicrosoft::DebuggerInitialize(Debugger &debugger) {
+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 Microsoft Symbol Locator plug-in.",
+ "Properties for the SymStore Symbol Locator plug-in.",
is_global_setting);
}
}
-void SymbolLocatorMicrosoft::Terminate() {
+void SymbolLocatorSymStore::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
-llvm::StringRef SymbolLocatorMicrosoft::GetPluginDescriptionStatic() {
- return "Symbol locator for PDB in Microsoft SymStore";
+llvm::StringRef SymbolLocatorSymStore::GetPluginDescriptionStatic() {
+ return "Symbol locator for PDB in SymStore SymStore";
}
-SymbolLocator *SymbolLocatorMicrosoft::CreateInstance() {
- return new SymbolLocatorMicrosoft();
+SymbolLocator *SymbolLocatorSymStore::CreateInstance() {
+ return new SymbolLocatorSymStore();
}
// LLDB stores PDB identity as a 20-byte UUID composed of 16-byte GUID and
@@ -109,7 +109,7 @@ static std::string formatSymStoreKey(const UUID &uuid) {
return llvm::toHex(bytes.slice(0, 16), LowerCase) + std::to_string(age);
}
-std::optional<FileSpec> SymbolLocatorMicrosoft::LocateExecutableSymbolFile(
+std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
const UUID &uuid = module_spec.GetUUID();
if (!uuid.IsValid() ||
diff --git a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
similarity index 71%
rename from lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h
rename to lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
index 36bdfd4d67d9a..551b774dc9f3a 100644
--- a/lldb/source/Plugins/SymbolLocator/Microsoft/SymbolLocatorMicrosoft.h
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
@@ -1,4 +1,4 @@
-//===-- SymbolLocatorMicrosoft.h -------------------------------*- C++ -*-===//
+//===-- SymbolLocatorSymStore.h ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
-#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
+#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"
@@ -15,15 +15,15 @@
namespace lldb_private {
-class SymbolLocatorMicrosoft : public SymbolLocator {
+class SymbolLocatorSymStore : public SymbolLocator {
public:
- SymbolLocatorMicrosoft();
+ SymbolLocatorSymStore();
static void Initialize();
static void Terminate();
static void DebuggerInitialize(Debugger &debugger);
- static llvm::StringRef GetPluginNameStatic() { return "microsoft"; }
+ static llvm::StringRef GetPluginNameStatic() { return "symstore"; }
static llvm::StringRef GetPluginDescriptionStatic();
static lldb_private::SymbolLocator *CreateInstance();
@@ -44,4 +44,4 @@ class SymbolLocatorMicrosoft : public SymbolLocator {
} // namespace lldb_private
-#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_MICROSOFT_SYMBOLLOCATORMICROSOFT_H
+#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/test/API/microsoft_symsrv/Makefile b/lldb/test/API/symstore/PDB/Makefile
similarity index 100%
rename from lldb/test/API/microsoft_symsrv/Makefile
rename to lldb/test/API/symstore/PDB/Makefile
diff --git a/lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py b/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
similarity index 75%
rename from lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py
rename to lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
index f69d4cc9791be..370c3000690bf 100644
--- a/lldb/test/API/microsoft_symsrv/TestMicrosoftSymSrv.py
+++ b/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
@@ -7,8 +7,14 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
-
-class MicrosoftSymSrvTests(TestBase):
+"""
+Test debug symbol acquisition from a local SymStore repository. We populate the
+respective file structure in a temporary directory and run LLDB on it. This is
+supposed to work cross-platform. The test can run on all platforms that can link
+debug info in a PDB file with clang.
+"""
+
+class SymStoreLocalPDBTests(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def try_breakpoint(self, should_have_loc):
@@ -37,32 +43,31 @@ def try_breakpoint(self, should_have_loc):
)
self.dbg.DeleteTarget(target)
- def populate_symstore(self, tmp):
- """
- Build test binary and mock local symstore directory tree:
- tmp/test/a.out binary (no PDB in search path)
- tmp/server/<pdb>/<key>/<pdb> PDB in symstore
- """
+ def build_inferior_with_pdb(self):
+ self.main_source_file = lldb.SBFileSpec("main.c")
self.build()
pdbs = glob.glob(os.path.join(self.getBuildDir(), "*.pdb"))
- if len(pdbs) == 0:
- self.skipTest("Build did not produce a PDB file")
-
- self.main_source_file = lldb.SBFileSpec("main.c")
+ return len(pdbs) > 0
+ def populate_symstore(self, tmp):
+ """
+ Mock local symstore directory tree and fill in build artifacts:
+ * tmp/test/<exe>
+ * tmp/server/<pdb>/<key>/<pdb>
+ """
binary_name = "a.out"
pdb_name = "a.pdb"
key = self.symstore_key(binary_name)
if key is None:
- self.skipTest("Could not obtain a 20-byte PDB UUID from the binary")
+ self.skipTest("Binary has no valid UUID for PDB")
- # Set up test directory with just the binary (no PDB).
+ # Move exe to isolated directory
test_dir = os.path.join(tmp, "test")
os.makedirs(test_dir)
shutil.move(self.getBuildArtifact(binary_name), test_dir)
self.aout = os.path.join(test_dir, binary_name)
- # SymStore directory tree: <pdb>/<key>/<pdb>
+ # Move PDB to SymStore directory
server_dir = os.path.join(tmp, "server")
pdb_key_dir = os.path.join(server_dir, pdb_name, key)
os.makedirs(pdb_key_dir)
@@ -89,15 +94,17 @@ def symstore_key(self, exe):
except Exception:
return None
- # TODO: Check on other platforms, it should work in theory
- @skipUnlessPlatform(["windows"])
- def test_local_folder(self):
- """Check that LLDB can fetch PDB from local SymStore directory"""
+ # TODO: Add a test that fails if we don't set the URL
+ def test_basic(self):
+ """Check that breakpoint hits if LLDB fetches PDB from local SymStore"""
+ if not self.build_inferior_with_pdb():
+ self.skipTest("Build did not produce a PDB file")
+
tmp_dir = tempfile.mkdtemp()
symstore_dir = self.populate_symstore(tmp_dir)
self.runCmd(
- "settings set plugin.symbol-locator.microsoft.symstore-urls %s"
+ "settings set plugin.symbol-locator.symstore.urls %s"
% symstore_dir.replace("\\", "/")
)
diff --git a/lldb/test/API/microsoft_symsrv/main.c b/lldb/test/API/symstore/PDB/main.c
similarity index 100%
rename from lldb/test/API/microsoft_symsrv/main.c
rename to lldb/test/API/symstore/PDB/main.c
>From 96ff05a5c6c1e326414308706af0c55828f51f7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 15:05:25 +0100
Subject: [PATCH 04/12] Fix formatting (NFC)
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 2 +-
lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 0341249f0da0e..2e5af2f65fde4 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolLocatorSymStore.cpp ---------------------------------------===//
+//===-- SymbolLocatorSymStore.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py b/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
index 370c3000690bf..7605af7c8d8f2 100644
--- a/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
+++ b/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
@@ -14,6 +14,7 @@
debug info in a PDB file with clang.
"""
+
class SymStoreLocalPDBTests(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@@ -99,7 +100,7 @@ def test_basic(self):
"""Check that breakpoint hits if LLDB fetches PDB from local SymStore"""
if not self.build_inferior_with_pdb():
self.skipTest("Build did not produce a PDB file")
-
+
tmp_dir = tempfile.mkdtemp()
symstore_dir = self.populate_symstore(tmp_dir)
>From 53ba121854a8326159d8b4e1df777b66cc033bd9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 18:35:11 +0100
Subject: [PATCH 05/12] Update
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
index 551b774dc9f3a..7b54f7c4f8765 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
@@ -1,4 +1,4 @@
-//===-- SymbolLocatorSymStore.h ---------------------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 1bc7692f27628601e362c05282d2f6951f6bbd18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 18:35:31 +0100
Subject: [PATCH 06/12] Update
lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 2e169bb6e8a53..cd87e5cfcd2c3 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -1112,7 +1112,7 @@ 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)) {
- // Ignore corrupt DebugInfo sections
+ // Ignore corrupt DebugInfo sections.
llvm::consumeError(std::move(Err));
return std::nullopt;
}
>From 655b28a8a69db423412a0c4a0fa1d244239a541f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 18:38:21 +0100
Subject: [PATCH 07/12] Update
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 2e5af2f65fde4..5d1ee6bc6bb90 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -134,9 +134,8 @@ std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
// FIXME: We need this for the test executable, because it is loaded as DWARF
if (!llvm::StringRef(pdb_name).ends_with(".pdb")) {
auto last_dot = pdb_name.find_last_of('.');
- if (last_dot != llvm::StringRef::npos) {
+ if (last_dot != llvm::StringRef::npos)
pdb_name = pdb_name.substr(0, last_dot);
- }
pdb_name += ".pdb";
}
>From 2e762ca384f91aeb602e332815c8ec55a1f9387d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 18:38:45 +0100
Subject: [PATCH 08/12] Update
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 5d1ee6bc6bb90..6816fdc74896a 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -65,7 +65,7 @@ static PluginProperties &GetGlobalPluginProperties() {
SymbolLocatorSymStore::SymbolLocatorSymStore() : SymbolLocator() {}
void SymbolLocatorSymStore::Initialize() {
- // First version can only locate PDB in local SymStore (no download yet)
+ // First version can only locate PDB in local SymStore (no download yet).
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
nullptr, LocateExecutableSymbolFile, nullptr, nullptr,
>From 9ec4f08afdc993f46eafef25b8fa98d06ffad276 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 25 Feb 2026 19:01:33 +0100
Subject: [PATCH 09/12] Update
lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 6816fdc74896a..f1e0c27c5a012 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolLocatorSymStore.cpp -----------------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 45f41d87ef576d8e5b420d115e55179d7ccb7862 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Fri, 27 Feb 2026 12:24:56 +0100
Subject: [PATCH 10/12] Address minor comments
---
lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index cd87e5cfcd2c3..ad2a0ff3da808 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -1117,10 +1117,11 @@ std::optional<FileSpec> ObjectFilePECOFF::GetPDBPath() {
return std::nullopt;
}
if (pdb_file.empty()) {
- // No DebugInfo section
+ // No DebugInfo section present.
return std::nullopt;
}
- return FileSpec(pdb_file);
+ return FileSpec(pdb_file, FileSpec::GuessPathStyle(pdb_file).value_or(
+ FileSpec::Style::native));
}
uint32_t ObjectFilePECOFF::ParseDependentModules() {
>From 17a2effa783689b246b5c6da7e008196ef508ec0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Fri, 27 Feb 2026 12:27:31 +0100
Subject: [PATCH 11/12] Address fixme, add failing test-case, turn into
debuginfo test with PDB (only)
---
.../SymStore/SymbolLocatorSymStore.cpp | 8 --
lldb/test/API/symstore/{PDB => }/Makefile | 2 +
.../API/symstore/PDB/TestSymStoreLocalPDB.py | 113 ------------------
lldb/test/API/symstore/TestSymStoreLocal.py | 113 ++++++++++++++++++
lldb/test/API/symstore/{PDB => }/main.c | 0
5 files changed, 115 insertions(+), 121 deletions(-)
rename lldb/test/API/symstore/{PDB => }/Makefile (71%)
delete mode 100644 lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
create mode 100644 lldb/test/API/symstore/TestSymStoreLocal.py
rename lldb/test/API/symstore/{PDB => }/main.c (100%)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index f1e0c27c5a012..4655cd457f516 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -131,14 +131,6 @@ std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
return {};
}
- // FIXME: We need this for the test executable, because it is loaded as DWARF
- if (!llvm::StringRef(pdb_name).ends_with(".pdb")) {
- auto last_dot = pdb_name.find_last_of('.');
- if (last_dot != llvm::StringRef::npos)
- pdb_name = pdb_name.substr(0, last_dot);
- pdb_name += ".pdb";
- }
-
std::string key = formatSymStoreKey(uuid);
Args sym_store_urls = GetGlobalPluginProperties().GetURLs();
for (const Args::ArgEntry &url : sym_store_urls) {
diff --git a/lldb/test/API/symstore/PDB/Makefile b/lldb/test/API/symstore/Makefile
similarity index 71%
rename from lldb/test/API/symstore/PDB/Makefile
rename to lldb/test/API/symstore/Makefile
index c9319d6e6888a..6279aee698dad 100644
--- a/lldb/test/API/symstore/PDB/Makefile
+++ b/lldb/test/API/symstore/Makefile
@@ -1,2 +1,4 @@
+MAKE_PDB := YES
+
C_SOURCES := main.c
include Makefile.rules
diff --git a/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py b/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
deleted file mode 100644
index 7605af7c8d8f2..0000000000000
--- a/lldb/test/API/symstore/PDB/TestSymStoreLocalPDB.py
+++ /dev/null
@@ -1,113 +0,0 @@
-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. We populate the
-respective file structure in a temporary directory and run LLDB on it. This is
-supposed to work cross-platform. The test can run on all platforms that can link
-debug info in a PDB file with clang.
-"""
-
-
-class SymStoreLocalPDBTests(TestBase):
- NO_DEBUG_INFO_TESTCASE = True
-
- def try_breakpoint(self, should_have_loc):
- target = self.dbg.CreateTarget(self.aout)
- 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)
-
- loc = bp.GetLocationAtIndex(0)
- self.assertTrue(loc and loc.IsValid(), "Location is valid")
- addr = loc.GetAddress()
- self.assertTrue(addr and addr.IsValid(), "Loc address is valid")
- line_entry = addr.GetLineEntry()
- self.assertEqual(
- should_have_loc,
- line_entry is not None and line_entry.IsValid(),
- "Loc line entry validity",
- )
- if should_have_loc:
- self.assertEqual(line_entry.GetLine(), 2)
- self.assertEqual(
- line_entry.GetFileSpec().GetFilename(),
- self.main_source_file.GetFilename(),
- )
- self.dbg.DeleteTarget(target)
-
- def build_inferior_with_pdb(self):
- self.main_source_file = lldb.SBFileSpec("main.c")
- self.build()
- pdbs = glob.glob(os.path.join(self.getBuildDir(), "*.pdb"))
- return len(pdbs) > 0
-
- def populate_symstore(self, tmp):
- """
- Mock local symstore directory tree and fill in build artifacts:
- * tmp/test/<exe>
- * tmp/server/<pdb>/<key>/<pdb>
- """
- binary_name = "a.out"
- pdb_name = "a.pdb"
- key = self.symstore_key(binary_name)
- if key is None:
- self.skipTest("Binary has no valid UUID for PDB")
-
- # Move exe to isolated directory
- test_dir = os.path.join(tmp, "test")
- os.makedirs(test_dir)
- shutil.move(self.getBuildArtifact(binary_name), test_dir)
- self.aout = os.path.join(test_dir, binary_name)
-
- # Move PDB to SymStore directory
- server_dir = os.path.join(tmp, "server")
- pdb_key_dir = os.path.join(server_dir, pdb_name, key)
- os.makedirs(pdb_key_dir)
- shutil.move(
- self.getBuildArtifact(pdb_name),
- os.path.join(pdb_key_dir, pdb_name),
- )
-
- return server_dir
-
- def symstore_key(self, exe):
- """Load module UUID like: 12345678-1234-5678-9ABC-DEF012345678-00000001
- and transform to SymStore key: 12345678123456789ABCDEF0123456781"""
- try:
- spec = lldb.SBModuleSpec()
- spec.SetFileSpec(lldb.SBFileSpec(self.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
-
- # TODO: Add a test that fails if we don't set the URL
- def test_basic(self):
- """Check that breakpoint hits if LLDB fetches PDB from local SymStore"""
- if not self.build_inferior_with_pdb():
- self.skipTest("Build did not produce a PDB file")
-
- tmp_dir = tempfile.mkdtemp()
- symstore_dir = self.populate_symstore(tmp_dir)
-
- self.runCmd(
- "settings set plugin.symbol-locator.symstore.urls %s"
- % symstore_dir.replace("\\", "/")
- )
-
- self.try_breakpoint(should_have_loc=True)
- shutil.rmtree(tmp_dir)
diff --git a/lldb/test/API/symstore/TestSymStoreLocal.py b/lldb/test/API/symstore/TestSymStoreLocal.py
new file mode 100644
index 0000000000000..e759ed78d10b3
--- /dev/null
+++ b/lldb/test/API/symstore/TestSymStoreLocal.py
@@ -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")
+ 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(self):
+ """
+ Check that breakpoint doesn't hit without SymStore.
+ """
+ exe, sym = self.build_inferior()
+ with MockedSymStore(self, exe, sym):
+ self.try_breakpoint(exe, should_have_loc=False)
+
+ def test_basic(self):
+ """
+ Check that breakpoint hits with local SymStore.
+ """
+ exe, sym = self.build_inferior()
+ with MockedSymStore(self, exe, sym) as symstore_dir:
+ self.runCmd(
+ "settings set plugin.symbol-locator.symstore.urls %s" % symstore_dir
+ )
+ self.try_breakpoint(exe, should_have_loc=True)
diff --git a/lldb/test/API/symstore/PDB/main.c b/lldb/test/API/symstore/main.c
similarity index 100%
rename from lldb/test/API/symstore/PDB/main.c
rename to lldb/test/API/symstore/main.c
>From adca824523faae61173dc6030cee0beb08ad73db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 2 Mar 2026 09:53:05 +0100
Subject: [PATCH 12/12] Address feedback
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 2 +-
lldb/test/API/symstore/Makefile | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 4655cd457f516..71290951db751 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -88,7 +88,7 @@ void SymbolLocatorSymStore::Terminate() {
}
llvm::StringRef SymbolLocatorSymStore::GetPluginDescriptionStatic() {
- return "Symbol locator for PDB in SymStore SymStore";
+ return "Symbol locator for PDB in SymStore";
}
SymbolLocator *SymbolLocatorSymStore::CreateInstance() {
diff --git a/lldb/test/API/symstore/Makefile b/lldb/test/API/symstore/Makefile
index 6279aee698dad..c9319d6e6888a 100644
--- a/lldb/test/API/symstore/Makefile
+++ b/lldb/test/API/symstore/Makefile
@@ -1,4 +1,2 @@
-MAKE_PDB := YES
-
C_SOURCES := main.c
include Makefile.rules
More information about the lldb-commits
mailing list