brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · b775ec9 Raw
212 lines · cpp
1//===-- SymbolLocatorDebuginfod.cpp ---------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SymbolLocatorDebuginfod.h"10 11#include "lldb/Core/PluginManager.h"12#include "lldb/Interpreter/OptionValueString.h"13#include "lldb/Utility/Args.h"14#include "lldb/Utility/LLDBLog.h"15#include "lldb/Utility/Log.h"16 17#include "llvm/Debuginfod/Debuginfod.h"18#include "llvm/Debuginfod/HTTPClient.h"19 20using namespace lldb;21using namespace lldb_private;22 23LLDB_PLUGIN_DEFINE(SymbolLocatorDebuginfod)24 25namespace {26 27#define LLDB_PROPERTIES_symbollocatordebuginfod28#include "SymbolLocatorDebuginfodProperties.inc"29 30enum {31#define LLDB_PROPERTIES_symbollocatordebuginfod32#include "SymbolLocatorDebuginfodPropertiesEnum.inc"33};34 35class PluginProperties : public Properties {36public:37  static llvm::StringRef GetSettingName() {38    return SymbolLocatorDebuginfod::GetPluginNameStatic();39  }40 41  PluginProperties() {42    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());43    m_collection_sp->Initialize(g_symbollocatordebuginfod_properties);44 45    // We need to read the default value first to read the environment variable.46    llvm::SmallVector<llvm::StringRef> urls = llvm::getDefaultDebuginfodUrls();47    Args arg_urls{urls};48    m_collection_sp->SetPropertyAtIndexFromArgs(ePropertyServerURLs, arg_urls);49 50    m_collection_sp->SetValueChangedCallback(51        ePropertyServerURLs, [this] { ServerURLsChangedCallback(); });52  }53 54  Args GetDebugInfoDURLs() const {55    Args urls;56    m_collection_sp->GetPropertyAtIndexAsArgs(ePropertyServerURLs, urls);57    return urls;58  }59 60  llvm::Expected<std::string> GetCachePath() {61    OptionValueString *s =62        m_collection_sp->GetPropertyAtIndexAsOptionValueString(63            ePropertySymbolCachePath);64    // If we don't have a valid cache location, use the default one.65    if (!s || !s->GetCurrentValueAsRef().size()) {66      llvm::Expected<std::string> maybeCachePath =67          llvm::getDefaultDebuginfodCacheDirectory();68      if (!maybeCachePath)69        return maybeCachePath;70      return *maybeCachePath;71    }72    return s->GetCurrentValue();73  }74 75  std::chrono::milliseconds GetTimeout() const {76    std::optional<uint64_t> seconds =77        m_collection_sp->GetPropertyAtIndexAs<uint64_t>(ePropertyTimeout);78    if (seconds && *seconds != 0) {79      return std::chrono::duration_cast<std::chrono::milliseconds>(80          std::chrono::seconds(*seconds));81    } else {82      return llvm::getDefaultDebuginfodTimeout();83    }84  }85 86private:87  void ServerURLsChangedCallback() {88    m_server_urls = GetDebugInfoDURLs();89    llvm::SmallVector<llvm::StringRef> dbginfod_urls;90    for (const auto &obj : m_server_urls)91      dbginfod_urls.push_back(obj.ref());92    llvm::setDefaultDebuginfodUrls(dbginfod_urls);93  }94  // Storage for the StringRef's used within the Debuginfod library.95  Args m_server_urls;96};97 98} // namespace99 100static PluginProperties &GetGlobalPluginProperties() {101  static PluginProperties g_settings;102  return g_settings;103}104 105SymbolLocatorDebuginfod::SymbolLocatorDebuginfod() : SymbolLocator() {}106 107void SymbolLocatorDebuginfod::Initialize() {108  static llvm::once_flag g_once_flag;109 110  llvm::call_once(g_once_flag, []() {111    PluginManager::RegisterPlugin(112        GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,113        LocateExecutableObjectFile, LocateExecutableSymbolFile, nullptr,114        nullptr, SymbolLocatorDebuginfod::DebuggerInitialize);115    llvm::HTTPClient::initialize();116  });117}118 119void SymbolLocatorDebuginfod::DebuggerInitialize(Debugger &debugger) {120  if (!PluginManager::GetSettingForSymbolLocatorPlugin(121          debugger, PluginProperties::GetSettingName())) {122    const bool is_global_setting = true;123    PluginManager::CreateSettingForSymbolLocatorPlugin(124        debugger, GetGlobalPluginProperties().GetValueProperties(),125        "Properties for the Debuginfod Symbol Locator plug-in.",126        is_global_setting);127  }128}129 130void SymbolLocatorDebuginfod::Terminate() {131  PluginManager::UnregisterPlugin(CreateInstance);132  llvm::HTTPClient::cleanup();133}134 135llvm::StringRef SymbolLocatorDebuginfod::GetPluginDescriptionStatic() {136  return "Debuginfod symbol locator.";137}138 139SymbolLocator *SymbolLocatorDebuginfod::CreateInstance() {140  return new SymbolLocatorDebuginfod();141}142 143static llvm::StringRef getFileName(const ModuleSpec &module_spec,144                                   std::string url_path) {145  // Check if the URL path requests an executable file or a symbol file146  bool is_executable = url_path.find("debuginfo") == std::string::npos;147  if (is_executable)148    return module_spec.GetFileSpec().GetFilename().GetStringRef();149  llvm::StringRef symbol_file =150      module_spec.GetSymbolFileSpec().GetFilename().GetStringRef();151  // Remove llvmcache- prefix and hash, keep origin file name152  if (symbol_file.starts_with("llvmcache-")) {153    size_t pos = symbol_file.rfind('-');154    if (pos != llvm::StringRef::npos) {155      symbol_file = symbol_file.substr(pos + 1);156    }157  }158  return symbol_file;159}160 161static std::optional<FileSpec>162GetFileForModule(const ModuleSpec &module_spec,163                 std::function<std::string(llvm::object::BuildID)> UrlBuilder) {164  const UUID &module_uuid = module_spec.GetUUID();165  // Don't bother if we don't have a valid UUID, Debuginfod isn't available,166  // or if the 'symbols.enable-external-lookup' setting is false.167  if (!module_uuid.IsValid() || !llvm::canUseDebuginfod() ||168      !ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup())169    return {};170 171  // Grab LLDB's Debuginfod overrides from the172  // plugin.symbol-locator.debuginfod.* settings.173  PluginProperties &plugin_props = GetGlobalPluginProperties();174  llvm::Expected<std::string> cache_path_or_err = plugin_props.GetCachePath();175  // A cache location is *required*.176  if (!cache_path_or_err)177    return {};178  std::string cache_path = *cache_path_or_err;179  llvm::SmallVector<llvm::StringRef> debuginfod_urls =180      llvm::getDefaultDebuginfodUrls();181  std::chrono::milliseconds timeout = plugin_props.GetTimeout();182 183  // We're ready to ask the Debuginfod library to find our file.184  llvm::object::BuildID build_id(module_uuid.GetBytes());185  std::string url_path = UrlBuilder(build_id);186  llvm::StringRef file_name = getFileName(module_spec, url_path);187  std::string cache_file_name = llvm::toHex(build_id, true);188  if (!file_name.empty())189    cache_file_name += "-" + file_name.str();190  llvm::Expected<std::string> result = llvm::getCachedOrDownloadArtifact(191      cache_file_name, url_path, cache_path, debuginfod_urls, timeout);192  if (result)193    return FileSpec(*result);194 195  Log *log = GetLog(LLDBLog::Symbols);196  auto err_message = llvm::toString(result.takeError());197  LLDB_LOGV(log,198            "Debuginfod failed to download symbol artifact {0} with error {1}",199            url_path, err_message);200  return {};201}202 203std::optional<ModuleSpec> SymbolLocatorDebuginfod::LocateExecutableObjectFile(204    const ModuleSpec &module_spec) {205  return GetFileForModule(module_spec, llvm::getDebuginfodExecutableUrlPath);206}207 208std::optional<FileSpec> SymbolLocatorDebuginfod::LocateExecutableSymbolFile(209    const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {210  return GetFileForModule(module_spec, llvm::getDebuginfodDebuginfoUrlPath);211}212