//===-- 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;
    for (const auto &obj : m_server_urls)
      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 llvm::StringRef getFileName(const ModuleSpec &module_spec,
                                   std::string url_path) {
  // Check if the URL path requests an executable file or a symbol file
  bool is_executable = url_path.find("debuginfo") == std::string::npos;
  if (is_executable)
    return module_spec.GetFileSpec().GetFilename().GetStringRef();
  llvm::StringRef symbol_file =
      module_spec.GetSymbolFileSpec().GetFilename().GetStringRef();
  // Remove llvmcache- prefix and hash, keep origin file name
  if (symbol_file.starts_with("llvmcache-")) {
    size_t pos = symbol_file.rfind('-');
    if (pos != llvm::StringRef::npos) {
      symbol_file = symbol_file.substr(pos + 1);
    }
  }
  return symbol_file;
}

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);
  llvm::StringRef file_name = getFileName(module_spec, url_path);
  std::string cache_file_name = llvm::toHex(build_id, true);
  if (!file_name.empty())
    cache_file_name += "-" + file_name.str();
  llvm::Expected<std::string> result = llvm::getCachedOrDownloadArtifact(
      cache_file_name, 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);
}
