aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp191
1 files changed, 191 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
new file mode 100644
index 000000000000..2cd7bbbb2449
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
@@ -0,0 +1,191 @@
+//===-- SymbolLocatorDebuginfod.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 "SymbolLocatorDebuginfod.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Interpreter/OptionValueString.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+
+#include "llvm/Debuginfod/Debuginfod.h"
+#include "llvm/Debuginfod/HTTPClient.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(SymbolLocatorDebuginfod)
+
+namespace {
+
+#define LLDB_PROPERTIES_symbollocatordebuginfod
+#include "SymbolLocatorDebuginfodProperties.inc"
+
+enum {
+#define LLDB_PROPERTIES_symbollocatordebuginfod
+#include "SymbolLocatorDebuginfodPropertiesEnum.inc"
+};
+
+class PluginProperties : public Properties {
+public:
+ static llvm::StringRef GetSettingName() {
+ return SymbolLocatorDebuginfod::GetPluginNameStatic();
+ }
+
+ PluginProperties() {
+ m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
+ m_collection_sp->Initialize(g_symbollocatordebuginfod_properties);
+
+ // We need to read the default value first to read the environment variable.
+ llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls();
+ Args arg_urls{urls};
+ m_collection_sp->SetPropertyAtIndexFromArgs(ePropertyServerURLs, arg_urls);
+
+ m_collection_sp->SetValueChangedCallback(
+ ePropertyServerURLs, [this] { ServerURLsChangedCallback(); });
+ }
+
+ Args GetDebugInfoDURLs() const {
+ Args urls;
+ m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyServerURLs, urls);
+ return urls;
+ }
+
+ llvm::Expected<std::string> GetCachePath() {
+ OptionValueString *s =
+ m_collection_sp->GetPropertyAtIndexAsOptionValueString(
+ ePropertySymbolCachePath);
+ // If we don't have a valid cache location, use the default one.
+ if (!s || !s->GetCurrentValueAsRef().size()) {
+ llvm::Expected<std::string> maybeCachePath =
+ llvm::getDefaultDebuginfodCacheDirectory();
+ if (!maybeCachePath)
+ return maybeCachePath;
+ return *maybeCachePath;
+ }
+ return s->GetCurrentValue();
+ }
+
+ std::chrono::milliseconds GetTimeout() const {
+ std::optional<uint64_t> seconds =
+ m_collection_sp->GetPropertyAtIndexAs<uint64_t>(ePropertyTimeout);
+ if (seconds && *seconds != 0) {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::seconds(*seconds));
+ } else {
+ return llvm::getDefaultDebuginfodTimeout();
+ }
+ }
+
+private:
+ void ServerURLsChangedCallback() {
+ m_server_urls = GetDebugInfoDURLs();
+ llvm::SmallVector<llvm::StringRef> dbginfod_urls;
+ llvm::for_each(m_server_urls, [&](const auto &obj) {
+ dbginfod_urls.push_back(obj.ref());
+ });
+ llvm::setDefaultDebuginfodUrls(dbginfod_urls);
+ }
+ // Storage for the StringRef's used within the Debuginfod library.
+ Args m_server_urls;
+};
+
+} // namespace
+
+static PluginProperties &GetGlobalPluginProperties() {
+ static PluginProperties g_settings;
+ return g_settings;
+}
+
+SymbolLocatorDebuginfod::SymbolLocatorDebuginfod() : SymbolLocator() {}
+
+void SymbolLocatorDebuginfod::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+ LocateExecutableObjectFile, LocateExecutableSymbolFile, nullptr,
+ nullptr, SymbolLocatorDebuginfod::DebuggerInitialize);
+ llvm::HTTPClient::initialize();
+ });
+}
+
+void SymbolLocatorDebuginfod::DebuggerInitialize(Debugger &debugger) {
+ if (!PluginManager::GetSettingForSymbolLocatorPlugin(
+ debugger, PluginProperties::GetSettingName())) {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForSymbolLocatorPlugin(
+ debugger, GetGlobalPluginProperties().GetValueProperties(),
+ "Properties for the Debuginfod Symbol Locator plug-in.",
+ is_global_setting);
+ }
+}
+
+void SymbolLocatorDebuginfod::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+ llvm::HTTPClient::cleanup();
+}
+
+llvm::StringRef SymbolLocatorDebuginfod::GetPluginDescriptionStatic() {
+ return "Debuginfod symbol locator.";
+}
+
+SymbolLocator *SymbolLocatorDebuginfod::CreateInstance() {
+ return new SymbolLocatorDebuginfod();
+}
+
+static std::optional<FileSpec>
+GetFileForModule(const ModuleSpec &module_spec,
+ std::function<std::string(llvm::object::BuildID)> UrlBuilder) {
+ const UUID &module_uuid = module_spec.GetUUID();
+ // Don't bother if we don't have a valid UUID, Debuginfod isn't available,
+ // or if the 'symbols.enable-external-lookup' setting is false.
+ if (!module_uuid.IsValid() || !llvm::canUseDebuginfod() ||
+ !ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup())
+ return {};
+
+ // Grab LLDB's Debuginfod overrides from the
+ // plugin.symbol-locator.debuginfod.* settings.
+ PluginProperties &plugin_props = GetGlobalPluginProperties();
+ llvm::Expected<std::string> cache_path_or_err = plugin_props.GetCachePath();
+ // A cache location is *required*.
+ if (!cache_path_or_err)
+ return {};
+ std::string cache_path = *cache_path_or_err;
+ llvm::SmallVector<llvm::StringRef> debuginfod_urls =
+ llvm::getDefaultDebuginfodUrls();
+ std::chrono::milliseconds timeout = plugin_props.GetTimeout();
+
+ // We're ready to ask the Debuginfod library to find our file.
+ llvm::object::BuildID build_id(module_uuid.GetBytes());
+ std::string url_path = UrlBuilder(build_id);
+ std::string cache_key = llvm::getDebuginfodCacheKey(url_path);
+ llvm::Expected<std::string> result = llvm::getCachedOrDownloadArtifact(
+ cache_key, url_path, cache_path, debuginfod_urls, timeout);
+ if (result)
+ return FileSpec(*result);
+
+ Log *log = GetLog(LLDBLog::Symbols);
+ auto err_message = llvm::toString(result.takeError());
+ LLDB_LOGV(log,
+ "Debuginfod failed to download symbol artifact {0} with error {1}",
+ url_path, err_message);
+ return {};
+}
+
+std::optional<ModuleSpec> SymbolLocatorDebuginfod::LocateExecutableObjectFile(
+ const ModuleSpec &module_spec) {
+ return GetFileForModule(module_spec, llvm::getDebuginfodExecutableUrlPath);
+}
+
+std::optional<FileSpec> SymbolLocatorDebuginfod::LocateExecutableSymbolFile(
+ const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+ return GetFileForModule(module_spec, llvm::getDebuginfodDebuginfoUrlPath);
+}