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?= <[email protected]> Date: Mon, 23 Feb 2026 13:52:42 +0100 Subject: [PATCH 01/14] 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?= <[email protected]> Date: Wed, 25 Feb 2026 12:09:28 +0100 Subject: [PATCH 02/14] 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?= <[email protected]> Date: Wed, 25 Feb 2026 12:57:58 +0100 Subject: [PATCH 03/14] 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?= <[email protected]> Date: Wed, 25 Feb 2026 15:05:25 +0100 Subject: [PATCH 04/14] 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?= <[email protected]> Date: Wed, 25 Feb 2026 18:35:11 +0100 Subject: [PATCH 05/14] Update lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h Co-authored-by: Jonas Devlieghere <[email protected]> --- .../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?= <[email protected]> Date: Wed, 25 Feb 2026 18:35:31 +0100 Subject: [PATCH 06/14] Update lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp Co-authored-by: Jonas Devlieghere <[email protected]> --- 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?= <[email protected]> Date: Wed, 25 Feb 2026 18:38:21 +0100 Subject: [PATCH 07/14] Update lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp Co-authored-by: Jonas Devlieghere <[email protected]> --- .../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?= <[email protected]> Date: Wed, 25 Feb 2026 18:38:45 +0100 Subject: [PATCH 08/14] Update lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp Co-authored-by: Jonas Devlieghere <[email protected]> --- .../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?= <[email protected]> Date: Wed, 25 Feb 2026 19:01:33 +0100 Subject: [PATCH 09/14] Update lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp Co-authored-by: Jonas Devlieghere <[email protected]> --- .../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?= <[email protected]> Date: Fri, 27 Feb 2026 12:24:56 +0100 Subject: [PATCH 10/14] 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?= <[email protected]> Date: Fri, 27 Feb 2026 12:27:31 +0100 Subject: [PATCH 11/14] 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?= <[email protected]> Date: Mon, 2 Mar 2026 09:53:05 +0100 Subject: [PATCH 12/14] 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 From 6911da9319ec9b0053ae80163c20989bafea3c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <[email protected]> Date: Mon, 2 Mar 2026 10:45:42 +0100 Subject: [PATCH 13/14] Log corrupt debug info in GetPDBPath() --- .../Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index ad2a0ff3da808..cec47d96b33d2 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -1112,8 +1112,13 @@ 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)); + // 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()) { From 5a119aa005b4743974fc67e64c60253884ee9ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <[email protected]> Date: Mon, 2 Mar 2026 12:54:50 +0100 Subject: [PATCH 14/14] Re-introduce MAKE_PDB in test Makefile --- lldb/test/API/symstore/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/test/API/symstore/Makefile b/lldb/test/API/symstore/Makefile index c9319d6e6888a..6279aee698dad 100644 --- a/lldb/test/API/symstore/Makefile +++ b/lldb/test/API/symstore/Makefile @@ -1,2 +1,4 @@ +MAKE_PDB := YES + C_SOURCES := main.c include Makefile.rules _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
