[Lldb-commits] [lldb] [lldb] Add caching and _NT_SYMBOL_PATH parsing in SymbolLocatorSymStore (PR #191782)
Stefan Gränitz via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 14 03:24:48 PDT 2026
https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/191782
>From b6c01d870a5fdea8a78e074a4b5906b525547641 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 10:53:55 +0200
Subject: [PATCH 1/9] [lldb] Add caching and _NT_SYMBOL_PATH parsing in
SymbolLocatorSymStore
---
.../SymStore/SymbolLocatorSymStore.cpp | 220 ++++++++++++++++--
.../SymStore/SymbolLocatorSymStore.h | 7 +
.../SymbolLocatorSymStoreProperties.td | 3 +
lldb/test/API/symstore/TestSymStore.py | 56 ++++-
lldb/unittests/Symbol/CMakeLists.txt | 2 +
lldb/unittests/Symbol/SymStoreTest.cpp | 108 +++++++++
6 files changed, 378 insertions(+), 18 deletions(-)
create mode 100644 lldb/unittests/Symbol/SymStoreTest.cpp
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 41b15c6725a26..3d0e6243f4d6d 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -58,6 +58,25 @@ class PluginProperties : public Properties {
m_collection_sp->GetPropertyAtIndexAsArgs(ePropertySymStoreURLs, urls);
return urls;
}
+
+ std::string GetCachePath() const {
+ OptionValueString *s =
+ m_collection_sp->GetPropertyAtIndexAsOptionValueString(
+ ePropertyCachePath);
+ if (s && !s->GetCurrentValueAsRef().empty())
+ return s->GetCurrentValue();
+ // Fall back to the platform cache directory.
+ llvm::SmallString<128> cache_dir;
+ if (llvm::sys::path::cache_directory(cache_dir)) {
+ llvm::sys::path::append(cache_dir, "lldb", "symstore");
+ return cache_dir.str().str();
+ }
+ // Last resort: use a subdirectory of the system temp directory.
+ constexpr bool erase_on_reboot = false;
+ llvm::sys::path::system_temp_directory(erase_on_reboot, cache_dir);
+ llvm::sys::path::append(cache_dir, "lldb", "symstore");
+ return cache_dir.str().str();
+ }
};
} // namespace
@@ -103,6 +122,61 @@ SymbolLocator *SymbolLocatorSymStore::CreateInstance() {
namespace {
+SymbolLocatorSymStore::LookupEntry make_lookup_entry(llvm::StringRef source) {
+ SymbolLocatorSymStore::LookupEntry entry;
+ entry.source = source.str();
+ entry.cache = std::nullopt;
+ return entry;
+}
+
+SymbolLocatorSymStore::LookupEntry make_lookup_entry(llvm::StringRef source,
+ llvm::StringRef cache) {
+ SymbolLocatorSymStore::LookupEntry entry;
+ entry.source = source.str();
+ entry.cache = cache.str();
+ return entry;
+}
+
+std::vector<SymbolLocatorSymStore::LookupEntry> getGlobalLookupOrder() {
+ std::vector<SymbolLocatorSymStore::LookupEntry> result;
+
+ for (const auto &url : GetGlobalPluginProperties().GetURLs())
+ result.push_back(make_lookup_entry(url.ref()));
+
+ const char *sym_path = std::getenv("_NT_SYMBOL_PATH");
+ for (auto entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(sym_path))
+ result.push_back(std::move(entry));
+
+ const char *alt_path = std::getenv("_NT_ALT_SYMBOL_PATH");
+ for (auto entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(alt_path))
+ result.push_back(std::move(entry));
+
+ return result;
+}
+
+std::optional<SymbolLocatorSymStore::LookupEntry>
+ParseSrvEntry(llvm::StringRef entry) {
+ llvm::SmallVector<llvm::StringRef, 4> parts;
+ entry.trim().split(parts, '*');
+ switch (parts.size()) {
+ case 2:
+ return make_lookup_entry(parts[1]);
+ case 3:
+ return make_lookup_entry(parts[2], parts[1]);
+ default:
+ return {}; // Ignore entries with invalid number of parts.
+ }
+}
+
+std::optional<std::string> ParseCacheEntry(llvm::StringRef entry) {
+ llvm::SmallVector<llvm::StringRef, 2> parts;
+ entry.trim().split(parts, '*');
+ // Ignore entries with invalid number of parts.
+ if (parts.size() != 2)
+ return {};
+ return parts.back().str();
+}
+
// RSDS entries store identity as a 20-byte UUID composed of 16-byte GUID and
// 4-byte age:
// 12345678-1234-5678-9ABC-DEF012345678-00000001
@@ -133,8 +207,6 @@ bool HasUnsafeCharacters(llvm::StringRef s) {
return s == "." || s == "..";
}
-// TODO: This is a dumb initial implementation: It always downloads the file and
-// doesn't validate the result.
std::optional<FileSpec>
RequestFileFromSymStoreServerHTTP(llvm::StringRef base_url, llvm::StringRef key,
llvm::StringRef pdb_name) {
@@ -151,11 +223,9 @@ RequestFileFromSymStoreServerHTTP(llvm::StringRef base_url, llvm::StringRef key,
// Download into a temporary file. Cache coming soon.
llvm::SmallString<128> tmp_file;
- std::string tmp_file_name =
- llvm::formatv("lldb_symstore_{0}_{1}", key, pdb_name);
constexpr bool erase_on_reboot = true;
path::system_temp_directory(erase_on_reboot, tmp_file);
- path::append(tmp_file, tmp_file_name);
+ path::append(tmp_file, llvm::formatv("lldb_symstore_{0}_{1}", key, pdb_name));
// Server has SymStore directory structure with forward slashes as separators.
std::string source_url =
@@ -223,16 +293,86 @@ std::optional<FileSpec> FindFileInLocalSymStore(llvm::StringRef root_dir,
return spec;
}
-std::optional<FileSpec> LocateSymStoreEntry(llvm::StringRef base_url,
+std::optional<FileSpec> MoveToLocalSymStore(llvm::StringRef cache,
llvm::StringRef key,
- llvm::StringRef pdb_name) {
- if (base_url.starts_with("http://") || base_url.starts_with("https://"))
- return RequestFileFromSymStoreServerHTTP(base_url, key, pdb_name);
+ llvm::StringRef pdb_name,
+ FileSpec tmp_file) {
+ // Caches have SymStore directory structure: cache/pdb_name/key/pdb_name
+ llvm::SmallString<256> dest_dir;
+ llvm::sys::path::append(dest_dir, cache, pdb_name, key);
+ if (std::error_code ec = llvm::sys::fs::create_directories(dest_dir)) {
+ Debugger::ReportWarning(
+ llvm::formatv("failed to create SymStore cache directory '{0}': {1}",
+ dest_dir, ec.message()));
+ return tmp_file;
+ }
+
+ llvm::SmallString<256> dest;
+ llvm::sys::path::append(dest, dest_dir, pdb_name);
+ std::error_code ec = llvm::sys::fs::rename(tmp_file.GetPath(), dest);
+
+ // Fall back to copy+delete if we move to a different volume.
+ if (ec == std::errc::cross_device_link) {
+ ec = llvm::sys::fs::copy_file(tmp_file.GetPath(), dest);
+ if (!ec)
+ llvm::sys::fs::remove(tmp_file.GetPath());
+ }
+ if (ec) {
+ Debugger::ReportWarning(
+ llvm::formatv("failed to move '{0}' to SymStore cache '{1}': {2}",
+ tmp_file.GetPath(), dest, ec.message()));
+ return tmp_file;
+ }
+
+ return FileSpec(dest.str());
+}
+
+std::optional<FileSpec>
+LocateSymStoreEntry(const SymbolLocatorSymStore::LookupEntry &entry,
+ llvm::StringRef key, llvm::StringRef pdb_name) {
+ Log *log = GetLog(LLDBLog::Symbols);
+ std::string default_cache = GetGlobalPluginProperties().GetCachePath();
+
+ llvm::StringRef url = entry.source;
+ if (url.starts_with("http://") || url.starts_with("https://")) {
+ // Check cache first.
+ if (entry.cache) {
+ if (auto spec = FindFileInLocalSymStore(*entry.cache, key, pdb_name)) {
+ LLDB_LOG_VERBOSE(log, "Found {0} in SymStore cache {1}", pdb_name,
+ *entry.cache);
+ return *spec;
+ }
+ } else {
+ // Check LLDB default cache to avoid duplicate downloads in the same
+ // session.
+ if (auto spec = FindFileInLocalSymStore(default_cache, key, pdb_name)) {
+ LLDB_LOG_VERBOSE(log, "Found {0} in SymStore cache {1}", pdb_name,
+ default_cache);
+ return *spec;
+ }
+ }
+
+ // Download and move to cache.
+ if (auto spec = RequestFileFromSymStoreServerHTTP(url, key, pdb_name)) {
+ LLDB_LOG_VERBOSE(log, "Downloaded {0} from SymStore {1}", pdb_name, url);
+ std::string cache = entry.cache.value_or(default_cache);
+ spec = MoveToLocalSymStore(cache, key, pdb_name, *spec);
+ LLDB_LOG_VERBOSE(log, "Added {0} to SymStore cache {1}", pdb_name, cache);
+ return *spec;
+ }
- if (base_url.starts_with("file://"))
- base_url = base_url.drop_front(7);
+ return {};
+ }
- return FindFileInLocalSymStore(base_url, key, pdb_name);
+ llvm::StringRef file = entry.source;
+ if (file.starts_with("file://"))
+ file = file.drop_front(7);
+ if (auto spec = FindFileInLocalSymStore(file, key, pdb_name)) {
+ LLDB_LOG_VERBOSE(log, "Found {0} in local SymStore {1}", pdb_name, file);
+ return *spec;
+ }
+
+ return {};
}
} // namespace
@@ -261,13 +401,59 @@ std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
}
std::string key = FormatSymStoreKey(uuid);
- Args sym_store_urls = GetGlobalPluginProperties().GetURLs();
- for (const Args::ArgEntry &url : sym_store_urls) {
- if (auto spec = LocateSymStoreEntry(url.ref(), key, pdb_name)) {
- LLDB_LOG_VERBOSE(log, "Found {0} in SymStore {1}", pdb_name, url.ref());
+ for (const LookupEntry &entry : getGlobalLookupOrder()) {
+ if (auto spec = LocateSymStoreEntry(entry, key, pdb_name))
return *spec;
- }
}
return {};
}
+
+std::vector<SymbolLocatorSymStore::LookupEntry>
+SymbolLocatorSymStore::ParseEnvSymbolPaths(llvm::StringRef val) {
+ if (val.empty())
+ return {};
+
+ std::vector<LookupEntry> result;
+ std::optional<std::string> implicit_cache;
+ llvm::SmallVector<llvm::StringRef, 2> entries;
+ val.split(entries, ';');
+
+ for (llvm::StringRef raw : entries) {
+ llvm::StringRef entry = raw.trim();
+ if (entry.empty())
+ continue;
+
+ // Explicit cache directives apply to all subsequent srv* entries that don't
+ // set their own explicit cache.
+ if (entry.starts_with_insensitive("cache*")) {
+ if (auto cache = ParseCacheEntry(entry))
+ implicit_cache = *cache;
+ continue;
+ }
+
+ // SymStore directives with explicit interpreters are unsupported
+ // explicitly.
+ if (entry.starts_with_insensitive("symsrv*")) {
+ Debugger::ReportWarning(
+ llvm::formatv("ignoring unsupported entry in env: {0}", entry));
+ continue;
+ }
+
+ // SymStore server directives may include an explicit cache.
+ // Format is: srv*[LocalCache*]SymbolStore
+ if (entry.starts_with_insensitive("srv*")) {
+ if (auto lookup_entry = ParseSrvEntry(entry)) {
+ if (!lookup_entry->cache && implicit_cache)
+ lookup_entry->cache = implicit_cache;
+ result.push_back(*lookup_entry);
+ }
+ continue;
+ }
+
+ // Plain local paths aren't cached.
+ result.push_back(make_lookup_entry(entry));
+ }
+
+ return result;
+}
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
index 52ec04cae387b..de2a1c6b9bdd5 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
@@ -43,6 +43,13 @@ class SymbolLocatorSymStore : public SymbolLocator {
static std::optional<FileSpec>
LocateExecutableSymbolFile(const ModuleSpec &module_spec,
const FileSpecList &default_search_paths);
+
+ struct LookupEntry {
+ std::string source;
+ std::optional<std::string> cache;
+ };
+
+ static std::vector<LookupEntry> ParseEnvSymbolPaths(llvm::StringRef val);
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
index 0cd631a80b90b..337f570b2ec7e 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStoreProperties.td
@@ -4,4 +4,7 @@ let Definition = "symbollocatorsymstore", Path = "plugin.symbol-locator.symstore
def SymStoreURLs : Property<"urls", "Array">,
ElementType<"String">,
Desc<"List of local symstore directories to query for symbols">;
+ def CachePath : Property<"cache", "String">,
+ DefaultStringValue<"">,
+ Desc<"Default cache directory for downloaded symbol files. Used when no cache is specified in _NT_SYMBOL_PATH.">;
}
diff --git a/lldb/test/API/symstore/TestSymStore.py b/lldb/test/API/symstore/TestSymStore.py
index 5baa5fa4d0da8..6af45dbe7e56c 100644
--- a/lldb/test/API/symstore/TestSymStore.py
+++ b/lldb/test/API/symstore/TestSymStore.py
@@ -66,6 +66,26 @@ def __exit__(self, *exc_info):
self._test.runCmd("settings clear plugin.symbol-locator.symstore")
+class NtSymbolPath:
+ """
+ Context Manager to temporarily set the _NT_SYMBOL_PATH environment variable.
+ """
+
+ def __init__(self, value):
+ self._value = value
+ self._saved = None
+
+ def __enter__(self):
+ self._saved = os.environ.get("_NT_SYMBOL_PATH")
+ os.environ["_NT_SYMBOL_PATH"] = self._value
+
+ def __exit__(self, *exc_info):
+ if self._saved is None:
+ os.environ.pop("_NT_SYMBOL_PATH", None)
+ else:
+ os.environ["_NT_SYMBOL_PATH"] = self._saved
+
+
class HTTPServer:
"""
Context Manager to serve a local directory tree via HTTP.
@@ -162,10 +182,44 @@ def test_http_not_found(self):
# certs, non-HTTPS redirects, etc.
def test_http(self):
"""
- Check that breakpoint hits with remote SymStore.
+ Check that breakpoint resolves with remote SymStore.
"""
exe, sym = self.build_inferior()
with MockedSymStore(self, exe, sym) as dir:
with HTTPServer(dir) as url:
self.runCmd(f"settings set plugin.symbol-locator.symstore.urls {url}")
self.try_breakpoint(exe, should_have_loc=True)
+
+ def test_nt_symbol_path_local(self):
+ """
+ Check that breakpoint resolves with a local SymStore path in
+ _NT_SYMBOL_PATH, and that the PDB is not copied to the cache.
+ """
+ exe, sym = self.build_inferior()
+ cache_dir = self.getBuildArtifact("cache")
+ symstore = MockedSymStore(self, exe, sym)
+ with symstore as dir:
+ self.runCmd(
+ f"settings set plugin.symbol-locator.symstore.cache {cache_dir}"
+ )
+ with NtSymbolPath(dir):
+ self.try_breakpoint(exe, should_have_loc=True)
+ self.assertFalse(any(files for _, _, files in os.walk(cache_dir)))
+
+ def test_nt_symbol_path_srv(self):
+ """
+ Check that breakpoint resolves with an HTTP symbol server in
+ _NT_SYMBOL_PATH using the srv* syntax, and that the PDB is cached.
+ """
+ exe, sym = self.build_inferior()
+ cache_dir = self.getBuildArtifact("cache")
+ symstore = MockedSymStore(self, exe, sym)
+ with symstore as dir:
+ self.runCmd(
+ f"settings set plugin.symbol-locator.symstore.cache {cache_dir}"
+ )
+ with HTTPServer(dir) as url:
+ with NtSymbolPath(f"srv*{url}"):
+ self.try_breakpoint(exe, should_have_loc=True)
+ key = symstore.get_key_pdb(exe)
+ self.assertTrue(os.path.isfile(os.path.join(cache_dir, sym, key, sym)))
diff --git a/lldb/unittests/Symbol/CMakeLists.txt b/lldb/unittests/Symbol/CMakeLists.txt
index 5664c21adbe3f..f9794369a89f4 100644
--- a/lldb/unittests/Symbol/CMakeLists.txt
+++ b/lldb/unittests/Symbol/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_unittest(SymbolTests
PostfixExpressionTest.cpp
SymbolTest.cpp
SymtabTest.cpp
+ SymStoreTest.cpp
TestTypeSystem.cpp
TestTypeSystemClang.cpp
TestClangASTImporter.cpp
@@ -24,6 +25,7 @@ add_lldb_unittest(SymbolTests
lldbPluginSymbolFileDWARF
lldbPluginSymbolFileSymtab
lldbPluginTypeSystemClang
+ lldbPluginSymbolLocatorSymStore
LLVMTestingSupport
)
diff --git a/lldb/unittests/Symbol/SymStoreTest.cpp b/lldb/unittests/Symbol/SymStoreTest.cpp
new file mode 100644
index 0000000000000..b08cdadf74400
--- /dev/null
+++ b/lldb/unittests/Symbol/SymStoreTest.cpp
@@ -0,0 +1,108 @@
+//===-- SymbolsTest.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 "gtest/gtest.h"
+
+#include "Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h"
+
+using namespace lldb_private;
+using LookupEntry = SymbolLocatorSymStore::LookupEntry;
+
+TEST(SymStoreTest, ParseEnvSymbolPaths_Srv) {
+ auto check = [](const char *str) {
+ std::vector<std::string> sources;
+ for (LookupEntry entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(str))
+ sources.push_back(std::move(entry.source));
+ return sources;
+ };
+ auto returns = [](auto... strs) { return std::vector<std::string>{strs...}; };
+
+ // Local paths
+ EXPECT_EQ(check(""), returns());
+ EXPECT_EQ(check("C:\\ProgramData\\Symbols"),
+ returns("C:\\ProgramData\\Symbols"));
+ EXPECT_EQ(check("C:\\symbols;\\\\buildserver\\syms;file://D:/pdb"),
+ returns("C:\\symbols", "\\\\buildserver\\syms", "file://D:/pdb"));
+
+ // Symbol servers
+ EXPECT_EQ(check("srv*https://msdl.microsoft.com/download/symbols"),
+ returns("https://msdl.microsoft.com/download/symbols"));
+ EXPECT_EQ(check("Srv*https://msdl.microsoft.com/download/symbols"),
+ returns("https://msdl.microsoft.com/download/symbols"));
+ EXPECT_EQ(check("SRV*http://localhost"), returns("http://localhost"));
+
+ // Symbol servers and local paths with caches
+ EXPECT_EQ(check("SRV*C:\\symcache*\\\\corp\\symbols"),
+ returns("\\\\corp\\symbols"));
+ EXPECT_EQ(check("D:\\sym;srv*C:\\symcache*D:\\sym"),
+ returns("D:\\sym", "D:\\sym"));
+ EXPECT_EQ(check("srv**https://symbols.mozilla.org"),
+ returns("https://symbols.mozilla.org"));
+
+ // Symbol server with custom implementation (unsupported)
+ EXPECT_EQ(check("symsrv*symsrv.dll*https://symbols.mozilla.org"), returns());
+ EXPECT_EQ(check("symsrv*symsrv.dll*C:\\symbols*https://symbols.mozilla.org"),
+ returns());
+ EXPECT_EQ(check("symsrv*https://symbols.mozilla.org;D:\\sym"),
+ returns("D:\\sym"));
+
+ // Partially invalid specs
+ EXPECT_EQ(check("srv*;;D:\\sym;SRV*"), returns("", "D:\\sym", ""));
+ EXPECT_EQ(check("srv*D:\\1*D:\\2*D:\\3;D:\\sym"), returns("D:\\sym"));
+ EXPECT_EQ(check("symsrv*D:\\1;D:\\sym"), returns("D:\\sym"));
+}
+
+TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
+ auto check = [](const char *str) {
+ std::vector<std::string> caches;
+ for (LookupEntry entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(str))
+ if (entry.cache)
+ caches.push_back(std::move(*entry.cache));
+ return caches;
+ };
+ auto returns = [](auto... strs) { return std::vector<std::string>{strs...}; };
+
+ // No caches
+ EXPECT_EQ(check(""), returns());
+ EXPECT_EQ(check("C:\\ProgramData\\Symbols"), returns());
+ EXPECT_EQ(check("C:\\symbols;\\\\buildserver\\syms;file://D:/pdb"),
+ returns());
+ EXPECT_EQ(check("SRV*http://localhost"), returns());
+
+ // No cache without a server
+ EXPECT_EQ(check("cache*C:\\symcache"), returns());
+ EXPECT_EQ(check("cache*C:\\symcache;D:\\sym"), returns());
+
+ // Explicit caches for symbol servers
+ EXPECT_EQ(check("SRV*C:\\symcache*\\\\corp\\symbols"),
+ returns("C:\\symcache"));
+ EXPECT_EQ(check("D:\\sym;srv*C:\\symcache*D:\\sym"), returns("C:\\symcache"));
+ EXPECT_EQ(check("srv**https://symbols.mozilla.org"), returns(""));
+
+ // Implicit caches for following symbol servers
+ EXPECT_EQ(check("cache*D:\\s;srv*\\\\corp"), returns("D:\\s"));
+ EXPECT_EQ(check("CACHE*D:\\s;srv*\\\\corp;SRV*http://localhost"),
+ returns("D:\\s", "D:\\s"));
+ EXPECT_EQ(check("Cache*D:\\s;srv*\\\\corp;SRV*C:\\X*http://localhost"),
+ returns("D:\\s", "C:\\X"));
+ EXPECT_EQ(check("srv*\\\\corp;cache*D:\\s;SRV*C:\\X*http://localhost"),
+ returns("C:\\X"));
+ EXPECT_EQ(check("srv*\\\\corp;SRV*C:\\X*http://localhost;cache*D:\\s"),
+ returns("C:\\X"));
+
+ // Symbol server with custom implementation (unsupported)
+ EXPECT_EQ(check("symsrv*symsrv.dll*https://symbols.mozilla.org"), returns());
+ EXPECT_EQ(check("symsrv*symsrv.dll*C:\\symbols*https://symbols.mozilla.org"),
+ returns());
+
+ // Partially invalid specs
+ EXPECT_EQ(check("cache*C:\\1;;D:\\sym;SRV*"), returns("C:\\1"));
+ EXPECT_EQ(check("cache*C:\\1;srv*D:\\1*D:\\2*D:\\3;srv*D:\\sym"),
+ returns("C:\\1"));
+ EXPECT_EQ(check("cache*C:\\1;symsrv*D:\\1;srv*D:\\sym"), returns("C:\\1"));
+}
>From a82d232e480687a3b3195428b1a34b972092cc99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 18:08:26 +0200
Subject: [PATCH 2/9] Rename make_lookup_entry() -> MakeLookupEntry()
---
.../SymStore/SymbolLocatorSymStore.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index 3d0e6243f4d6d..b3b572bcfa21e 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -122,15 +122,15 @@ SymbolLocator *SymbolLocatorSymStore::CreateInstance() {
namespace {
-SymbolLocatorSymStore::LookupEntry make_lookup_entry(llvm::StringRef source) {
+SymbolLocatorSymStore::LookupEntry MakeLookupEntry(llvm::StringRef source) {
SymbolLocatorSymStore::LookupEntry entry;
entry.source = source.str();
entry.cache = std::nullopt;
return entry;
}
-SymbolLocatorSymStore::LookupEntry make_lookup_entry(llvm::StringRef source,
- llvm::StringRef cache) {
+SymbolLocatorSymStore::LookupEntry MakeLookupEntry(llvm::StringRef source,
+ llvm::StringRef cache) {
SymbolLocatorSymStore::LookupEntry entry;
entry.source = source.str();
entry.cache = cache.str();
@@ -141,7 +141,7 @@ std::vector<SymbolLocatorSymStore::LookupEntry> getGlobalLookupOrder() {
std::vector<SymbolLocatorSymStore::LookupEntry> result;
for (const auto &url : GetGlobalPluginProperties().GetURLs())
- result.push_back(make_lookup_entry(url.ref()));
+ result.push_back(MakeLookupEntry(url.ref()));
const char *sym_path = std::getenv("_NT_SYMBOL_PATH");
for (auto entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(sym_path))
@@ -160,9 +160,9 @@ ParseSrvEntry(llvm::StringRef entry) {
entry.trim().split(parts, '*');
switch (parts.size()) {
case 2:
- return make_lookup_entry(parts[1]);
+ return MakeLookupEntry(parts[1]);
case 3:
- return make_lookup_entry(parts[2], parts[1]);
+ return MakeLookupEntry(parts[2], parts[1]);
default:
return {}; // Ignore entries with invalid number of parts.
}
@@ -452,7 +452,7 @@ SymbolLocatorSymStore::ParseEnvSymbolPaths(llvm::StringRef val) {
}
// Plain local paths aren't cached.
- result.push_back(make_lookup_entry(entry));
+ result.push_back(MakeLookupEntry(entry));
}
return result;
>From c732f6537332c21d2d0d9deb25de34ae522189bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 18:09:30 +0200
Subject: [PATCH 3/9] Rename getGlobalLookupOrder() -> GetGlobalLookupOrder()
---
.../Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index b3b572bcfa21e..ca9a75694dcc4 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -137,7 +137,7 @@ SymbolLocatorSymStore::LookupEntry MakeLookupEntry(llvm::StringRef source,
return entry;
}
-std::vector<SymbolLocatorSymStore::LookupEntry> getGlobalLookupOrder() {
+std::vector<SymbolLocatorSymStore::LookupEntry> GetGlobalLookupOrder() {
std::vector<SymbolLocatorSymStore::LookupEntry> result;
for (const auto &url : GetGlobalPluginProperties().GetURLs())
@@ -401,7 +401,7 @@ std::optional<FileSpec> SymbolLocatorSymStore::LocateExecutableSymbolFile(
}
std::string key = FormatSymStoreKey(uuid);
- for (const LookupEntry &entry : getGlobalLookupOrder()) {
+ for (const LookupEntry &entry : GetGlobalLookupOrder()) {
if (auto spec = LocateSymStoreEntry(entry, key, pdb_name))
return *spec;
}
>From 3cb8481c00c5dedddd57c8e52736a29c942837b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 18:19:51 +0200
Subject: [PATCH 4/9] Unify lookup order for server and cache
---
.../SymbolLocator/SymStore/SymbolLocatorSymStore.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index ca9a75694dcc4..c3389416fd7ec 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -140,9 +140,6 @@ SymbolLocatorSymStore::LookupEntry MakeLookupEntry(llvm::StringRef source,
std::vector<SymbolLocatorSymStore::LookupEntry> GetGlobalLookupOrder() {
std::vector<SymbolLocatorSymStore::LookupEntry> result;
- for (const auto &url : GetGlobalPluginProperties().GetURLs())
- result.push_back(MakeLookupEntry(url.ref()));
-
const char *sym_path = std::getenv("_NT_SYMBOL_PATH");
for (auto entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(sym_path))
result.push_back(std::move(entry));
@@ -151,6 +148,9 @@ std::vector<SymbolLocatorSymStore::LookupEntry> GetGlobalLookupOrder() {
for (auto entry : SymbolLocatorSymStore::ParseEnvSymbolPaths(alt_path))
result.push_back(std::move(entry));
+ for (const auto &url : GetGlobalPluginProperties().GetURLs())
+ result.push_back(MakeLookupEntry(url.ref()));
+
return result;
}
>From 299c37307c95a7a33c137bf6b1bd43e946a180d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 18:45:41 +0200
Subject: [PATCH 5/9] Set local default cache in all API tests to avoid writing
outside the test dir
---
lldb/test/API/symstore/TestSymStore.py | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/lldb/test/API/symstore/TestSymStore.py b/lldb/test/API/symstore/TestSymStore.py
index 6af45dbe7e56c..37ed762497942 100644
--- a/lldb/test/API/symstore/TestSymStore.py
+++ b/lldb/test/API/symstore/TestSymStore.py
@@ -26,6 +26,7 @@ def __init__(self, test, exe, pdb):
self._test = test
self._exe = exe
self._pdb = pdb
+ self.cache_dir = test.getBuildArtifact("cache")
def get_key_pdb(self, exe):
"""
@@ -57,6 +58,9 @@ def __enter__(self):
self._test.getBuildArtifact(self._pdb),
os.path.join(pdb_dir, self._pdb),
)
+ self._test.runCmd(
+ f"settings set plugin.symbol-locator.symstore.cache {self.cache_dir}"
+ )
return symstore_dir
def __exit__(self, *exc_info):
@@ -196,12 +200,9 @@ def test_nt_symbol_path_local(self):
_NT_SYMBOL_PATH, and that the PDB is not copied to the cache.
"""
exe, sym = self.build_inferior()
- cache_dir = self.getBuildArtifact("cache")
symstore = MockedSymStore(self, exe, sym)
with symstore as dir:
- self.runCmd(
- f"settings set plugin.symbol-locator.symstore.cache {cache_dir}"
- )
+ # Symbol path with plain directory
with NtSymbolPath(dir):
self.try_breakpoint(exe, should_have_loc=True)
self.assertFalse(any(files for _, _, files in os.walk(cache_dir)))
@@ -212,12 +213,8 @@ def test_nt_symbol_path_srv(self):
_NT_SYMBOL_PATH using the srv* syntax, and that the PDB is cached.
"""
exe, sym = self.build_inferior()
- cache_dir = self.getBuildArtifact("cache")
symstore = MockedSymStore(self, exe, sym)
with symstore as dir:
- self.runCmd(
- f"settings set plugin.symbol-locator.symstore.cache {cache_dir}"
- )
with HTTPServer(dir) as url:
with NtSymbolPath(f"srv*{url}"):
self.try_breakpoint(exe, should_have_loc=True)
>From 9295f19d0aca0bd4e4cd3e67d6da7cd728e9c2e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 18:46:31 +0200
Subject: [PATCH 6/9] Polish cache checks
---
lldb/test/API/symstore/TestSymStore.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/lldb/test/API/symstore/TestSymStore.py b/lldb/test/API/symstore/TestSymStore.py
index 37ed762497942..2b94a1af455b1 100644
--- a/lldb/test/API/symstore/TestSymStore.py
+++ b/lldb/test/API/symstore/TestSymStore.py
@@ -205,7 +205,11 @@ def test_nt_symbol_path_local(self):
# Symbol path with plain directory
with NtSymbolPath(dir):
self.try_breakpoint(exe, should_have_loc=True)
- self.assertFalse(any(files for _, _, files in os.walk(cache_dir)))
+ # Symbol path with local directory in server notation
+ with NtSymbolPath(f"srv*{dir}"):
+ self.try_breakpoint(exe, should_have_loc=True)
+ cached_files = sum(len(f) for _, _, f in os.walk(symstore.cache_dir))
+ self.assertEqual(cached_files, 0)
def test_nt_symbol_path_srv(self):
"""
@@ -219,4 +223,7 @@ def test_nt_symbol_path_srv(self):
with NtSymbolPath(f"srv*{url}"):
self.try_breakpoint(exe, should_have_loc=True)
key = symstore.get_key_pdb(exe)
- self.assertTrue(os.path.isfile(os.path.join(cache_dir, sym, key, sym)))
+ cache_file = os.path.join(symstore.cache_dir, sym, key, sym)
+ self.assertTrue(os.path.isfile(cache_file))
+ cached_files = sum(len(f) for _, _, f in os.walk(symstore.cache_dir))
+ self.assertEqual(cached_files, 1)
>From caec5ef791e0010d9d87a8050836722989dad1e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 19:13:22 +0200
Subject: [PATCH 7/9] Add test_lookup_order()
---
lldb/test/API/symstore/TestSymStore.py | 30 ++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/lldb/test/API/symstore/TestSymStore.py b/lldb/test/API/symstore/TestSymStore.py
index 2b94a1af455b1..de16220521239 100644
--- a/lldb/test/API/symstore/TestSymStore.py
+++ b/lldb/test/API/symstore/TestSymStore.py
@@ -95,9 +95,10 @@ class HTTPServer:
Context Manager to serve a local directory tree via HTTP.
"""
- def __init__(self, dir):
+ def __init__(self, dir, handler=None):
address = ("localhost", 0) # auto-select free port
- handler = partial(http.server.SimpleHTTPRequestHandler, directory=dir)
+ if handler is None:
+ handler = partial(http.server.SimpleHTTPRequestHandler, directory=dir)
self._server = socketserver.ThreadingTCPServer(address, handler)
self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
@@ -114,6 +115,17 @@ def __exit__(self, *exc_info):
self._thread.join()
+class RequestCounter(http.server.SimpleHTTPRequestHandler):
+ requests = 0 # class-level so all instances share one counter
+
+ def __init__(self, *args, directory=None, **kwargs):
+ super().__init__(*args, directory=directory, **kwargs)
+
+ def do_GET(self):
+ RequestCounter.requests += 1
+ super().do_GET()
+
+
class SymStoreTests(TestBase):
SHARED_BUILD_TESTCASE = False
TEST_WITH_PDB_DEBUG_INFO = True
@@ -227,3 +239,17 @@ def test_nt_symbol_path_srv(self):
self.assertTrue(os.path.isfile(cache_file))
cached_files = sum(len(f) for _, _, f in os.walk(symstore.cache_dir))
self.assertEqual(cached_files, 1)
+
+ def test_lookup_order(self):
+ """
+ Check that _NT_SYMBOL_PATH takes precedence over symstore.urls setting.
+ """
+ exe, sym = self.build_inferior()
+ symstore = MockedSymStore(self, exe, sym)
+ RequestCounter.requests = 0
+ with symstore as dir:
+ with HTTPServer(dir, RequestCounter) as url:
+ self.runCmd(f"settings set plugin.symbol-locator.symstore.urls {url}")
+ with NtSymbolPath(dir):
+ self.try_breakpoint(exe, should_have_loc=True)
+ self.assertEqual(RequestCounter.requests, 0)
>From 2f6b6ceee0041bc1dd23cae57350e2c301f4945a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 23:05:28 +0200
Subject: [PATCH 8/9] Fall back to default system path for empty and invalid
cache strings
---
.../SymStore/SymbolLocatorSymStore.cpp | 53 +++++++++++++------
.../SymStore/SymbolLocatorSymStore.h | 1 +
lldb/unittests/Symbol/SymStoreTest.cpp | 11 ++--
3 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
index c3389416fd7ec..a5a3e3e79bde9 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.cpp
@@ -65,17 +65,7 @@ class PluginProperties : public Properties {
ePropertyCachePath);
if (s && !s->GetCurrentValueAsRef().empty())
return s->GetCurrentValue();
- // Fall back to the platform cache directory.
- llvm::SmallString<128> cache_dir;
- if (llvm::sys::path::cache_directory(cache_dir)) {
- llvm::sys::path::append(cache_dir, "lldb", "symstore");
- return cache_dir.str().str();
- }
- // Last resort: use a subdirectory of the system temp directory.
- constexpr bool erase_on_reboot = false;
- llvm::sys::path::system_temp_directory(erase_on_reboot, cache_dir);
- llvm::sys::path::append(cache_dir, "lldb", "symstore");
- return cache_dir.str().str();
+ return SymbolLocatorSymStore::GetDefaultCachePath();
}
};
@@ -158,11 +148,18 @@ std::optional<SymbolLocatorSymStore::LookupEntry>
ParseSrvEntry(llvm::StringRef entry) {
llvm::SmallVector<llvm::StringRef, 4> parts;
entry.trim().split(parts, '*');
+
+ // Format is: srv*[LocalCache*]SymbolStore
switch (parts.size()) {
case 2:
return MakeLookupEntry(parts[1]);
- case 3:
- return MakeLookupEntry(parts[2], parts[1]);
+ case 3: {
+ if (llvm::sys::path::is_absolute(parts[1]))
+ return MakeLookupEntry(parts[2], parts[1]);
+ // Fall back to LLDB's default cache for empty and invalid cache values.
+ return MakeLookupEntry(parts[2],
+ SymbolLocatorSymStore::GetDefaultCachePath());
+ }
default:
return {}; // Ignore entries with invalid number of parts.
}
@@ -171,10 +168,21 @@ ParseSrvEntry(llvm::StringRef entry) {
std::optional<std::string> ParseCacheEntry(llvm::StringRef entry) {
llvm::SmallVector<llvm::StringRef, 2> parts;
entry.trim().split(parts, '*');
+
// Ignore entries with invalid number of parts.
- if (parts.size() != 2)
+ if (parts.size() > 2)
return {};
- return parts.back().str();
+
+ // Empty cache* deliberatly specifies the default cache path.
+ llvm::StringRef value;
+ if (parts.size() == 2)
+ value = parts.back();
+
+ // Fall back to LLDB's default cache for empty and invalid values.
+ if (!llvm::sys::path::is_absolute(value))
+ return SymbolLocatorSymStore::GetDefaultCachePath();
+
+ return value.str();
}
// RSDS entries store identity as a 20-byte UUID composed of 16-byte GUID and
@@ -457,3 +465,18 @@ SymbolLocatorSymStore::ParseEnvSymbolPaths(llvm::StringRef val) {
return result;
}
+
+std::string SymbolLocatorSymStore::GetDefaultCachePath() {
+ // Fall back to the platform cache directory.
+ llvm::SmallString<128> cache_dir;
+ if (llvm::sys::path::cache_directory(cache_dir)) {
+ llvm::sys::path::append(cache_dir, "lldb", "symstore");
+ return cache_dir.str().str();
+ }
+ // Last resort: use a subdirectory of the system temp directory.
+ constexpr bool erase_on_reboot = false;
+ llvm::sys::path::system_temp_directory(erase_on_reboot, cache_dir);
+ llvm::sys::path::append(cache_dir, "lldb", "symstore");
+ return cache_dir.str().str();
+}
+
diff --git a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
index de2a1c6b9bdd5..deb2419a67d9a 100644
--- a/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
+++ b/lldb/source/Plugins/SymbolLocator/SymStore/SymbolLocatorSymStore.h
@@ -50,6 +50,7 @@ class SymbolLocatorSymStore : public SymbolLocator {
};
static std::vector<LookupEntry> ParseEnvSymbolPaths(llvm::StringRef val);
+ static std::string GetDefaultCachePath();
};
} // namespace lldb_private
diff --git a/lldb/unittests/Symbol/SymStoreTest.cpp b/lldb/unittests/Symbol/SymStoreTest.cpp
index b08cdadf74400..cf9c509443228 100644
--- a/lldb/unittests/Symbol/SymStoreTest.cpp
+++ b/lldb/unittests/Symbol/SymStoreTest.cpp
@@ -74,7 +74,8 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
returns());
EXPECT_EQ(check("SRV*http://localhost"), returns());
- // No cache without a server
+ // No cache without a server.
+ EXPECT_EQ(check("cache*"), returns());
EXPECT_EQ(check("cache*C:\\symcache"), returns());
EXPECT_EQ(check("cache*C:\\symcache;D:\\sym"), returns());
@@ -82,7 +83,6 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
EXPECT_EQ(check("SRV*C:\\symcache*\\\\corp\\symbols"),
returns("C:\\symcache"));
EXPECT_EQ(check("D:\\sym;srv*C:\\symcache*D:\\sym"), returns("C:\\symcache"));
- EXPECT_EQ(check("srv**https://symbols.mozilla.org"), returns(""));
// Implicit caches for following symbol servers
EXPECT_EQ(check("cache*D:\\s;srv*\\\\corp"), returns("D:\\s"));
@@ -95,7 +95,12 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
EXPECT_EQ(check("srv*\\\\corp;SRV*C:\\X*http://localhost;cache*D:\\s"),
returns("C:\\X"));
- // Symbol server with custom implementation (unsupported)
+ // Fall back to default cache.
+ auto default_cache = SymbolLocatorSymStore::GetDefaultCachePath();
+ EXPECT_EQ(check("cache*;srv*\\\\corp"), returns(default_cache));
+ EXPECT_EQ(check("srv**https://symbols.mozilla.org"), returns(default_cache));
+
+ // Symbol server with custom implementation (unsupported).
EXPECT_EQ(check("symsrv*symsrv.dll*https://symbols.mozilla.org"), returns());
EXPECT_EQ(check("symsrv*symsrv.dll*C:\\symbols*https://symbols.mozilla.org"),
returns());
>From 6560044567c4de7cc43f2e4ce68acae58784bff1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Mon, 13 Apr 2026 23:06:07 +0200
Subject: [PATCH 9/9] Add missing punctation in comments.
---
lldb/unittests/Symbol/SymStoreTest.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/lldb/unittests/Symbol/SymStoreTest.cpp b/lldb/unittests/Symbol/SymStoreTest.cpp
index cf9c509443228..8f1020f9d7ee5 100644
--- a/lldb/unittests/Symbol/SymStoreTest.cpp
+++ b/lldb/unittests/Symbol/SymStoreTest.cpp
@@ -22,21 +22,21 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Srv) {
};
auto returns = [](auto... strs) { return std::vector<std::string>{strs...}; };
- // Local paths
+ // Local paths.
EXPECT_EQ(check(""), returns());
EXPECT_EQ(check("C:\\ProgramData\\Symbols"),
returns("C:\\ProgramData\\Symbols"));
EXPECT_EQ(check("C:\\symbols;\\\\buildserver\\syms;file://D:/pdb"),
returns("C:\\symbols", "\\\\buildserver\\syms", "file://D:/pdb"));
- // Symbol servers
+ // Symbol servers.
EXPECT_EQ(check("srv*https://msdl.microsoft.com/download/symbols"),
returns("https://msdl.microsoft.com/download/symbols"));
EXPECT_EQ(check("Srv*https://msdl.microsoft.com/download/symbols"),
returns("https://msdl.microsoft.com/download/symbols"));
EXPECT_EQ(check("SRV*http://localhost"), returns("http://localhost"));
- // Symbol servers and local paths with caches
+ // Symbol servers and local paths with caches.
EXPECT_EQ(check("SRV*C:\\symcache*\\\\corp\\symbols"),
returns("\\\\corp\\symbols"));
EXPECT_EQ(check("D:\\sym;srv*C:\\symcache*D:\\sym"),
@@ -44,14 +44,14 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Srv) {
EXPECT_EQ(check("srv**https://symbols.mozilla.org"),
returns("https://symbols.mozilla.org"));
- // Symbol server with custom implementation (unsupported)
+ // Symbol server with custom implementation (unsupported).
EXPECT_EQ(check("symsrv*symsrv.dll*https://symbols.mozilla.org"), returns());
EXPECT_EQ(check("symsrv*symsrv.dll*C:\\symbols*https://symbols.mozilla.org"),
returns());
EXPECT_EQ(check("symsrv*https://symbols.mozilla.org;D:\\sym"),
returns("D:\\sym"));
- // Partially invalid specs
+ // Partially invalid specs.
EXPECT_EQ(check("srv*;;D:\\sym;SRV*"), returns("", "D:\\sym", ""));
EXPECT_EQ(check("srv*D:\\1*D:\\2*D:\\3;D:\\sym"), returns("D:\\sym"));
EXPECT_EQ(check("symsrv*D:\\1;D:\\sym"), returns("D:\\sym"));
@@ -67,7 +67,7 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
};
auto returns = [](auto... strs) { return std::vector<std::string>{strs...}; };
- // No caches
+ // No caches.
EXPECT_EQ(check(""), returns());
EXPECT_EQ(check("C:\\ProgramData\\Symbols"), returns());
EXPECT_EQ(check("C:\\symbols;\\\\buildserver\\syms;file://D:/pdb"),
@@ -79,12 +79,12 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
EXPECT_EQ(check("cache*C:\\symcache"), returns());
EXPECT_EQ(check("cache*C:\\symcache;D:\\sym"), returns());
- // Explicit caches for symbol servers
+ // Explicit caches for symbol servers.
EXPECT_EQ(check("SRV*C:\\symcache*\\\\corp\\symbols"),
returns("C:\\symcache"));
EXPECT_EQ(check("D:\\sym;srv*C:\\symcache*D:\\sym"), returns("C:\\symcache"));
- // Implicit caches for following symbol servers
+ // Implicit caches for following symbol servers.
EXPECT_EQ(check("cache*D:\\s;srv*\\\\corp"), returns("D:\\s"));
EXPECT_EQ(check("CACHE*D:\\s;srv*\\\\corp;SRV*http://localhost"),
returns("D:\\s", "D:\\s"));
@@ -105,7 +105,7 @@ TEST(SymStoreTest, ParseEnvSymbolPaths_Cache) {
EXPECT_EQ(check("symsrv*symsrv.dll*C:\\symbols*https://symbols.mozilla.org"),
returns());
- // Partially invalid specs
+ // Partially invalid specs.
EXPECT_EQ(check("cache*C:\\1;;D:\\sym;SRV*"), returns("C:\\1"));
EXPECT_EQ(check("cache*C:\\1;srv*D:\\1*D:\\2*D:\\3;srv*D:\\sym"),
returns("C:\\1"));
More information about the lldb-commits
mailing list