1 //===-- CommandObject.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 
9 #include "lldb/Interpreter/CommandObject.h"
10 
11 #include <map>
12 #include <sstream>
13 #include <string>
14 
15 #include <cctype>
16 #include <cstdlib>
17 
18 #include "lldb/Core/Address.h"
19 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
20 #include "lldb/Interpreter/Options.h"
21 #include "lldb/Utility/ArchSpec.h"
22 #include "llvm/ADT/ScopeExit.h"
23 
24 // These are for the Sourcename completers.
25 // FIXME: Make a separate file for the completers.
26 #include "lldb/DataFormatters/FormatManager.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/FileSpec.h"
30 #include "lldb/Utility/FileSpecList.h"
31 
32 #include "lldb/Target/Language.h"
33 
34 #include "lldb/Interpreter/CommandInterpreter.h"
35 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
36 #include "lldb/Interpreter/CommandReturnObject.h"
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 // CommandObject
42 
43 CommandObject::CommandObject(CommandInterpreter &interpreter,
44                              llvm::StringRef name, llvm::StringRef help,
45                              llvm::StringRef syntax, uint32_t flags)
46     : m_interpreter(interpreter), m_cmd_name(std::string(name)),
47       m_flags(flags), m_deprecated_command_override_callback(nullptr),
48       m_command_override_callback(nullptr), m_command_override_baton(nullptr) {
49   m_cmd_help_short = std::string(help);
50   m_cmd_syntax = std::string(syntax);
51 }
52 
53 Debugger &CommandObject::GetDebugger() { return m_interpreter.GetDebugger(); }
54 
55 llvm::StringRef CommandObject::GetHelp() { return m_cmd_help_short; }
56 
57 llvm::StringRef CommandObject::GetHelpLong() { return m_cmd_help_long; }
58 
59 llvm::StringRef CommandObject::GetSyntax() {
60   if (!m_cmd_syntax.empty())
61     return m_cmd_syntax;
62 
63   StreamString syntax_str;
64   syntax_str.PutCString(GetCommandName());
65 
66   if (!IsDashDashCommand() && GetOptions() != nullptr)
67     syntax_str.PutCString(" <cmd-options>");
68 
69   if (!m_arguments.empty()) {
70     syntax_str.PutCString(" ");
71 
72     if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() &&
73         GetOptions()->NumCommandOptions())
74       syntax_str.PutCString("-- ");
75     GetFormattedCommandArguments(syntax_str);
76   }
77   m_cmd_syntax = std::string(syntax_str.GetString());
78 
79   return m_cmd_syntax;
80 }
81 
82 llvm::StringRef CommandObject::GetCommandName() const { return m_cmd_name; }
83 
84 void CommandObject::SetCommandName(llvm::StringRef name) {
85   m_cmd_name = std::string(name);
86 }
87 
88 void CommandObject::SetHelp(llvm::StringRef str) {
89   m_cmd_help_short = std::string(str);
90 }
91 
92 void CommandObject::SetHelpLong(llvm::StringRef str) {
93   m_cmd_help_long = std::string(str);
94 }
95 
96 void CommandObject::SetSyntax(llvm::StringRef str) {
97   m_cmd_syntax = std::string(str);
98 }
99 
100 Options *CommandObject::GetOptions() {
101   // By default commands don't have options unless this virtual function is
102   // overridden by base classes.
103   return nullptr;
104 }
105 
106 bool CommandObject::ParseOptions(Args &args, CommandReturnObject &result) {
107   // See if the subclass has options?
108   Options *options = GetOptions();
109   if (options != nullptr) {
110     Status error;
111 
112     auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
113     options->NotifyOptionParsingStarting(&exe_ctx);
114 
115     const bool require_validation = true;
116     llvm::Expected<Args> args_or = options->Parse(
117         args, &exe_ctx, GetCommandInterpreter().GetPlatform(true),
118         require_validation);
119 
120     if (args_or) {
121       args = std::move(*args_or);
122       error = options->NotifyOptionParsingFinished(&exe_ctx);
123     } else
124       error = args_or.takeError();
125 
126     if (error.Success()) {
127       if (options->VerifyOptions(result))
128         return true;
129     } else {
130       const char *error_cstr = error.AsCString();
131       if (error_cstr) {
132         // We got an error string, lets use that
133         result.AppendError(error_cstr);
134       } else {
135         // No error string, output the usage information into result
136         options->GenerateOptionUsage(
137             result.GetErrorStream(), *this,
138             GetCommandInterpreter().GetDebugger().GetTerminalWidth());
139       }
140     }
141     result.SetStatus(eReturnStatusFailed);
142     return false;
143   }
144   return true;
145 }
146 
147 bool CommandObject::CheckRequirements(CommandReturnObject &result) {
148   // Nothing should be stored in m_exe_ctx between running commands as
149   // m_exe_ctx has shared pointers to the target, process, thread and frame and
150   // we don't want any CommandObject instances to keep any of these objects
151   // around longer than for a single command. Every command should call
152   // CommandObject::Cleanup() after it has completed.
153   assert(!m_exe_ctx.GetTargetPtr());
154   assert(!m_exe_ctx.GetProcessPtr());
155   assert(!m_exe_ctx.GetThreadPtr());
156   assert(!m_exe_ctx.GetFramePtr());
157 
158   // Lock down the interpreter's execution context prior to running the command
159   // so we guarantee the selected target, process, thread and frame can't go
160   // away during the execution
161   m_exe_ctx = m_interpreter.GetExecutionContext();
162 
163   const uint32_t flags = GetFlags().Get();
164   if (flags & (eCommandRequiresTarget | eCommandRequiresProcess |
165                eCommandRequiresThread | eCommandRequiresFrame |
166                eCommandTryTargetAPILock)) {
167 
168     if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope()) {
169       result.AppendError(GetInvalidTargetDescription());
170       return false;
171     }
172 
173     if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope()) {
174       if (!m_exe_ctx.HasTargetScope())
175         result.AppendError(GetInvalidTargetDescription());
176       else
177         result.AppendError(GetInvalidProcessDescription());
178       return false;
179     }
180 
181     if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope()) {
182       if (!m_exe_ctx.HasTargetScope())
183         result.AppendError(GetInvalidTargetDescription());
184       else if (!m_exe_ctx.HasProcessScope())
185         result.AppendError(GetInvalidProcessDescription());
186       else
187         result.AppendError(GetInvalidThreadDescription());
188       return false;
189     }
190 
191     if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope()) {
192       if (!m_exe_ctx.HasTargetScope())
193         result.AppendError(GetInvalidTargetDescription());
194       else if (!m_exe_ctx.HasProcessScope())
195         result.AppendError(GetInvalidProcessDescription());
196       else if (!m_exe_ctx.HasThreadScope())
197         result.AppendError(GetInvalidThreadDescription());
198       else
199         result.AppendError(GetInvalidFrameDescription());
200       return false;
201     }
202 
203     if ((flags & eCommandRequiresRegContext) &&
204         (m_exe_ctx.GetRegisterContext() == nullptr)) {
205       result.AppendError(GetInvalidRegContextDescription());
206       return false;
207     }
208 
209     if (flags & eCommandTryTargetAPILock) {
210       Target *target = m_exe_ctx.GetTargetPtr();
211       if (target)
212         m_api_locker =
213             std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
214     }
215   }
216 
217   if (GetFlags().AnySet(eCommandProcessMustBeLaunched |
218                         eCommandProcessMustBePaused)) {
219     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
220     if (process == nullptr) {
221       // A process that is not running is considered paused.
222       if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
223         result.AppendError("Process must exist.");
224         return false;
225       }
226     } else {
227       StateType state = process->GetState();
228       switch (state) {
229       case eStateInvalid:
230       case eStateSuspended:
231       case eStateCrashed:
232       case eStateStopped:
233         break;
234 
235       case eStateConnected:
236       case eStateAttaching:
237       case eStateLaunching:
238       case eStateDetached:
239       case eStateExited:
240       case eStateUnloaded:
241         if (GetFlags().Test(eCommandProcessMustBeLaunched)) {
242           result.AppendError("Process must be launched.");
243           return false;
244         }
245         break;
246 
247       case eStateRunning:
248       case eStateStepping:
249         if (GetFlags().Test(eCommandProcessMustBePaused)) {
250           result.AppendError("Process is running.  Use 'process interrupt' to "
251                              "pause execution.");
252           return false;
253         }
254       }
255     }
256   }
257 
258   if (GetFlags().Test(eCommandProcessMustBeTraced)) {
259     Target *target = m_exe_ctx.GetTargetPtr();
260     if (target && !target->GetTrace()) {
261       result.AppendError("Process is not being traced.");
262       return false;
263     }
264   }
265 
266   return true;
267 }
268 
269 void CommandObject::Cleanup() {
270   m_exe_ctx.Clear();
271   if (m_api_locker.owns_lock())
272     m_api_locker.unlock();
273 }
274 
275 void CommandObject::HandleCompletion(CompletionRequest &request) {
276 
277   m_exe_ctx = m_interpreter.GetExecutionContext();
278   auto reset_ctx = llvm::make_scope_exit([this]() { Cleanup(); });
279 
280   // Default implementation of WantsCompletion() is !WantsRawCommandString().
281   // Subclasses who want raw command string but desire, for example, argument
282   // completion should override WantsCompletion() to return true, instead.
283   if (WantsRawCommandString() && !WantsCompletion()) {
284     // FIXME: Abstract telling the completion to insert the completion
285     // character.
286     return;
287   } else {
288     // Can we do anything generic with the options?
289     Options *cur_options = GetOptions();
290     CommandReturnObject result(m_interpreter.GetDebugger().GetUseColor());
291     OptionElementVector opt_element_vector;
292 
293     if (cur_options != nullptr) {
294       opt_element_vector = cur_options->ParseForCompletion(
295           request.GetParsedLine(), request.GetCursorIndex());
296 
297       bool handled_by_options = cur_options->HandleOptionCompletion(
298           request, opt_element_vector, GetCommandInterpreter());
299       if (handled_by_options)
300         return;
301     }
302 
303     // If we got here, the last word is not an option or an option argument.
304     HandleArgumentCompletion(request, opt_element_vector);
305   }
306 }
307 
308 bool CommandObject::HelpTextContainsWord(llvm::StringRef search_word,
309                                          bool search_short_help,
310                                          bool search_long_help,
311                                          bool search_syntax,
312                                          bool search_options) {
313   std::string options_usage_help;
314 
315   bool found_word = false;
316 
317   llvm::StringRef short_help = GetHelp();
318   llvm::StringRef long_help = GetHelpLong();
319   llvm::StringRef syntax_help = GetSyntax();
320 
321   if (search_short_help && short_help.contains_insensitive(search_word))
322     found_word = true;
323   else if (search_long_help && long_help.contains_insensitive(search_word))
324     found_word = true;
325   else if (search_syntax && syntax_help.contains_insensitive(search_word))
326     found_word = true;
327 
328   if (!found_word && search_options && GetOptions() != nullptr) {
329     StreamString usage_help;
330     GetOptions()->GenerateOptionUsage(
331         usage_help, *this,
332         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
333     if (!usage_help.Empty()) {
334       llvm::StringRef usage_text = usage_help.GetString();
335       if (usage_text.contains_insensitive(search_word))
336         found_word = true;
337     }
338   }
339 
340   return found_word;
341 }
342 
343 bool CommandObject::ParseOptionsAndNotify(Args &args,
344                                           CommandReturnObject &result,
345                                           OptionGroupOptions &group_options,
346                                           ExecutionContext &exe_ctx) {
347   if (!ParseOptions(args, result))
348     return false;
349 
350   Status error(group_options.NotifyOptionParsingFinished(&exe_ctx));
351   if (error.Fail()) {
352     result.AppendError(error.AsCString());
353     return false;
354   }
355   return true;
356 }
357 
358 int CommandObject::GetNumArgumentEntries() { return m_arguments.size(); }
359 
360 CommandObject::CommandArgumentEntry *
361 CommandObject::GetArgumentEntryAtIndex(int idx) {
362   if (static_cast<size_t>(idx) < m_arguments.size())
363     return &(m_arguments[idx]);
364 
365   return nullptr;
366 }
367 
368 const CommandObject::ArgumentTableEntry *
369 CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) {
370   for (int i = 0; i < eArgTypeLastArg; ++i)
371     if (g_argument_table[i].arg_type == arg_type)
372       return &(g_argument_table[i]);
373 
374   return nullptr;
375 }
376 
377 void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type,
378                                     CommandInterpreter &interpreter) {
379   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
380 
381   // The table is *supposed* to be kept in arg_type order, but someone *could*
382   // have messed it up...
383 
384   if (entry->arg_type != arg_type)
385     entry = CommandObject::FindArgumentDataByType(arg_type);
386 
387   if (!entry)
388     return;
389 
390   StreamString name_str;
391   name_str.Printf("<%s>", entry->arg_name);
392 
393   if (entry->help_function) {
394     llvm::StringRef help_text = entry->help_function();
395     if (!entry->help_function.self_formatting) {
396       interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
397                                           help_text, name_str.GetSize());
398     } else {
399       interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text,
400                                  name_str.GetSize());
401     }
402   } else {
403     interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--",
404                                         entry->help_text, name_str.GetSize());
405 
406     // Print enum values and their description if any.
407     OptionEnumValues enum_values = g_argument_table[arg_type].enum_values;
408     if (!enum_values.empty()) {
409       str.EOL();
410       size_t longest = 0;
411       for (const OptionEnumValueElement &element : enum_values)
412         longest =
413             std::max(longest, llvm::StringRef(element.string_value).size());
414       str.IndentMore(5);
415       for (const OptionEnumValueElement &element : enum_values) {
416         str.Indent();
417         interpreter.OutputHelpText(str, element.string_value, ":",
418                                    element.usage, longest);
419       }
420       str.IndentLess(5);
421       str.EOL();
422     }
423   }
424 }
425 
426 const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
427   const ArgumentTableEntry *entry = &(g_argument_table[arg_type]);
428 
429   // The table is *supposed* to be kept in arg_type order, but someone *could*
430   // have messed it up...
431 
432   if (entry->arg_type != arg_type)
433     entry = CommandObject::FindArgumentDataByType(arg_type);
434 
435   if (entry)
436     return entry->arg_name;
437 
438   return nullptr;
439 }
440 
441 bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
442   return (arg_repeat_type == eArgRepeatPairPlain) ||
443          (arg_repeat_type == eArgRepeatPairOptional) ||
444          (arg_repeat_type == eArgRepeatPairPlus) ||
445          (arg_repeat_type == eArgRepeatPairStar) ||
446          (arg_repeat_type == eArgRepeatPairRange) ||
447          (arg_repeat_type == eArgRepeatPairRangeOptional);
448 }
449 
450 static CommandObject::CommandArgumentEntry
451 OptSetFiltered(uint32_t opt_set_mask,
452                CommandObject::CommandArgumentEntry &cmd_arg_entry) {
453   CommandObject::CommandArgumentEntry ret_val;
454   for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
455     if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
456       ret_val.push_back(cmd_arg_entry[i]);
457   return ret_val;
458 }
459 
460 // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means
461 // take all the argument data into account.  On rare cases where some argument
462 // sticks with certain option sets, this function returns the option set
463 // filtered args.
464 void CommandObject::GetFormattedCommandArguments(Stream &str,
465                                                  uint32_t opt_set_mask) {
466   int num_args = m_arguments.size();
467   for (int i = 0; i < num_args; ++i) {
468     if (i > 0)
469       str.Printf(" ");
470     CommandArgumentEntry arg_entry =
471         opt_set_mask == LLDB_OPT_SET_ALL
472             ? m_arguments[i]
473             : OptSetFiltered(opt_set_mask, m_arguments[i]);
474     // This argument is not associated with the current option set, so skip it.
475     if (arg_entry.empty())
476       continue;
477     int num_alternatives = arg_entry.size();
478 
479     if ((num_alternatives == 2) && IsPairType(arg_entry[0].arg_repetition)) {
480       const char *first_name = GetArgumentName(arg_entry[0].arg_type);
481       const char *second_name = GetArgumentName(arg_entry[1].arg_type);
482       switch (arg_entry[0].arg_repetition) {
483       case eArgRepeatPairPlain:
484         str.Printf("<%s> <%s>", first_name, second_name);
485         break;
486       case eArgRepeatPairOptional:
487         str.Printf("[<%s> <%s>]", first_name, second_name);
488         break;
489       case eArgRepeatPairPlus:
490         str.Printf("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name,
491                    first_name, second_name);
492         break;
493       case eArgRepeatPairStar:
494         str.Printf("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name,
495                    first_name, second_name);
496         break;
497       case eArgRepeatPairRange:
498         str.Printf("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name,
499                    first_name, second_name);
500         break;
501       case eArgRepeatPairRangeOptional:
502         str.Printf("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name,
503                    first_name, second_name);
504         break;
505       // Explicitly test for all the rest of the cases, so if new types get
506       // added we will notice the missing case statement(s).
507       case eArgRepeatPlain:
508       case eArgRepeatOptional:
509       case eArgRepeatPlus:
510       case eArgRepeatStar:
511       case eArgRepeatRange:
512         // These should not be reached, as they should fail the IsPairType test
513         // above.
514         break;
515       }
516     } else {
517       StreamString names;
518       for (int j = 0; j < num_alternatives; ++j) {
519         if (j > 0)
520           names.Printf(" | ");
521         names.Printf("%s", GetArgumentName(arg_entry[j].arg_type));
522       }
523 
524       std::string name_str = std::string(names.GetString());
525       switch (arg_entry[0].arg_repetition) {
526       case eArgRepeatPlain:
527         str.Printf("<%s>", name_str.c_str());
528         break;
529       case eArgRepeatPlus:
530         str.Printf("<%s> [<%s> [...]]", name_str.c_str(), name_str.c_str());
531         break;
532       case eArgRepeatStar:
533         str.Printf("[<%s> [<%s> [...]]]", name_str.c_str(), name_str.c_str());
534         break;
535       case eArgRepeatOptional:
536         str.Printf("[<%s>]", name_str.c_str());
537         break;
538       case eArgRepeatRange:
539         str.Printf("<%s_1> .. <%s_n>", name_str.c_str(), name_str.c_str());
540         break;
541       // Explicitly test for all the rest of the cases, so if new types get
542       // added we will notice the missing case statement(s).
543       case eArgRepeatPairPlain:
544       case eArgRepeatPairOptional:
545       case eArgRepeatPairPlus:
546       case eArgRepeatPairStar:
547       case eArgRepeatPairRange:
548       case eArgRepeatPairRangeOptional:
549         // These should not be hit, as they should pass the IsPairType test
550         // above, and control should have gone into the other branch of the if
551         // statement.
552         break;
553       }
554     }
555   }
556 }
557 
558 CommandArgumentType
559 CommandObject::LookupArgumentName(llvm::StringRef arg_name) {
560   CommandArgumentType return_type = eArgTypeLastArg;
561 
562   arg_name = arg_name.ltrim('<').rtrim('>');
563 
564   for (int i = 0; i < eArgTypeLastArg; ++i)
565     if (arg_name == g_argument_table[i].arg_name)
566       return_type = g_argument_table[i].arg_type;
567 
568   return return_type;
569 }
570 
571 void CommandObject::FormatLongHelpText(Stream &output_strm,
572                                        llvm::StringRef long_help) {
573   CommandInterpreter &interpreter = GetCommandInterpreter();
574   std::stringstream lineStream{std::string(long_help)};
575   std::string line;
576   while (std::getline(lineStream, line)) {
577     if (line.empty()) {
578       output_strm << "\n";
579       continue;
580     }
581     size_t result = line.find_first_not_of(" \t");
582     if (result == std::string::npos) {
583       result = 0;
584     }
585     std::string whitespace_prefix = line.substr(0, result);
586     std::string remainder = line.substr(result);
587     interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix,
588                                         remainder);
589   }
590 }
591 
592 void CommandObject::GenerateHelpText(CommandReturnObject &result) {
593   GenerateHelpText(result.GetOutputStream());
594 
595   result.SetStatus(eReturnStatusSuccessFinishNoResult);
596 }
597 
598 void CommandObject::GenerateHelpText(Stream &output_strm) {
599   CommandInterpreter &interpreter = GetCommandInterpreter();
600   std::string help_text(GetHelp());
601   if (WantsRawCommandString()) {
602     help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
603   }
604   interpreter.OutputFormattedHelpText(output_strm, "", help_text);
605   output_strm << "\nSyntax: " << GetSyntax() << "\n";
606   Options *options = GetOptions();
607   if (options != nullptr) {
608     options->GenerateOptionUsage(
609         output_strm, *this,
610         GetCommandInterpreter().GetDebugger().GetTerminalWidth());
611   }
612   llvm::StringRef long_help = GetHelpLong();
613   if (!long_help.empty()) {
614     FormatLongHelpText(output_strm, long_help);
615   }
616   if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0) {
617     if (WantsRawCommandString() && !WantsCompletion()) {
618       // Emit the message about using ' -- ' between the end of the command
619       // options and the raw input conditionally, i.e., only if the command
620       // object does not want completion.
621       interpreter.OutputFormattedHelpText(
622           output_strm, "", "",
623           "\nImportant Note: Because this command takes 'raw' input, if you "
624           "use any command options"
625           " you must use ' -- ' between the end of the command options and the "
626           "beginning of the raw input.",
627           1);
628     } else if (GetNumArgumentEntries() > 0) {
629       // Also emit a warning about using "--" in case you are using a command
630       // that takes options and arguments.
631       interpreter.OutputFormattedHelpText(
632           output_strm, "", "",
633           "\nThis command takes options and free-form arguments.  If your "
634           "arguments resemble"
635           " option specifiers (i.e., they start with a - or --), you must use "
636           "' -- ' between"
637           " the end of the command options and the beginning of the arguments.",
638           1);
639     }
640   }
641 }
642 
643 void CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg,
644                                        CommandArgumentType ID,
645                                        CommandArgumentType IDRange) {
646   CommandArgumentData id_arg;
647   CommandArgumentData id_range_arg;
648 
649   // Create the first variant for the first (and only) argument for this
650   // command.
651   id_arg.arg_type = ID;
652   id_arg.arg_repetition = eArgRepeatOptional;
653 
654   // Create the second variant for the first (and only) argument for this
655   // command.
656   id_range_arg.arg_type = IDRange;
657   id_range_arg.arg_repetition = eArgRepeatOptional;
658 
659   // The first (and only) argument for this command could be either an id or an
660   // id_range. Push both variants into the entry for the first argument for
661   // this command.
662   arg.push_back(id_arg);
663   arg.push_back(id_range_arg);
664 }
665 
666 const char *CommandObject::GetArgumentTypeAsCString(
667     const lldb::CommandArgumentType arg_type) {
668   assert(arg_type < eArgTypeLastArg &&
669          "Invalid argument type passed to GetArgumentTypeAsCString");
670   return g_argument_table[arg_type].arg_name;
671 }
672 
673 const char *CommandObject::GetArgumentDescriptionAsCString(
674     const lldb::CommandArgumentType arg_type) {
675   assert(arg_type < eArgTypeLastArg &&
676          "Invalid argument type passed to GetArgumentDescriptionAsCString");
677   return g_argument_table[arg_type].help_text;
678 }
679 
680 Target &CommandObject::GetDummyTarget() {
681   return m_interpreter.GetDebugger().GetDummyTarget();
682 }
683 
684 Target &CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy) {
685   return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
686 }
687 
688 Target &CommandObject::GetSelectedTarget() {
689   assert(m_flags.AnySet(eCommandRequiresTarget | eCommandProcessMustBePaused |
690                         eCommandProcessMustBeLaunched | eCommandRequiresFrame |
691                         eCommandRequiresThread | eCommandRequiresProcess |
692                         eCommandRequiresRegContext) &&
693          "GetSelectedTarget called from object that may have no target");
694   return *m_interpreter.GetDebugger().GetSelectedTarget();
695 }
696 
697 Thread *CommandObject::GetDefaultThread() {
698   Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
699   if (thread_to_use)
700     return thread_to_use;
701 
702   Process *process = m_exe_ctx.GetProcessPtr();
703   if (!process) {
704     Target *target = m_exe_ctx.GetTargetPtr();
705     if (!target) {
706       target = m_interpreter.GetDebugger().GetSelectedTarget().get();
707     }
708     if (target)
709       process = target->GetProcessSP().get();
710   }
711 
712   if (process)
713     return process->GetThreadList().GetSelectedThread().get();
714   else
715     return nullptr;
716 }
717 
718 bool CommandObjectParsed::Execute(const char *args_string,
719                                   CommandReturnObject &result) {
720   bool handled = false;
721   Args cmd_args(args_string);
722   if (HasOverrideCallback()) {
723     Args full_args(GetCommandName());
724     full_args.AppendArguments(cmd_args);
725     handled =
726         InvokeOverrideCallback(full_args.GetConstArgumentVector(), result);
727   }
728   if (!handled) {
729     for (auto entry : llvm::enumerate(cmd_args.entries())) {
730       const Args::ArgEntry &value = entry.value();
731       if (!value.ref().empty() && value.GetQuoteChar() == '`') {
732         // We have to put the backtick back in place for PreprocessCommand.
733         std::string opt_string = value.c_str();
734         Status error;
735         error = m_interpreter.PreprocessToken(opt_string);
736         if (error.Success())
737           cmd_args.ReplaceArgumentAtIndex(entry.index(), opt_string);
738       }
739     }
740 
741     if (CheckRequirements(result)) {
742       if (ParseOptions(cmd_args, result)) {
743         // Call the command-specific version of 'Execute', passing it the
744         // already processed arguments.
745         if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
746           result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
747                                         GetCommandName());
748           Cleanup();
749           return false;
750         }
751         handled = DoExecute(cmd_args, result);
752       }
753     }
754 
755     Cleanup();
756   }
757   return handled;
758 }
759 
760 bool CommandObjectRaw::Execute(const char *args_string,
761                                CommandReturnObject &result) {
762   bool handled = false;
763   if (HasOverrideCallback()) {
764     std::string full_command(GetCommandName());
765     full_command += ' ';
766     full_command += args_string;
767     const char *argv[2] = {nullptr, nullptr};
768     argv[0] = full_command.c_str();
769     handled = InvokeOverrideCallback(argv, result);
770   }
771   if (!handled) {
772     if (CheckRequirements(result))
773       handled = DoExecute(args_string, result);
774 
775     Cleanup();
776   }
777   return handled;
778 }
779