The _NT_SYMBOL_PATH environment variable is the idiomatic way to set a system-wide lookup order of symbol servers and a local cache for SymStore. It holds a semicolon-separated list of entries in the following notations: * srv*[<cache>*]<source> sets a source and an optional explicit cache * cache*<cache> sets an implicit cache for all subsequent entries * all other entries are bare local directories Since symbol paths are closely intertwined with the caching of symbol files, this patch proposes support in LLDB for both features at once. ParseEnvSymbolPaths() implements the parsing logic, which processes entries of the symbol path string from left to right to create a series of LookupEntry objects that each store a source and a cache location. The source of a LookupEntry can be a local directory or an HTTP server address. The cache is a local directory or empty. This representation unifies the implicit vs. explicit caching options from the SymStore protocol. The lookup remains in LocateSymStoreEntry() which we now invoke for each LookupEntry. Here we distinguish sources between HTTP servers and local directories. The latter doesn't change. We just moved the logging to clearly express the new cases. For HTTP downloads we now check the cache first and add files to it after download. The download itself keeps targeting a temporary file to avoid corrupt cache entries in case of interruptions. After all, the SymStore protocol has no check-sums! We define a default cache path that is used as a fallback, if the symbol path doesn't specify any. It can be overridden through the plugin.symbol-locator.symstore.cache property. This is analog to Debuginfod and very handy since we want to move files out from temp after download. The default cache path is what we use if there are no other options. The symbol path notation in the SymStore protocol carries quite some legacy. The SymStoreTest unittest checks that we can parse all the obscure combinations of possible server and cache entries. --------- Co-authored-by: Nerixyz <nero.9@hotmail.de>
114 lines
4.8 KiB
C++
114 lines
4.8 KiB
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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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*"), returns());
|
|
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"));
|
|
|
|
// 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"));
|
|
|
|
// Fall back to default cache.
|
|
auto default_cache = SymbolLocatorSymStore::GetSystemDefaultCachePath();
|
|
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());
|
|
|
|
// 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"));
|
|
}
|