Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add commands to list/enable/disable plugins #134418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

dmpots
Copy link
Contributor

@dmpots dmpots commented Apr 4, 2025

This commit adds three new commands for managing plugins. The list command will show which plugins are currently registered and their enabled state. The enable and disable commands can be used to enable or disable plugins.

A disabled plugin will not show up to the PluginManager when it iterates over available plugins of a particular type.

The purpose of these commands is to provide more visibility into registered plugins and allow users to disable plugins for experimental perf reasons.

There are a few limitations to the current implementation

  1. Only SystemRuntime plugins are currently supported. We can easily extend the existing implementation to support more types.
  2. Only "statically" know plugin types are supported (i.e. those managed by the PluginManager and not from plugin load). It is possibly we could support dynamic plugins as well, but I have not looked into it yet.

This commit adds three new commands for managing plugins. The `list`
command will show which plugins are currently registered and their
enabled state. The `enable` and `disable` commands can be used to
enable or disable plugins.

A disabled plugin will not show up to the PluginManager when it iterates
over available plugins of a particular type.

The purpose of these commands is to provide more visibility into registered
plugins and allow users to disable plugins for experimental perf reasons.

There are a few limitations to the current implementation

  1. Only SystemRuntime plugins are currently supported. We can easily
     extend the existing implementation to support more types.
  2. Only "statically" know plugin types are supported (i.e. those
     managed by the PluginManager and not from `plugin load`). It is
     possibly we could support dynamic plugins as well, but I have
     not looked into it yet.
@dmpots dmpots requested review from clayborg and Jlalond April 4, 2025 17:00
@dmpots dmpots requested a review from JDevlieghere as a code owner April 4, 2025 17:00
@llvmbot llvmbot added the lldb label Apr 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 4, 2025

@llvm/pr-subscribers-lldb

Author: David Peixotto (dmpots)

Changes

This commit adds three new commands for managing plugins. The list command will show which plugins are currently registered and their enabled state. The enable and disable commands can be used to enable or disable plugins.

A disabled plugin will not show up to the PluginManager when it iterates over available plugins of a particular type.

The purpose of these commands is to provide more visibility into registered plugins and allow users to disable plugins for experimental perf reasons.

There are a few limitations to the current implementation

  1. Only SystemRuntime plugins are currently supported. We can easily extend the existing implementation to support more types.
  2. Only "statically" know plugin types are supported (i.e. those managed by the PluginManager and not from plugin load). It is possibly we could support dynamic plugins as well, but I have not looked into it yet.

Full diff: https://github.com/llvm/llvm-project/pull/134418.diff

5 Files Affected:

  • (modified) lldb/source/Commands/CommandObjectPlugin.cpp (+335)
  • (modified) lldb/source/Commands/CommandObjectSettings.cpp (+1)
  • (modified) lldb/source/Commands/Options.td (+5)
  • (added) lldb/test/Shell/Commands/command-plugin-enable+disable.test (+53)
  • (added) lldb/test/Shell/Commands/command-plugin-list.test (+51)
diff --git a/lldb/source/Commands/CommandObjectPlugin.cpp b/lldb/source/Commands/CommandObjectPlugin.cpp
index f3108b8a768d2..68261d24ffe1f 100644
--- a/lldb/source/Commands/CommandObjectPlugin.cpp
+++ b/lldb/source/Commands/CommandObjectPlugin.cpp
@@ -7,8 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "CommandObjectPlugin.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/OptionParser.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
+#include "llvm/Support/GlobPattern.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -46,12 +49,344 @@ class CommandObjectPluginLoad : public CommandObjectParsed {
   }
 };
 
