brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · 093ebde Raw
359 lines · cpp
1//===-- CommandObjectPlugin.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 "CommandObjectPlugin.h"10#include "lldb/Core/PluginManager.h"11#include "lldb/Host/OptionParser.h"12#include "lldb/Interpreter/CommandInterpreter.h"13#include "lldb/Interpreter/CommandReturnObject.h"14 15using namespace lldb;16using namespace lldb_private;17 18class CommandObjectPluginLoad : public CommandObjectParsed {19public:20  CommandObjectPluginLoad(CommandInterpreter &interpreter)21      : CommandObjectParsed(interpreter, "plugin load",22                            "Import a dylib that implements an LLDB plugin.",23                            nullptr) {24    AddSimpleArgumentList(eArgTypeFilename);25  }26 27  ~CommandObjectPluginLoad() override = default;28 29protected:30  void DoExecute(Args &command, CommandReturnObject &result) override {31    size_t argc = command.GetArgumentCount();32 33    if (argc != 1) {34      result.AppendError("'plugin load' requires one argument");35      return;36    }37 38    Status error;39 40    FileSpec dylib_fspec(command[0].ref());41    FileSystem::Instance().Resolve(dylib_fspec);42 43    if (GetDebugger().LoadPlugin(dylib_fspec, error))44      result.SetStatus(eReturnStatusSuccessFinishResult);45    else {46      result.AppendError(error.AsCString());47    }48  }49};50 51namespace {52// Helper function to perform an action on each matching plugin.53// The action callback is given the containing namespace along with plugin info54// for each matching plugin.55static int ActOnMatchingPlugins(56    const llvm::StringRef pattern,57    std::function<void(const PluginNamespace &plugin_namespace,58                       const std::vector<RegisteredPluginInfo> &plugin_info)>59        action) {60  int num_matching = 0;61 62  for (const PluginNamespace &plugin_namespace :63       PluginManager::GetPluginNamespaces()) {64 65    std::vector<RegisteredPluginInfo> matching_plugins;66    for (const RegisteredPluginInfo &plugin_info :67         plugin_namespace.get_info()) {68      if (PluginManager::MatchPluginName(pattern, plugin_namespace,69                                         plugin_info))70        matching_plugins.push_back(plugin_info);71    }72 73    if (!matching_plugins.empty()) {74      num_matching += matching_plugins.size();75      action(plugin_namespace, matching_plugins);76    }77  }78 79  return num_matching;80}81 82// Call the "SetEnable" function for each matching plugins.83// Used to share the majority of the code between the enable84// and disable commands.85int SetEnableOnMatchingPlugins(const llvm::StringRef &pattern,86                               CommandReturnObject &result, bool enabled) {87  return ActOnMatchingPlugins(88      pattern, [&](const PluginNamespace &plugin_namespace,89                   const std::vector<RegisteredPluginInfo> &plugins) {90        result.AppendMessage(plugin_namespace.name);91        for (const auto &plugin : plugins) {92          if (!plugin_namespace.set_enabled(plugin.name, enabled)) {93            result.AppendErrorWithFormat("failed to enable plugin %s.%s",94                                         plugin_namespace.name.data(),95                                         plugin.name.data());96            continue;97          }98 99          result.AppendMessageWithFormat(100              "  %s %-30s %s\n", enabled ? "[+]" : "[-]", plugin.name.data(),101              plugin.description.data());102        }103      });104}105 106static std::string ConvertJSONToPrettyString(const llvm::json::Value &json) {107  std::string str;108  llvm::raw_string_ostream os(str);109  os << llvm::formatv("{0:2}", json).str();110  os.flush();111  return str;112}113 114#define LLDB_OPTIONS_plugin_list115#include "CommandOptions.inc"116 117// These option definitions are used by the plugin list command.118class PluginListCommandOptions : public Options {119public:120  PluginListCommandOptions() = default;121 122  ~PluginListCommandOptions() override = default;123 124  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,125                        ExecutionContext *execution_context) override {126    Status error;127    const int short_option = m_getopt_table[option_idx].val;128 129    switch (short_option) {130    case 'j':131      m_json_format = true;132      break;133    default:134      llvm_unreachable("Unimplemented option");135    }136 137    return error;138  }139 140  void OptionParsingStarting(ExecutionContext *execution_context) override {141    m_json_format = false;142  }143 144  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {145    return llvm::ArrayRef(g_plugin_list_options);146  }147 148  // Instance variables to hold the values for command options.149  bool m_json_format = false;150};151} // namespace152 153class CommandObjectPluginList : public CommandObjectParsed {154public:155  CommandObjectPluginList(CommandInterpreter &interpreter)156      : CommandObjectParsed(interpreter, "plugin list",157                            "Report info about registered LLDB plugins.",158                            nullptr) {159    AddSimpleArgumentList(eArgTypeManagedPlugin);160    SetHelpLong(R"(161Display information about registered plugins.162The plugin information is formatted as shown below:163 164    <plugin-namespace>165      [+] <plugin-name>                  Plugin #1 description166      [-] <plugin-name>                  Plugin #2 description167 168An enabled plugin is marked with [+] and a disabled plugin is marked with [-].169 170Plugins can be listed by namespace and name with:171 172  plugin list <plugin-namespace>[.<plugin-name>]173 174Plugins can be listed by namespace alone or with a fully qualified name. When listed175with just a namespace all plugins in that namespace are listed.  When no arguments176are given all plugins are listed.177 178Examples:179List all plugins180 181  (lldb) plugin list182 183List all plugins in the system-runtime namespace184 185  (lldb) plugin list system-runtime186 187List only the plugin 'foo' matching a fully qualified name exactly188 189  (lldb) plugin list system-runtime.foo190)");191  }192 193  ~CommandObjectPluginList() override = default;194 195  Options *GetOptions() override { return &m_options; }196 197  void198  HandleArgumentCompletion(CompletionRequest &request,199                           OptionElementVector &opt_element_vector) override {200    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(201        GetCommandInterpreter(), lldb::eManagedPluginCompletion, request,202        nullptr);203  }204 205protected:206  void DoExecute(Args &command, CommandReturnObject &result) override {207    size_t argc = command.GetArgumentCount();208    result.SetStatus(eReturnStatusSuccessFinishResult);209 210    // Create a temporary vector to hold the patterns to simplify the logic211    // for the case when the user passes no patterns212    std::vector<llvm::StringRef> patterns;213    patterns.reserve(argc == 0 ? 1 : argc);214    if (argc == 0)215      patterns.push_back("");216    else217      for (size_t i = 0; i < argc; ++i)218        patterns.push_back(command[i].ref());219 220    if (m_options.m_json_format)221      OutputJsonFormat(patterns, result);222    else223      OutputTextFormat(patterns, result);224  }225 226private:227  void OutputJsonFormat(const std::vector<llvm::StringRef> &patterns,228                        CommandReturnObject &result) {229    llvm::json::Object obj;230    bool found_empty = false;231    for (const llvm::StringRef pattern : patterns) {232      llvm::json::Object pat_obj = PluginManager::GetJSON(pattern);233      if (pat_obj.empty()) {234        found_empty = true;235        result.AppendErrorWithFormat(236            "Found no matching plugins for pattern '%s'", pattern.data());237        break;238      }239      for (auto &entry : pat_obj) {240        obj[entry.first] = std::move(entry.second);241      }242    }243    if (!found_empty) {244      result.AppendMessage(ConvertJSONToPrettyString(std::move(obj)));245    }246  }247 248  void OutputTextFormat(const std::vector<llvm::StringRef> &patterns,249                        CommandReturnObject &result) {250    for (const llvm::StringRef pattern : patterns) {251      int num_matching = ActOnMatchingPlugins(252          pattern, [&](const PluginNamespace &plugin_namespace,253                       const std::vector<RegisteredPluginInfo> &plugins) {254            result.AppendMessage(plugin_namespace.name);255            for (auto &plugin : plugins) {256              result.AppendMessageWithFormat(257                  "  %s %-30s %s\n", plugin.enabled ? "[+]" : "[-]",258                  plugin.name.data(), plugin.description.data());259            }260          });261      if (num_matching == 0) {262        result.AppendErrorWithFormat(263            "Found no matching plugins for pattern '%s'", pattern.data());264        break;265      }266    }267  }268 269  PluginListCommandOptions m_options;270};271 272static void DoPluginEnableDisable(Args &command, CommandReturnObject &result,273                                  bool enable) {274  const char *name = enable ? "enable" : "disable";275  size_t argc = command.GetArgumentCount();276  if (argc == 0) {277    result.AppendErrorWithFormat("'plugin %s' requires one or more arguments",278                                 name);279    return;280  }281  result.SetStatus(eReturnStatusSuccessFinishResult);282 283  for (size_t i = 0; i < argc; ++i) {284    llvm::StringRef pattern = command[i].ref();285    int num_matching = SetEnableOnMatchingPlugins(pattern, result, enable);286 287    if (num_matching == 0) {288      result.AppendErrorWithFormat(289          "Found no matching plugins to %s for pattern '%s'", name,290          pattern.data());291      break;292    }293  }294}295 296class CommandObjectPluginEnable : public CommandObjectParsed {297public:298  CommandObjectPluginEnable(CommandInterpreter &interpreter)299      : CommandObjectParsed(interpreter, "plugin enable",300                            "Enable registered LLDB plugins.", nullptr) {301    AddSimpleArgumentList(eArgTypeManagedPlugin);302  }303 304  void305  HandleArgumentCompletion(CompletionRequest &request,306                           OptionElementVector &opt_element_vector) override {307    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(308        GetCommandInterpreter(), lldb::eManagedPluginCompletion, request,309        nullptr);310  }311 312  ~CommandObjectPluginEnable() override = default;313 314protected:315  void DoExecute(Args &command, CommandReturnObject &result) override {316    DoPluginEnableDisable(command, result, /*enable=*/true);317  }318};319 320class CommandObjectPluginDisable : public CommandObjectParsed {321public:322  CommandObjectPluginDisable(CommandInterpreter &interpreter)323      : CommandObjectParsed(interpreter, "plugin disable",324                            "Disable registered LLDB plugins.", nullptr) {325    AddSimpleArgumentList(eArgTypeManagedPlugin);326  }327 328  void329  HandleArgumentCompletion(CompletionRequest &request,330                           OptionElementVector &opt_element_vector) override {331    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(332        GetCommandInterpreter(), lldb::eManagedPluginCompletion, request,333        nullptr);334  }335 336  ~CommandObjectPluginDisable() override = default;337 338protected:339  void DoExecute(Args &command, CommandReturnObject &result) override {340    DoPluginEnableDisable(command, result, /*enable=*/false);341  }342};343 344CommandObjectPlugin::CommandObjectPlugin(CommandInterpreter &interpreter)345    : CommandObjectMultiword(interpreter, "plugin",346                             "Commands for managing LLDB plugins.",347                             "plugin <subcommand> [<subcommand-options>]") {348  LoadSubCommand("load",349                 CommandObjectSP(new CommandObjectPluginLoad(interpreter)));350  LoadSubCommand("list",351                 CommandObjectSP(new CommandObjectPluginList(interpreter)));352  LoadSubCommand("enable",353                 CommandObjectSP(new CommandObjectPluginEnable(interpreter)));354  LoadSubCommand("disable",355                 CommandObjectSP(new CommandObjectPluginDisable(interpreter)));356}357 358CommandObjectPlugin::~CommandObjectPlugin() = default;359