[Lldb-commits] [lldb] Add commands to list/enable/disable plugins (PR #134418)
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 6 15:27:07 PDT 2025
================
@@ -46,12 +48,287 @@ class CommandObjectPluginLoad : public CommandObjectParsed {
}
};
+namespace {
+// 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(
+ const llvm::StringRef pattern,
+ std::function<void(const PluginNamespace &plugin_namespace,
+ const std::vector<RegisteredPluginInfo> &plugin_info)>
+ action) {
+ int num_matching = 0;
+
+ for (const PluginNamespace &plugin_namespace :
+ PluginManager::GetPluginNamespaces()) {
+
+ std::vector<RegisteredPluginInfo> matching_plugins;
+ for (const RegisteredPluginInfo &plugin_info :
+ plugin_namespace.get_info()) {
+ if (PluginManager::MatchPluginName(pattern, plugin_namespace,
+ plugin_info))
+ matching_plugins.push_back(plugin_info);
+ }
+
+ if (!matching_plugins.empty()) {
+ num_matching += matching_plugins.size();
+ action(plugin_namespace, matching_plugins);
+ }
+ }
+
+ return num_matching;
+}
+
+// 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::StringRef &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());
+ }
+ });
+}
+
+static std::string ConvertJSONToPrettyString(const llvm::json::Value &json) {
+ std::string str;
+ llvm::raw_string_ostream os(str);
+ os << llvm::formatv("{0:2}", json).str();
+ os.flush();
+ return str;
+}
+
+#define LLDB_OPTIONS_plugin_list
+#include "CommandOptions.inc"
+
+// These option definitions are used by the plugin list command.
+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 'j':
+ m_json_format = true;
+ break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_json_format = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::ArrayRef(g_plugin_list_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ bool m_json_format = false;
+};
+} // namespace
+
+class CommandObjectPluginList : public CommandObjectParsed {
+public:
+ CommandObjectPluginList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "plugin list",
+ "Report info about registered LLDB plugins.",
+ nullptr) {
+ AddSimpleArgumentList(eArgTypeManagedPlugin);
+ 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 [-].
+
+Plugins can be listed by namespace and name with:
+
+ plugin list <plugin-namespace>[.<plugin-name>]
+
+Plugins can be listed by namespace alone or with a fully qualified name. When listed
+with just a namespace all plugins in that namespace are listed. When no arguments
+are given all plugins are listed.
+
+Examples:
+List all plugins
+
+ (lldb) plugin list
+
+List all plugins in the system-runtime namespace
+
+ (lldb) plugin list system-runtime
+
+List only the plugin 'foo' matching a fully qualified name exactly
+
+ (lldb) plugin list system-runtime.foo
+)");
+ }
+
+ ~CommandObjectPluginList() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ size_t argc = command.GetArgumentCount();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ // Create a temporary vector to hold the patterns to simplify the logic
+ // for the case when the user passes no patterns
+ std::vector<llvm::StringRef> patterns;
+ patterns.reserve(argc == 0 ? 1 : argc);
+ if (argc == 0)
+ patterns.push_back("");
+ else
+ for (size_t i = 0; i < argc; ++i)
+ patterns.push_back(command[i].ref());
+
+ if (m_options.m_json_format)
+ OutputJsonFormat(patterns, result);
+ else
+ OutputTextFormat(patterns, result);
+ }
+
+private:
+ void OutputJsonFormat(const std::vector<llvm::StringRef> &patterns,
+ CommandReturnObject &result) {
+ llvm::json::Object obj;
+ bool found_empty = false;
+ for (const llvm::StringRef pattern : patterns) {
+ llvm::json::Object pat_obj = PluginManager::GetJSON(pattern);
+ if (pat_obj.empty()) {
+ found_empty = true;
+ result.AppendErrorWithFormat(
+ "Found no matching plugins for pattern '%s'", pattern.data());
+ break;
+ }
+ for (auto &entry : pat_obj) {
+ obj[entry.first] = std::move(entry.second);
+ }
+ }
+ if (!found_empty) {
+ result.AppendMessage(ConvertJSONToPrettyString(std::move(obj)));
+ }
+ }
+
+ void OutputTextFormat(const std::vector<llvm::StringRef> &patterns,
+ CommandReturnObject &result) {
+ for (const llvm::StringRef pattern : patterns) {
+ int num_matching = ActOnMatchingPlugins(
+ pattern, [&](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 for pattern '%s'", pattern.data());
+ break;
+ }
+ }
+ }
+
+ PluginListCommandOptions m_options;
+};
+
+static void DoPluginEnableDisable(Args &command, CommandReturnObject &result,
+ bool enable) {
+ const char *name = enable ? "enable" : "disable";
+ size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat("'plugin %s' requires one or more arguments",
+ name);
+ return;
+ }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ for (size_t i = 0; i < argc; ++i) {
+ llvm::StringRef pattern = command[i].ref();
+ int num_matching = SetEnableOnMatchingPlugins(pattern, result, enable);
+
+ if (num_matching == 0) {
+ result.AppendErrorWithFormat(
+ "Found no matching plugins to %s for pattern '%s'", name,
+ pattern.data());
+ break;
+ }
+ }
+}
+
+class CommandObjectPluginEnable : public CommandObjectParsed {
+public:
+ CommandObjectPluginEnable(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "plugin enable",
+ "Enable registered LLDB plugins.", nullptr) {
+ AddSimpleArgumentList(eArgTypeManagedPlugin);
+ }
+
+ ~CommandObjectPluginEnable() override = default;
+
+protected:
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ DoPluginEnableDisable(command, result, true);
+ }
+};
+
+class CommandObjectPluginDisable : public CommandObjectParsed {
+public:
+ CommandObjectPluginDisable(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "plugin disable",
+ "Disable registered LLDB plugins.", nullptr) {
+ AddSimpleArgumentList(eArgTypeManagedPlugin);
+ }
+
+ ~CommandObjectPluginDisable() override = default;
+
+protected:
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ DoPluginEnableDisable(command, result, false);
----------------
clayborg wrote:
```
DoPluginEnableDisable(command, result, /*enable=*/false);
```
https://github.com/llvm/llvm-project/pull/134418
More information about the lldb-commits
mailing list