LLDB mainline
CommandObjectPlugin.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
14
15using namespace lldb;
16using namespace lldb_private;
17
19public:
21 : CommandObjectParsed(interpreter, "plugin load",
22 "Import a dylib that implements an LLDB plugin.",
23 nullptr) {
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
39
40 FileSpec dylib_fspec(command[0].ref());
41 FileSystem::Instance().Resolve(dylib_fspec);
42
43 if (GetDebugger().LoadPlugin(dylib_fspec, error))
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 info
54// 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 :
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 enable
84// 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
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_list
115#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 {
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} // namespace
152
154public:
156 : CommandObjectParsed(interpreter, "plugin list",
157 "Report info about registered LLDB plugins.",
158 nullptr) {
160 SetHelpLong(R"(
161Display information about registered plugins.
162The plugin information is formatted as shown below:
164 <plugin-namespace>
165 [+] <plugin-name> Plugin #1 description
166 [-] <plugin-name> Plugin #2 description
167
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 listed
175with just a namespace all plugins in that namespace are listed. When no arguments
176are given all plugins are listed.
177
178Examples:
179List all plugins
180
181 (lldb) plugin list
182
183List all plugins in the system-runtime namespace
184
185 (lldb) plugin list system-runtime
186
187List only the plugin 'foo' matching a fully qualified name exactly
188
189 (lldb) plugin list system-runtime.foo
190)");
191 }
192
193 ~CommandObjectPluginList() override = default;
194
195 Options *GetOptions() override { return &m_options; }
196
197 void
199 OptionElementVector &opt_element_vector) override {
202 nullptr);
203 }
204
205protected:
206 void DoExecute(Args &command, CommandReturnObject &result) override {
207 size_t argc = command.GetArgumentCount();
209
210 // Create a temporary vector to hold the patterns to simplify the logic
211 // for the case when the user passes no patterns
212 std::vector<llvm::StringRef> patterns;
213 patterns.reserve(argc == 0 ? 1 : argc);
214 if (argc == 0)
215 patterns.push_back("");
216 else
217 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 else
223 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;
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) {
257 " %s %-30s %s\n", plugin.enabled ? "[+]" : "[-]",
258 plugin.name.data(), plugin.description.data());
259 }
260 });
261 if (num_matching == 0) {
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 }
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) {
289 "Found no matching plugins to %s for pattern '%s'", name,
290 pattern.data());
291 break;
292 }
293 }
294}
295
297public:
299 : CommandObjectParsed(interpreter, "plugin enable",
300 "Enable registered LLDB plugins.", nullptr) {
302 }
303
304 void
311
312 ~CommandObjectPluginEnable() override = default;
313
314protected:
315 void DoExecute(Args &command, CommandReturnObject &result) override {
316 DoPluginEnableDisable(command, result, /*enable=*/true);
317 }
318};
319
321public:
323 : CommandObjectParsed(interpreter, "plugin disable",
324 "Disable registered LLDB plugins.", nullptr) {
326 }
327
328 void
335
336 ~CommandObjectPluginDisable() override = default;
337
338protected:
339 void DoExecute(Args &command, CommandReturnObject &result) override {
340 DoPluginEnableDisable(command, result, /*enable=*/false);
341 }
342};
343
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",
354 LoadSubCommand("disable",
356}
357
static void DoPluginEnableDisable(Args &command, CommandReturnObject &result, bool enable)
static llvm::raw_ostream & error(Stream &strm)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
~CommandObjectPluginDisable() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectPluginDisable(CommandInterpreter &interpreter)
CommandObjectPluginEnable(CommandInterpreter &interpreter)
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectPluginEnable() override=default
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
~CommandObjectPluginList() override=default
void OutputTextFormat(const std::vector< llvm::StringRef > &patterns, CommandReturnObject &result)
void OutputJsonFormat(const std::vector< llvm::StringRef > &patterns, CommandReturnObject &result)
PluginListCommandOptions m_options
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectPluginList(CommandInterpreter &interpreter)
Options * GetOptions() override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectPluginLoad() override=default
CommandObjectPluginLoad(CommandInterpreter &interpreter)
A command line argument class.
Definition Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition Args.h:120
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectMultiword(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectParsed(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectPlugin(CommandInterpreter &interpreter)
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
CommandInterpreter & GetCommandInterpreter()
void AppendMessage(llvm::StringRef in_string)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
"lldb/Utility/ArgCompletionRequest.h"
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A file utility class.
Definition FileSpec.h:57
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
A command line option parsing protocol class.
Definition Options.h:58
static bool MatchPluginName(llvm::StringRef pattern, const PluginNamespace &plugin_ns, const RegisteredPluginInfo &plugin)
static llvm::json::Object GetJSON(llvm::StringRef pattern="")
static llvm::ArrayRef< PluginNamespace > GetPluginNamespaces()
An error handling class.
Definition Status.h:118
A class that represents a running process on the host machine.
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
@ eManagedPluginCompletion
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
@ eReturnStatusSuccessFinishResult
@ eArgTypeManagedPlugin