+namespace {
+#define LLDB_OPTIONS_plugin_list
+#include "CommandOptions.inc"
+
+// These option definitions are shared by the plugin list/enable/disable
+// commands.
+class PluginListCommandOptions : public Options {
+public:
+  PluginListCommandOptions() = default;
+
+  ~PluginListCommandOptions() override = default;
+
+  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+                        ExecutionContext *execution_context) override {
+    Status error;
+    const int short_option = m_getopt_table[option_idx].val;
+
+    switch (short_option) {
+    case 'x':
+      m_exact_name_match = true;
+      break;
+    default:
+      llvm_unreachable("Unimplemented option");
+    }
+
+    return error;
+  }
+
+  void OptionParsingStarting(ExecutionContext *execution_context) override {
+    m_exact_name_match = false;
+  }
+
+  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+    return llvm::ArrayRef(g_plugin_list_options);
+  }
+
+  // Instance variables to hold the values for command options.
+  bool m_exact_name_match = false;
+};
+
+// Define some data structures to describe known plugin "namespaces".
+// The PluginManager is organized into a series of static functions
+// that operate on different types of plugin. For example SystemRuntime
+// and ObjectFile plugins.
+//
+// The namespace name is used a prefix when matching plugin names. For example,
+// if we have an "elf" plugin in the "object-file" namespace then we will
+// match a plugin name pattern against the "object-file.elf" name.
+//
+// The plugin namespace here is used so we can operate on all the plugins
+// of a given type so it is easy to enable or disable them as a group.
+using GetPluginInfo = std::function<std::vector<RegisteredPluginInfo>()>;
+using SetPluginEnabled = std::function<bool(llvm::StringRef, bool)>;
+struct PluginNamespace {
+  llvm::StringRef name;
+  GetPluginInfo get_info;
+  SetPluginEnabled set_enabled;
+};
+
+// Currently supported set of plugin namespaces. This will be expanded
+// over time.
+PluginNamespace PluginNamespaces[] = {
+    {"system-runtime", PluginManager::GetSystemRuntimePluginInfo,
+     PluginManager::SetSystemRuntimePluginEnabled}};
+
+// Helper function to perform an action on each matching plugin.
+// The action callback is given the containing namespace along with plugin info
+// for each matching plugin.
+static int ActOnMatchingPlugins(
+    llvm::GlobPattern pattern,
+    std::function<void(const PluginNamespace &plugin_namespace,
+                       const std::vector<RegisteredPluginInfo> &plugin_info)>
+        action) {
+  int num_matching = 0;
+
+  for (const PluginNamespace &plugin_namespace : PluginNamespaces) {
+    std::vector<RegisteredPluginInfo> all_plugins = plugin_namespace.get_info();
+    std::vector<RegisteredPluginInfo> matching_plugins;
+    for (const RegisteredPluginInfo &plugin_info : all_plugins) {
+      std::string qualified_name =
+          (plugin_namespace.name + "." + plugin_info.name).str();
+      if (pattern.match(qualified_name)) {
+        matching_plugins.push_back(plugin_info);
+      }
+    }
+
+    if (!matching_plugins.empty()) {
+      num_matching += matching_plugins.size();
+      action(plugin_namespace, matching_plugins);
+    }
+  }
+
+  return num_matching;
+}
+
+// Return a string in glob syntax for matching plugins.
+static std::string GetPluginNamePatternString(llvm::StringRef user_input,
+                                              bool add_default_glob) {
+  std::string pattern_str;
+  if (user_input.empty())
+    pattern_str = "*";
+  else
+    pattern_str = user_input;
+
+  if (add_default_glob && pattern_str != "*") {
+    pattern_str = "*" + pattern_str + "*";
+  }
+
+  return pattern_str;
+}
+
+// Attempts to create a glob pattern for a plugin name based on plugin command
+// input. Writes an error message to the `result` object if the glob cannot be
+// created successfully.
+//
+// The `glob_storage` is used to hold the string data for the glob pattern. The
+// llvm::GlobPattern only contains pointers into the string data so we need a
+// stable location that can outlive the glob pattern itself.
+std::optional<llvm::GlobPattern>
+TryCreatePluginPattern(const char *plugin_command_name, const Args &command,
+                       const PluginListCommandOptions &options,
+                       CommandReturnObject &result, std::string &glob_storage) {
+  size_t argc = command.GetArgumentCount();
+  if (argc > 1) {
+    result.AppendErrorWithFormat("'%s' requires one argument",
+                                 plugin_command_name);
+    return {};
+  }
+
+  llvm::StringRef user_pattern;
+  if (argc == 1) {
+    user_pattern = command[0].ref();
+  }
+
+  glob_storage =
+      GetPluginNamePatternString(user_pattern, !options.m_exact_name_match);
+
+  auto glob_pattern = llvm::GlobPattern::create(glob_storage);
+
+  if (auto error = glob_pattern.takeError()) {
+    std::string error_message =
+        (llvm::Twine("Invalid plugin glob pattern: '") + glob_storage +
+         "': " + llvm::toString(std::move(error)))
+            .str();
+    result.AppendError(error_message);
+    return {};
+  }
+
+  return *glob_pattern;
+}
+
+// Call the "SetEnable" function for each matching plugins.
+// Used to share the majority of the code between the enable
+// and disable commands.
+int SetEnableOnMatchingPlugins(const llvm::GlobPattern &pattern,
+                               CommandReturnObject &result, bool enabled) {
+  return ActOnMatchingPlugins(
+      pattern, [&](const PluginNamespace &plugin_namespace,
+                   const std::vector<RegisteredPluginInfo> &plugins) {
+        result.AppendMessage(plugin_namespace.name);
+        for (const auto &plugin : plugins) {
+          if (!plugin_namespace.set_enabled(plugin.name, enabled)) {
+            result.AppendErrorWithFormat("failed to enable plugin %s.%s",
+                                         plugin_namespace.name.data(),
+                                         plugin.name.data());
+            continue;
+          }
+
+          result.AppendMessageWithFormat(
+              "  %s %-30s %s\n", enabled ? "[+]" : "[-]", plugin.name.data(),
+              plugin.description.data());
+        }
+      });
+}
+} // namespace
+
+class CommandObjectPluginList : public CommandObjectParsed {
+public:
+  CommandObjectPluginList(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "plugin list",
+                            "Report info about registered LLDB plugins.",
+                            nullptr) {
+    AddSimpleArgumentList(eArgTypePlugin);
+    SetHelpLong(R"(
+Display information about registered plugins.
+The plugin information is formatted as shown below
+
+    <plugin-namespace>
+      [+] <plugin-name>                  Plugin #1 description
+      [-] <plugin-name>                  Plugin #2 description
+
+An enabled plugin is marked with [+] and a disabled plugin is marked with [-].
+
+Selecting plugins
+------------------
+plugin list [<plugin-namespace>.][<plugin-name>]
+
+Plugin names are specified using glob patterns. The pattern will be matched
+against the plugins fully qualified name, which is composed of the namespace,
+followed by a '.', followed by the plugin name.
+
+When no arguments are given the plugin selection string is the wildcard '*'.
+By default wildcards are added around the input to enable searching by
+substring. You can prevent these implicit wild cards by using the
+-x flag.
+
+Examples
+-----------------
+List all plugins in the system-runtime namespace
+
+  (lldb) plugin list system-runtime.*
+
+List all plugins containing the string foo
+
+  (lldb) plugin list foo
+
+This is equivalent to
+
+  (lldb) plugin list *foo*
+
+List only a plugin matching a fully qualified name exactly
+
+  (lldb) plugin list -x system-runtime.foo
+)");
+  }
+
+  ~CommandObjectPluginList() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+protected:
+  void DoExecute(Args &command, CommandReturnObject &result) override {
+    std::string glob_storage;
+    std::optional<llvm::GlobPattern> plugin_glob = TryCreatePluginPattern(
+        "plugin list", command, m_options, result, glob_storage);
+
+    if (!plugin_glob) {
+      assert(!result.Succeeded());
+      return;
+    }
+
+    int num_matching = ActOnMatchingPlugins(
+        *plugin_glob, [&](const PluginNamespace &plugin_namespace,
+                          const std::vector<RegisteredPluginInfo> &plugins) {
+          result.AppendMessage(plugin_namespace.name);
+          for (auto &plugin : plugins) {
+            result.AppendMessageWithFormat(
+                "  %s %-30s %s\n", plugin.enabled ? "[+]" : "[-]",
+                plugin.name.data(), plugin.description.data());
+          }
+        });
+
+    if (num_matching == 0) {
+      result.AppendErrorWithFormat("Found no matching plugins");
+    }
+  }
+
+  PluginListCommandOptions m_options;
+};
+
+class CommandObjectPluginEnable : public CommandObjectParsed {
+public:
+  CommandObjectPluginEnable(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "plugin enable",
+                            "Enable registered LLDB plugins.", nullptr) {
+    AddSimpleArgumentList(eArgTypePlugin);
+  }
+
+  ~CommandObjectPluginEnable() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+protected:
+  void DoExecute(Args &command, CommandReturnObject &result) override {
+    std::string glob_storage;
+    std::optional<llvm::GlobPattern> plugin_glob = TryCreatePluginPattern(
+        "plugin enable", command, m_options, result, glob_storage);
+
+    if (!plugin_glob) {
+      assert(!result.Succeeded());
+      return;
+    }
+
+    int num_matching = SetEnableOnMatchingPlugins(*plugin_glob, result, true);
+
+    if (num_matching == 0) {
+      result.AppendErrorWithFormat("Found no matching plugins to enable");
+    }
+  }
+
+  PluginListCommandOptions m_options;
+};
+
+class CommandObjectPluginDisable : public CommandObjectParsed {
+public:
+  CommandObjectPluginDisable(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "plugin disable",
+                            "Disable registered LLDB plugins.", nullptr) {
+    AddSimpleArgumentList(eArgTypePlugin);
+  }
+
+  ~CommandObjectPluginDisable() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+protected:
+  void DoExecute(Args &command, CommandReturnObject &result) override {
+    std::string glob_storage;
+    std::optional<llvm::GlobPattern> plugin_glob = TryCreatePluginPattern(
+        "plugin disable", command, m_options, result, glob_storage);
+
+    if (!plugin_glob) {
+      assert(!result.Succeeded());
+      return;
+    }
+
+    int num_matching = SetEnableOnMatchingPlugins(*plugin_glob, result, false);
+
+    if (num_matching == 0) {
+      result.AppendErrorWithFormat("Found no matching plugins to disable");
+    }
+  }
+
+  PluginListCommandOptions m_options;
+};
+
 CommandObjectPlugin::CommandObjectPlugin(CommandInterpreter &interpreter)
     : CommandObjectMultiword(interpreter, "plugin",
                              "Commands for managing LLDB plugins.",
                              "plugin <subcommand> [<subcommand-options>]") {
   LoadSubCommand("load",
                  CommandObjectSP(new CommandObjectPluginLoad(interpreter)));
+  LoadSubCommand("list",
+                 CommandObjectSP(new CommandObjectPluginList(interpreter)));
+  LoadSubCommand("enable",
+                 CommandObjectSP(new CommandObjectPluginEnable(interpreter)));
+  LoadSubCommand("disable",
+                 CommandObjectSP(new CommandObjectPluginDisable(interpreter)));
 }
 
 CommandObjectPlugin::~CommandObjectPlugin() = default;
diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp
index 7bbb0dd567ab1..1b60d441264d6 100644
--- a/lldb/source/Commands/CommandObjectSettings.cpp
+++ b/lldb/source/Commands/CommandObjectSettings.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionValue.h"
 #include "lldb/Interpreter/OptionValueProperties.h"
 
 using namespace lldb;
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index cc579d767eb06..ac8fd78f4a894 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -683,6 +683,11 @@ let Command = "platform shell" in {
     Desc<"Shell interpreter path. This is the binary used to run the command.">;
 }
 
+let Command = "plugin list" in {
+  def plugin_info_exact : Option<"exact", "x">,
+                          Desc<"Do not add implicit * glob around plugin name">;
+}
+
 let Command = "process launch" in {
   def process_launch_stop_at_entry : Option<"stop-at-entry", "s">,
     Desc<"Stop at the entry point of the program when launching a process.">;
diff --git a/lldb/test/Shell/Commands/command-plugin-enable+disable.test b/lldb/test/Shell/Commands/command-plugin-enable+disable.test
new file mode 100644
index 0000000000000..fcc1994b7697c
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-plugin-enable+disable.test
@@ -0,0 +1,53 @@
+# This test validates the plugin enable and disable commands.
+# Currently it works only for system-runtime plugins and we only have one
+# system runtime plugin so testing is a bit limited.
+#
+# Note that commands that return errors will stop running a script, so we
+# have new RUN lines for any command that is expected to return an error.
+
+# RUN: %lldb -s %s -o exit 2>&1 | FileCheck %s
+
+# Test plugin list shows the default state which is expected to be enabled.
+plugin list
+# CHECK-LABEL: plugin list
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin disable disables a plugin.
+plugin disable systemruntime-macosx
+# CHECK-LABEL: plugin disable systemruntime-macosx
+# CHECK: system-runtime
+# CHECK:  [-] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Make sure plugin list shows it disabled as well.
+plugin list
+# CHECK: system-runtime
+# CHECK:  [-] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin enable re-enables a plugin.
+plugin enable systemruntime-macosx
+# CHECK-LABEL: plugin enable systemruntime-macosx
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Make sure plugin list shows it enabled as well.
+plugin list
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin disable with wildcard works.
+plugin disable system*
+# CHECK-LABEL: plugin disable system*
+# CHECK: system-runtime
+# CHECK:  [-] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin enable with wildcard works.
+plugin enable system*
+# CHECK-LABEL: plugin enable system*
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin enable/disable for unknown plugin returns an error.
+# RUN: %lldb -o "plugin enable some-plugin-that-does-not-exist" 2>&1 | FileCheck %s --check-prefix=ERROR_PLUGIN_NOT_FOUND
+# RUN: %lldb -o "plugin disable some-plugin-that-does-not-exist" 2>&1 | FileCheck %s --check-prefix=ERROR_PLUGIN_NOT_FOUND
+# ERROR_PLUGIN_NOT_FOUND: error: Found no matching plugins
diff --git a/lldb/test/Shell/Commands/command-plugin-list.test b/lldb/test/Shell/Commands/command-plugin-list.test
new file mode 100644
index 0000000000000..7e5c9c671a783
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-plugin-list.test
@@ -0,0 +1,51 @@
+# This test validates the plugin list command.
+# Currently it works only for system-runtime plugins and we only have one
+# system runtime plugin so testing is a bit limited.
+#
+# Note that commands that return errors will stop running a script, so we
+# have new RUN lines for any command that is expected to return an error.
+
+# RUN: %lldb -s %s -o exit 2>&1 | FileCheck %s
+
+# Test plugin list without an argument will list all plugins.
+plugin list
+# CHECK-LABEL: plugin list
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin list with an argument will match a plugin name by substring.
+plugin list macosx
+# CHECK-LABEL: plugin list macosx
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin exact list works with fully qualified name.
+plugin list -x system-runtime.systemruntime-macosx
+# CHECK-LABEL: plugin list -x system-runtime.systemruntime-macosx
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin glob list works with fully qualified name.
+plugin list system-runtime.systemruntime-macosx
+# CHECK-LABEL: plugin list system-runtime.systemruntime-macosx
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin exact list still allows glob patterns.
+plugin list -x system*
+# CHECK-LABEL: plugin list -x system*
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin glob list still allows glob patterns.
+plugin list system-runtime.*
+# CHECK-LABEL: plugin list system-runtime.*
+# CHECK: system-runtime
+# CHECK:  [+] systemruntime-macosx           System runtime plugin for Mac OS X native libraries
+
+# Test plugin list can disable implicit glob patterns.
+# RUN: %lldb -o "plugin list -x macosx" 2>&1 | FileCheck %s --check-prefix=ERROR_PLUGIN_NOT_FOUND
+
+# Test plugin list for unknown plugin returns an error.
+# RUN: %lldb -o "plugin list some-plugin-that-does-not-exist" 2>&1 | FileCheck %s --check-prefix=ERROR_PLUGIN_NOT_FOUND
+# ERROR_PLUGIN_NOT_FOUND: error: Found no matching plugins

@jimingham
Copy link
Collaborator

jimingham commented Apr 4, 2025

Either no one is going to use this except experts, or people will start cargo-culting "turn off plugin X and lldb will be faster" and then we get "Why doesn't 'obvious thing'" work bug reports, to which the answer would be "turn on plugin X" but people may not even know they have this off (a surprising number of folks don't really know what's in the .lldbinit they got from their helpful colleagues...) I don't want to have to have another round of information gathering every time we get a report of some weird behavior.

So we should make sure that any way that we have of gathering report information includes which plugins are disabled. For instance, if you turn on any log channel, there should be a crunchy frog notice at the beginning of the log for what plugins have been disabled.

Another way to do this would be to have the list of disabled plugins show in the result of the version command, since that's a commonly provided bit of info for bug reports.

Co-authored-by: Jonas Devlieghere <[email protected]>
Copy link

github-actions bot commented Apr 4, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@dmpots
Copy link
Contributor Author

dmpots commented Apr 4, 2025

Another way to do this would be to have the list of disabled plugins show in the result of the version command, since that's a commonly provided bit of info for bug reports.

Thanks for the suggestion. Let me work on this and update the PR.

@clayborg
Copy link
Collaborator

clayborg commented Apr 7, 2025

Either no one is going to use this except experts, or people will start cargo-culting "turn off plugin X and lldb will be faster" and then we get "Why doesn't 'obvious thing'" work bug reports, to which the answer would be "turn on plugin X" but people may not even know they have this off (a surprising number of folks don't really know what's in the .lldbinit they got from their helpful colleagues...) I don't want to have to have another round of information gathering every time we get a report of some weird behavior.

So we should make sure that any way that we have of gathering report information includes which plugins are disabled. For instance, if you turn on any log channel, there should be a crunchy frog notice at the beginning of the log for what plugins have been disabled.

Another way to do this would be to have the list of disabled plugins show in the result of the version command, since that's a commonly provided bit of info for bug reports.

Can we include the plug-in info in the "statistics dump" output? We could easily JSON'ify the enabled/disabled status of all plug-ins there? Let us know if that would be acceptable

Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like the ability to enable/disable any plug-in, but we should only add support for enabling and disabling plug-ins that are optional. This patch adds the ability to enable/disable system runtime plug-ins so that is good.

A few things to think about:

Do we want a separate command for this, or should we do this with "settings set"? It might make more sense to enable this via the "settings set" command and "settings show" command, but that doesn't allow for us to see ordering of the plug-ins. We already have a manual setting for "plugin.jit-loader.gdb.enable", but this should be a template for how we do enabling and disabling of plug-ins:

(lldb) settings set plugin.jit-loader.gdb.enable false
(lldb) settings set plugin.system-runtime.macosx.enable false
(lldb) settings set plugin.object-file.elf.enable false
(lldb) settings set plugin.object-file.pe-coff.enable false

The "SystemRuntimeMacOSX" currently has its name set to "systemruntime-macosx", but it should just be "macosx". The above are just for showing how it could look, we may not want to enable/disable object file plug-ins, but maybe we do...

So we could do the enable/disable via "settings set" if that makes more sense?

Having a separate command for listing the plug-ins does allow ordering to be displayed, so maybe that is preferable? Or maybe we add just the "plugins list" command so we can show the ordering, but set the enabled/disabled state via "settings set"?

The nice thing about having dedicated commands, it allows us to enable or disable all plug-ins in a plug-in namespace with one command and as new plug-ins get added, they can be disabled. If we use the "settings set" to enable/disable, then we lose this ability unless we have a category setting that would allow us to enable/disable all plug-ins in a namespace. For example:

(lldb) settings set plugin.jit-loader.enable = false

This could enable/disable all plug-ins in a namespace using a setting that we would add?

@JDevlieghere @jimingham let us know your thoughts?

@dmpots
Copy link
Contributor Author

dmpots commented Apr 12, 2025

@JDevlieghere @jimingham @clayborg

Thanks for the comments. I updated the PR based on the initial feedback. We still have a few open issues that could use a bit more feedback:

  1. Are we ok to start with a static table of plugin namespaces or do we want dynamic registration from the beginning?
    Add commands to list/enable/disable plugins #134418 (comment)

  2. Are we ok adding the disabled plug-in info to the "statistics dump" output, or do we want it as part of the version dump?
    Add commands to list/enable/disable plugins #134418 (comment)

  3. Do we want a separate command for this, or should we do this with "settings set"?
    Add commands to list/enable/disable plugins #134418 (review)

Please take a look when you get a chance. Thanks!

@mbucko mbucko self-requested a review April 15, 2025 17:14
@dmpots dmpots requested a review from jeffreytan81 April 22, 2025 20:58
@dmpots
Copy link
Contributor Author

dmpots commented Apr 22, 2025

@JDevlieghere @jimingham @clayborg

Please take a look at these open questions when you get a chance. Thanks!

#134418 (comment)

@JDevlieghere
Copy link
Member

@JDevlieghere @jimingham @clayborg

Thanks for the comments. I updated the PR based on the initial feedback. We still have a few open issues that could use a bit more feedback:

Thanks for the ping!

  1. Are we ok to start with a static table of plugin namespaces or do we want dynamic registration from the beginning?
    Add commands to list/enable/disable plugins #134418 (comment)

If you're committed to supporting the dynamic registration, I don't mind doing it incrementally.

  1. Are we ok adding the disabled plug-in info to the "statistics dump" output, or do we want it as part of the version dump?
    Add commands to list/enable/disable plugins #134418 (comment)

That sounds like a good idea. Jim made a similar point that if LLDB behaves oddly when you have a plugin disabled, that should be as obvious as possible. We don't currently collect this information automatically, but they seem like a natural place to note this.

  1. Do we want a separate command for this, or should we do this with "settings set"?
    Add commands to list/enable/disable plugins #134418 (review)

I'm on the fence on this one. I like Greg's suggestion of reusing something existing. If everything you care about can be done with the existing setting infrastructure, i.e. enabling/disabling and showing whether they're on or off, then I think we should reuse them. If you need more information and a dedicated dump command, then I'd make this its own command so that everything related to the plugins lives together. The latter has the advantage of being slightly more future proof, at the cost of not following the existing settings paradigm.

@dmpots
Copy link
Contributor Author

dmpots commented Apr 23, 2025

  1. Are we ok to start with a static table of plugin namespaces or do we want dynamic registration from the beginning?
    Add commands to list/enable/disable plugins #134418 (comment)

If you're committed to supporting the dynamic registration, I don't mind doing it incrementally.

Sounds good. I think it should be easy to add later and would be good to have a few instances to use as an example.

  1. Are we ok adding the disabled plug-in info to the "statistics dump" output, or do we want it as part of the version dump?
    Add commands to list/enable/disable plugins #134418 (comment)

That sounds like a good idea. Jim made a similar point that if LLDB behaves oddly when you have a plugin disabled, that should be as obvious as possible. We don't currently collect this information automatically, but they seem like a natural place to note this.

I agree adding to stats makes sense. Will update the PR to do it.

  1. Do we want a separate command for this, or should we do this with "settings set"?
    Add commands to list/enable/disable plugins #134418 (review)

I'm on the fence on this one. I like Greg's suggestion of reusing something existing. If everything you care about can be done with the existing setting infrastructure, i.e. enabling/disabling and showing whether they're on or off, then I think we should reuse them. If you need more information and a dedicated dump command, then I'd make this its own command so that everything related to the plugins lives together. The latter has the advantage of being slightly more future proof, at the cost of not following the existing settings paradigm.

I think we do want a separate dump command at least to be able to show the plugin order which is useful in understanding how the debugger works and makes the plugin discovery easier. @clayborg what do you think?

@clayborg
Copy link
Collaborator

  1. Are we ok to start with a static table of plugin namespaces or do we want dynamic registration from the beginning?
    Add commands to list/enable/disable plugins #134418 (comment)

If you're committed to supporting the dynamic registration, I don't mind doing it incrementally.

Sounds good. I think it should be easy to add later and would be good to have a few instances to use as an example.

  1. Are we ok adding the disabled plug-in info to the "statistics dump" output, or do we want it as part of the version dump?
    Add commands to list/enable/disable plugins #134418 (comment)

That sounds like a good idea. Jim made a similar point that if LLDB behaves oddly when you have a plugin disabled, that should be as obvious as possible. We don't currently collect this information automatically, but they seem like a natural place to note this.

I agree adding to stats makes sense. Will update the PR to do it.

  1. Do we want a separate command for this, or should we do this with "settings set"?
    Add commands to list/enable/disable plugins #134418 (review)

I'm on the fence on this one. I like Greg's suggestion of reusing something existing. If everything you care about can be done with the existing setting infrastructure, i.e. enabling/disabling and showing whether they're on or off, then I think we should reuse them. If you need more information and a dedicated dump command, then I'd make this its own command so that everything related to the plugins lives together. The latter has the advantage of being slightly more future proof, at the cost of not following the existing settings paradigm.

I think we do want a separate dump command at least to be able to show the plugin order which is useful in understanding how the debugger works and makes the plugin discovery easier. @clayborg what do you think?

Yeah, I agree with being able to dump the plug-ins from a command is nice so we can see the actual plug-in ordering.

@dmpots
Copy link
Contributor Author

dmpots commented Apr 25, 2025

@clayborg @JDevlieghere @jimingham I updated the PR to include plugin info in the stats. Please take a look when you get a chance. Thanks!

bool GetIncludePlugins() const {
if (m_include_plugins.has_value())
return m_include_plugins.value();
// Default to true in both default mode and summary mode.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include plugin info in the stats by default?

@dmpots
Copy link
Contributor Author

dmpots commented May 5, 2025

ping @clayborg @JDevlieghere @jimingham. I updated the PR to include plugin info in the stats. Please take a look when you get a chance. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants