1 //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 // C++ Includes
12 #include <vector>
13 
14 // Other libraries and framework includes
15 // Project includes
16 #include "CommandObjectBreakpoint.h"
17 #include "CommandObjectBreakpointCommand.h"
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointIDList.h"
20 #include "lldb/Breakpoint/BreakpointLocation.h"
21 #include "lldb/Core/RegularExpression.h"
22 #include "lldb/Core/StreamString.h"
23 #include "lldb/Host/StringConvert.h"
24 #include "lldb/Interpreter/CommandCompletions.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/OptionValueBoolean.h"
28 #include "lldb/Interpreter/OptionValueString.h"
29 #include "lldb/Interpreter/OptionValueUInt64.h"
30 #include "lldb/Interpreter/Options.h"
31 #include "lldb/Target/Language.h"
32 #include "lldb/Target/StackFrame.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
35 #include "lldb/Target/ThreadSpec.h"
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
41                                      lldb::DescriptionLevel level) {
42   s->IndentMore();
43   bp->GetDescription(s, level, true);
44   s->IndentLess();
45   s->EOL();
46 }
47 
48 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
49 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
50 #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
51 #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
52 #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
53 #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
54 #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
55 #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
56 
57 static OptionDefinition g_breakpoint_set_options[] = {
58     // clang-format off
59   { LLDB_OPT_NOT_10,               false, "shlib",                  's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion,     eArgTypeShlibName,           "Set the breakpoint only in this shared library.  Can repeat this option "
60   "multiple times to specify multiple shared libraries." },
61   { LLDB_OPT_SET_ALL,              false, "ignore-count",           'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeCount,               "Set the number of times this breakpoint is skipped before stopping." },
62   { LLDB_OPT_SET_ALL,              false, "one-shot",               'o', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "The breakpoint is deleted the first time it causes a stop." },
63   { LLDB_OPT_SET_ALL,              false, "condition",              'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeExpression,          "The breakpoint stops only if this condition expression evaluates to true." },
64   { LLDB_OPT_SET_ALL,              false, "thread-index",           'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadIndex,         "The breakpoint stops only for the thread whose indeX matches this argument." },
65   { LLDB_OPT_SET_ALL,              false, "thread-id",              't', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadID,            "The breakpoint stops only for the thread whose TID matches this argument." },
66   { LLDB_OPT_SET_ALL,              false, "thread-name",            'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadName,          "The breakpoint stops only for the thread whose thread name matches this "
67   "argument." },
68   { LLDB_OPT_SET_ALL,              false, "hardware",               'H', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "Require the breakpoint to use hardware breakpoints." },
69   { LLDB_OPT_SET_ALL,              false, "queue-name",             'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeQueueName,           "The breakpoint stops only for threads in the queue whose name is given by "
70   "this argument." },
71   { LLDB_OPT_FILE,                 false, "file",                   'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,            "Specifies the source file in which to set this breakpoint.  Note, by default "
72   "lldb only looks for files that are #included if they use the standard include "
73   "file extensions.  To set breakpoints on .c/.cpp/.m/.mm files that are "
74   "#included, set target.inline-breakpoint-strategy to \"always\"." },
75   { LLDB_OPT_SET_1,                true,  "line",                   'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,             "Specifies the line number on which to set this breakpoint." },
76 
77   // Comment out this option for the moment, as we don't actually use it, but will in the future.
78   // This way users won't see it, but the infrastructure is left in place.
79   //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, nullptr, "<column>",
80   //    "Set the breakpoint by source location at this particular column."},
81 
82   { LLDB_OPT_SET_2,                true,  "address",                'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeAddressOrExpression, "Set the breakpoint at the specified address.  If the address maps uniquely to "
83   "a particular binary, then the address will be converted to a \"file\" "
84   "address, so that the breakpoint will track that binary+offset no matter where "
85   "the binary eventually loads.  Alternately, if you also specify the module - "
86   "with the -s option - then the address will be treated as a file address in "
87   "that module, and resolved accordingly.  Again, this will allow lldb to track "
88   "that offset on subsequent reloads.  The module need not have been loaded at "
89   "the time you specify this breakpoint, and will get resolved when the module "
90   "is loaded." },
91   { LLDB_OPT_SET_3,                true,  "name",                   'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion,     eArgTypeFunctionName,        "Set the breakpoint by function name.  Can be repeated multiple times to make "
92   "one breakpoint for multiple names" },
93   { LLDB_OPT_SET_9,                false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion,     eArgTypeFunctionName,        "When used with '-p' limits the source regex to source contained in the named "
94   "functions.  Can be repeated multiple times." },
95   { LLDB_OPT_SET_4,                true,  "fullname",               'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion,     eArgTypeFullName,            "Set the breakpoint by fully qualified function names. For C++ this means "
96   "namespaces and all arguments, and for Objective C this means a full function "
97   "prototype with class and selector.  Can be repeated multiple times to make "
98   "one breakpoint for multiple names." },
99   { LLDB_OPT_SET_5,                true,  "selector",               'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeSelector,            "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
100   "make one breakpoint for multiple Selectors." },
101   { LLDB_OPT_SET_6,                true,  "method",                 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeMethod,              "Set the breakpoint by C++ method names.  Can be repeated multiple times to "
102   "make one breakpoint for multiple methods." },
103   { LLDB_OPT_SET_7,                true,  "func-regex",             'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeRegularExpression,   "Set the breakpoint by function name, evaluating a regular-expression to find "
104   "the function name(s)." },
105   { LLDB_OPT_SET_8,                true,  "basename",               'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion,     eArgTypeFunctionName,        "Set the breakpoint by function basename (C++ namespaces and arguments will be "
106   "ignored).  Can be repeated multiple times to make one breakpoint for multiple "
107   "symbols." },
108   { LLDB_OPT_SET_9,                true,  "source-pattern-regexp",  'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeRegularExpression,   "Set the breakpoint by specifying a regular expression which is matched "
109   "against the source text in a source file or files specified with the -f "
110   "option.  The -f option can be specified more than once.  If no source files "
111   "are specified, uses the current \"default source file\".  If you want to "
112   "match against all source files, pass the \"--all-files\" option." },
113   { LLDB_OPT_SET_9,                false, "all-files",              'A', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "All files are searched for source pattern matches." },
114   { LLDB_OPT_SET_10,               true,  "language-exception",     'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLanguage,            "Set the breakpoint on exceptions thrown by the specified language (without "
115   "options, on throw but not catch.)" },
116   { LLDB_OPT_SET_10,               false, "on-throw",               'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception throW." },
117   { LLDB_OPT_SET_10,               false, "on-catch",               'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception catcH." },
118 
119   //  Don't add this option till it actually does something useful...
120   //    { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
121   //        "The breakpoint will only stop if an exception Object of this type is thrown.  Can be repeated multiple times to stop for multiple object types" },
122 
123   { LLDB_OPT_EXPR_LANGUAGE,        false, "language",               'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLanguage,            "Specifies the Language to use when interpreting the breakpoint's expression "
124   "(note: currently only implemented for setting breakpoints on identifiers).  "
125   "If not set the target.language setting is used." },
126   { LLDB_OPT_SKIP_PROLOGUE,        false, "skip-prologue",          'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "sKip the prologue if the breakpoint is at the beginning of a function.  "
127   "If not set the target.skip-prologue setting is used." },
128   { LLDB_OPT_SET_ALL,              false, "dummy-breakpoints",      'D', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, "
129   "which prime new targets." },
130   { LLDB_OPT_SET_ALL,              false, "breakpoint-name",        'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBreakpointName,      "Adds this to the list of names for this breakpoint." },
131   { LLDB_OPT_OFFSET_APPLIES,       false, "address-slide",          'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeAddress,             "Add the specified offset to whatever address(es) the breakpoint resolves to.  "
132   "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
133   { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument,   nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
134   "setting is used." },
135     // clang-format on
136 };
137 
138 //-------------------------------------------------------------------------
139 // CommandObjectBreakpointSet
140 //-------------------------------------------------------------------------
141 
142 class CommandObjectBreakpointSet : public CommandObjectParsed {
143 public:
144   typedef enum BreakpointSetType {
145     eSetTypeInvalid,
146     eSetTypeFileAndLine,
147     eSetTypeAddress,
148     eSetTypeFunctionName,
149     eSetTypeFunctionRegexp,
150     eSetTypeSourceRegexp,
151     eSetTypeException
152   } BreakpointSetType;
153 
154   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
155       : CommandObjectParsed(
156             interpreter, "breakpoint set",
157             "Sets a breakpoint or set of breakpoints in the executable.",
158             "breakpoint set <cmd-options>"),
159         m_options() {}
160 
161   ~CommandObjectBreakpointSet() override = default;
162 
163   Options *GetOptions() override { return &m_options; }
164 
165   class CommandOptions : public Options {
166   public:
167     CommandOptions()
168         : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
169           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
170           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
171           m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
172           m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
173           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
174           m_exception_language(eLanguageTypeUnknown),
175           m_language(lldb::eLanguageTypeUnknown),
176           m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
177           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
178 
179     ~CommandOptions() override = default;
180 
181     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
182                          ExecutionContext *execution_context) override {
183       Error error;
184       const int short_option = m_getopt_table[option_idx].val;
185       llvm::StringRef option_strref(option_arg ? option_arg : "");
186 
187       switch (short_option) {
188       case 'a': {
189         m_load_addr = Args::StringToAddress(execution_context, option_arg,
190                                             LLDB_INVALID_ADDRESS, &error);
191       } break;
192 
193       case 'A':
194         m_all_files = true;
195         break;
196 
197       case 'b':
198         m_func_names.push_back(option_arg);
199         m_func_name_type_mask |= eFunctionNameTypeBase;
200         break;
201 
202       case 'C': {
203         bool success;
204         m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success);
205         if (!success)
206           error.SetErrorStringWithFormat("invalid column number: %s",
207                                          option_arg);
208         break;
209       }
210 
211       case 'c':
212         m_condition.assign(option_arg);
213         break;
214 
215       case 'D':
216         m_use_dummy = true;
217         break;
218 
219       case 'E': {
220         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
221 
222         switch (language) {
223         case eLanguageTypeC89:
224         case eLanguageTypeC:
225         case eLanguageTypeC99:
226         case eLanguageTypeC11:
227           m_exception_language = eLanguageTypeC;
228           break;
229         case eLanguageTypeC_plus_plus:
230         case eLanguageTypeC_plus_plus_03:
231         case eLanguageTypeC_plus_plus_11:
232         case eLanguageTypeC_plus_plus_14:
233           m_exception_language = eLanguageTypeC_plus_plus;
234           break;
235         case eLanguageTypeObjC:
236           m_exception_language = eLanguageTypeObjC;
237           break;
238         case eLanguageTypeObjC_plus_plus:
239           error.SetErrorStringWithFormat(
240               "Set exception breakpoints separately for c++ and objective-c");
241           break;
242         case eLanguageTypeUnknown:
243           error.SetErrorStringWithFormat(
244               "Unknown language type: '%s' for exception breakpoint",
245               option_arg);
246           break;
247         default:
248           error.SetErrorStringWithFormat(
249               "Unsupported language type: '%s' for exception breakpoint",
250               option_arg);
251         }
252       } break;
253 
254       case 'f':
255         m_filenames.AppendIfUnique(FileSpec(option_arg, false));
256         break;
257 
258       case 'F':
259         m_func_names.push_back(option_arg);
260         m_func_name_type_mask |= eFunctionNameTypeFull;
261         break;
262 
263       case 'h': {
264         bool success;
265         m_catch_bp = Args::StringToBoolean(option_strref, true, &success);
266         if (!success)
267           error.SetErrorStringWithFormat(
268               "Invalid boolean value for on-catch option: '%s'", option_arg);
269       } break;
270 
271       case 'H':
272         m_hardware = true;
273         break;
274 
275       case 'i':
276         m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
277         if (m_ignore_count == UINT32_MAX)
278           error.SetErrorStringWithFormat("invalid ignore count '%s'",
279                                          option_arg);
280         break;
281 
282       case 'K': {
283         bool success;
284         bool value;
285         value = Args::StringToBoolean(option_strref, true, &success);
286         if (value)
287           m_skip_prologue = eLazyBoolYes;
288         else
289           m_skip_prologue = eLazyBoolNo;
290 
291         if (!success)
292           error.SetErrorStringWithFormat(
293               "Invalid boolean value for skip prologue option: '%s'",
294               option_arg);
295       } break;
296 
297       case 'l': {
298         bool success;
299         m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
300         if (!success)
301           error.SetErrorStringWithFormat("invalid line number: %s.",
302                                          option_arg);
303         break;
304       }
305 
306       case 'L':
307         m_language = Language::GetLanguageTypeFromString(option_arg);
308         if (m_language == eLanguageTypeUnknown)
309           error.SetErrorStringWithFormat(
310               "Unknown language type: '%s' for breakpoint", option_arg);
311         break;
312 
313       case 'm': {
314         bool success;
315         bool value;
316         value = Args::StringToBoolean(option_strref, true, &success);
317         if (value)
318           m_move_to_nearest_code = eLazyBoolYes;
319         else
320           m_move_to_nearest_code = eLazyBoolNo;
321 
322         if (!success)
323           error.SetErrorStringWithFormat(
324               "Invalid boolean value for move-to-nearest-code option: '%s'",
325               option_arg);
326         break;
327       }
328 
329       case 'M':
330         m_func_names.push_back(option_arg);
331         m_func_name_type_mask |= eFunctionNameTypeMethod;
332         break;
333 
334       case 'n':
335         m_func_names.push_back(option_arg);
336         m_func_name_type_mask |= eFunctionNameTypeAuto;
337         break;
338 
339       case 'N': {
340         if (BreakpointID::StringIsBreakpointName(option_strref, error))
341           m_breakpoint_names.push_back(option_arg);
342         else
343           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
344                                          option_arg);
345         break;
346       }
347 
348       case 'R': {
349         lldb::addr_t tmp_offset_addr;
350         tmp_offset_addr =
351             Args::StringToAddress(execution_context, option_arg, 0, &error);
352         if (error.Success())
353           m_offset_addr = tmp_offset_addr;
354       } break;
355 
356       case 'o':
357         m_one_shot = true;
358         break;
359 
360       case 'O':
361         m_exception_extra_args.AppendArgument(llvm::StringRef("-O"));
362         m_exception_extra_args.AppendArgument(option_strref);
363         break;
364 
365       case 'p':
366         m_source_text_regexp.assign(option_arg);
367         break;
368 
369       case 'q':
370         m_queue_name.assign(option_arg);
371         break;
372 
373       case 'r':
374         m_func_regexp.assign(option_arg);
375         break;
376 
377       case 's':
378         m_modules.AppendIfUnique(FileSpec(option_arg, false));
379         break;
380 
381       case 'S':
382         m_func_names.push_back(option_arg);
383         m_func_name_type_mask |= eFunctionNameTypeSelector;
384         break;
385 
386       case 't':
387         m_thread_id =
388             StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
389         if (m_thread_id == LLDB_INVALID_THREAD_ID)
390           error.SetErrorStringWithFormat("invalid thread id string '%s'",
391                                          option_arg);
392         break;
393 
394       case 'T':
395         m_thread_name.assign(option_arg);
396         break;
397 
398       case 'w': {
399         bool success;
400         m_throw_bp = Args::StringToBoolean(option_strref, true, &success);
401         if (!success)
402           error.SetErrorStringWithFormat(
403               "Invalid boolean value for on-throw option: '%s'", option_arg);
404       } break;
405 
406       case 'x':
407         m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
408         if (m_thread_id == UINT32_MAX)
409           error.SetErrorStringWithFormat("invalid thread index string '%s'",
410                                          option_arg);
411         break;
412 
413       case 'X':
414         m_source_regex_func_names.insert(option_arg);
415         break;
416 
417       default:
418         error.SetErrorStringWithFormat("unrecognized option '%c'",
419                                        short_option);
420         break;
421       }
422 
423       return error;
424     }
425 
426     void OptionParsingStarting(ExecutionContext *execution_context) override {
427       m_condition.clear();
428       m_filenames.Clear();
429       m_line_num = 0;
430       m_column = 0;
431       m_func_names.clear();
432       m_func_name_type_mask = eFunctionNameTypeNone;
433       m_func_regexp.clear();
434       m_source_text_regexp.clear();
435       m_modules.Clear();
436       m_load_addr = LLDB_INVALID_ADDRESS;
437       m_offset_addr = 0;
438       m_ignore_count = 0;
439       m_thread_id = LLDB_INVALID_THREAD_ID;
440       m_thread_index = UINT32_MAX;
441       m_thread_name.clear();
442       m_queue_name.clear();
443       m_catch_bp = false;
444       m_throw_bp = true;
445       m_hardware = false;
446       m_exception_language = eLanguageTypeUnknown;
447       m_language = lldb::eLanguageTypeUnknown;
448       m_skip_prologue = eLazyBoolCalculate;
449       m_one_shot = false;
450       m_use_dummy = false;
451       m_breakpoint_names.clear();
452       m_all_files = false;
453       m_exception_extra_args.Clear();
454       m_move_to_nearest_code = eLazyBoolCalculate;
455       m_source_regex_func_names.clear();
456     }
457 
458     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
459       return llvm::makeArrayRef(g_breakpoint_set_options);
460     }
461 
462     // Instance variables to hold the values for command options.
463 
464     std::string m_condition;
465     FileSpecList m_filenames;
466     uint32_t m_line_num;
467     uint32_t m_column;
468     std::vector<std::string> m_func_names;
469     std::vector<std::string> m_breakpoint_names;
470     uint32_t m_func_name_type_mask;
471     std::string m_func_regexp;
472     std::string m_source_text_regexp;
473     FileSpecList m_modules;
474     lldb::addr_t m_load_addr;
475     lldb::addr_t m_offset_addr;
476     uint32_t m_ignore_count;
477     lldb::tid_t m_thread_id;
478     uint32_t m_thread_index;
479     std::string m_thread_name;
480     std::string m_queue_name;
481     bool m_catch_bp;
482     bool m_throw_bp;
483     bool m_hardware; // Request to use hardware breakpoints
484     lldb::LanguageType m_exception_language;
485     lldb::LanguageType m_language;
486     LazyBool m_skip_prologue;
487     bool m_one_shot;
488     bool m_use_dummy;
489     bool m_all_files;
490     Args m_exception_extra_args;
491     LazyBool m_move_to_nearest_code;
492     std::unordered_set<std::string> m_source_regex_func_names;
493   };
494 
495 protected:
496   bool DoExecute(Args &command, CommandReturnObject &result) override {
497     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
498 
499     if (target == nullptr) {
500       result.AppendError("Invalid target.  Must set target before setting "
501                          "breakpoints (see 'target create' command).");
502       result.SetStatus(eReturnStatusFailed);
503       return false;
504     }
505 
506     // The following are the various types of breakpoints that could be set:
507     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
508     //   2).  -a  [-s -g]         (setting breakpoint by address)
509     //   3).  -n  [-s -g]         (setting breakpoint by function name)
510     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
511     //   expression)
512     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
513     //   to source text)
514     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
515     //   given language.)
516 
517     BreakpointSetType break_type = eSetTypeInvalid;
518 
519     if (m_options.m_line_num != 0)
520       break_type = eSetTypeFileAndLine;
521     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
522       break_type = eSetTypeAddress;
523     else if (!m_options.m_func_names.empty())
524       break_type = eSetTypeFunctionName;
525     else if (!m_options.m_func_regexp.empty())
526       break_type = eSetTypeFunctionRegexp;
527     else if (!m_options.m_source_text_regexp.empty())
528       break_type = eSetTypeSourceRegexp;
529     else if (m_options.m_exception_language != eLanguageTypeUnknown)
530       break_type = eSetTypeException;
531 
532     Breakpoint *bp = nullptr;
533     FileSpec module_spec;
534     const bool internal = false;
535 
536     // If the user didn't specify skip-prologue, having an offset should turn
537     // that off.
538     if (m_options.m_offset_addr != 0 &&
539         m_options.m_skip_prologue == eLazyBoolCalculate)
540       m_options.m_skip_prologue = eLazyBoolNo;
541 
542     switch (break_type) {
543     case eSetTypeFileAndLine: // Breakpoint by source position
544     {
545       FileSpec file;
546       const size_t num_files = m_options.m_filenames.GetSize();
547       if (num_files == 0) {
548         if (!GetDefaultFile(target, file, result)) {
549           result.AppendError("No file supplied and no default file available.");
550           result.SetStatus(eReturnStatusFailed);
551           return false;
552         }
553       } else if (num_files > 1) {
554         result.AppendError("Only one file at a time is allowed for file and "
555                            "line breakpoints.");
556         result.SetStatus(eReturnStatusFailed);
557         return false;
558       } else
559         file = m_options.m_filenames.GetFileSpecAtIndex(0);
560 
561       // Only check for inline functions if
562       LazyBool check_inlines = eLazyBoolCalculate;
563 
564       bp = target
565                ->CreateBreakpoint(&(m_options.m_modules), file,
566                                   m_options.m_line_num, m_options.m_offset_addr,
567                                   check_inlines, m_options.m_skip_prologue,
568                                   internal, m_options.m_hardware,
569                                   m_options.m_move_to_nearest_code)
570                .get();
571     } break;
572 
573     case eSetTypeAddress: // Breakpoint by address
574     {
575       // If a shared library has been specified, make an lldb_private::Address
576       // with the library, and
577       // use that.  That way the address breakpoint will track the load location
578       // of the library.
579       size_t num_modules_specified = m_options.m_modules.GetSize();
580       if (num_modules_specified == 1) {
581         const FileSpec *file_spec =
582             m_options.m_modules.GetFileSpecPointerAtIndex(0);
583         bp = target
584                  ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
585                                                    internal, file_spec,
586                                                    m_options.m_hardware)
587                  .get();
588       } else if (num_modules_specified == 0) {
589         bp = target
590                  ->CreateBreakpoint(m_options.m_load_addr, internal,
591                                     m_options.m_hardware)
592                  .get();
593       } else {
594         result.AppendError("Only one shared library can be specified for "
595                            "address breakpoints.");
596         result.SetStatus(eReturnStatusFailed);
597         return false;
598       }
599       break;
600     }
601     case eSetTypeFunctionName: // Breakpoint by function name
602     {
603       uint32_t name_type_mask = m_options.m_func_name_type_mask;
604 
605       if (name_type_mask == 0)
606         name_type_mask = eFunctionNameTypeAuto;
607 
608       bp = target
609                ->CreateBreakpoint(
610                    &(m_options.m_modules), &(m_options.m_filenames),
611                    m_options.m_func_names, name_type_mask, m_options.m_language,
612                    m_options.m_offset_addr, m_options.m_skip_prologue, internal,
613                    m_options.m_hardware)
614                .get();
615     } break;
616 
617     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
618                                  // name
619       {
620         RegularExpression regexp(m_options.m_func_regexp);
621         if (!regexp.IsValid()) {
622           char err_str[1024];
623           regexp.GetErrorAsCString(err_str, sizeof(err_str));
624           result.AppendErrorWithFormat(
625               "Function name regular expression could not be compiled: \"%s\"",
626               err_str);
627           result.SetStatus(eReturnStatusFailed);
628           return false;
629         }
630 
631         bp = target
632                  ->CreateFuncRegexBreakpoint(
633                      &(m_options.m_modules), &(m_options.m_filenames), regexp,
634                      m_options.m_language, m_options.m_skip_prologue, internal,
635                      m_options.m_hardware)
636                  .get();
637       }
638       break;
639     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
640     {
641       const size_t num_files = m_options.m_filenames.GetSize();
642 
643       if (num_files == 0 && !m_options.m_all_files) {
644         FileSpec file;
645         if (!GetDefaultFile(target, file, result)) {
646           result.AppendError(
647               "No files provided and could not find default file.");
648           result.SetStatus(eReturnStatusFailed);
649           return false;
650         } else {
651           m_options.m_filenames.Append(file);
652         }
653       }
654 
655       RegularExpression regexp(m_options.m_source_text_regexp);
656       if (!regexp.IsValid()) {
657         char err_str[1024];
658         regexp.GetErrorAsCString(err_str, sizeof(err_str));
659         result.AppendErrorWithFormat(
660             "Source text regular expression could not be compiled: \"%s\"",
661             err_str);
662         result.SetStatus(eReturnStatusFailed);
663         return false;
664       }
665       bp = target
666                ->CreateSourceRegexBreakpoint(
667                    &(m_options.m_modules), &(m_options.m_filenames),
668                    m_options.m_source_regex_func_names, regexp, internal,
669                    m_options.m_hardware, m_options.m_move_to_nearest_code)
670                .get();
671     } break;
672     case eSetTypeException: {
673       Error precond_error;
674       bp = target
675                ->CreateExceptionBreakpoint(
676                    m_options.m_exception_language, m_options.m_catch_bp,
677                    m_options.m_throw_bp, internal,
678                    &m_options.m_exception_extra_args, &precond_error)
679                .get();
680       if (precond_error.Fail()) {
681         result.AppendErrorWithFormat(
682             "Error setting extra exception arguments: %s",
683             precond_error.AsCString());
684         target->RemoveBreakpointByID(bp->GetID());
685         result.SetStatus(eReturnStatusFailed);
686         return false;
687       }
688     } break;
689     default:
690       break;
691     }
692 
693     // Now set the various options that were passed in:
694     if (bp) {
695       if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
696         bp->SetThreadID(m_options.m_thread_id);
697 
698       if (m_options.m_thread_index != UINT32_MAX)
699         bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
700 
701       if (!m_options.m_thread_name.empty())
702         bp->GetOptions()->GetThreadSpec()->SetName(
703             m_options.m_thread_name.c_str());
704 
705       if (!m_options.m_queue_name.empty())
706         bp->GetOptions()->GetThreadSpec()->SetQueueName(
707             m_options.m_queue_name.c_str());
708 
709       if (m_options.m_ignore_count != 0)
710         bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
711 
712       if (!m_options.m_condition.empty())
713         bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
714 
715       if (!m_options.m_breakpoint_names.empty()) {
716         Error name_error;
717         for (auto name : m_options.m_breakpoint_names) {
718           bp->AddName(name.c_str(), name_error);
719           if (name_error.Fail()) {
720             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
721                                          name.c_str());
722             target->RemoveBreakpointByID(bp->GetID());
723             result.SetStatus(eReturnStatusFailed);
724             return false;
725           }
726         }
727       }
728 
729       bp->SetOneShot(m_options.m_one_shot);
730     }
731 
732     if (bp) {
733       Stream &output_stream = result.GetOutputStream();
734       const bool show_locations = false;
735       bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
736                          show_locations);
737       if (target == m_interpreter.GetDebugger().GetDummyTarget())
738         output_stream.Printf("Breakpoint set in dummy target, will get copied "
739                              "into future targets.\n");
740       else {
741         // Don't print out this warning for exception breakpoints.  They can get
742         // set before the target
743         // is set, but we won't know how to actually set the breakpoint till we
744         // run.
745         if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
746           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
747                                "actual locations.\n");
748         }
749       }
750       result.SetStatus(eReturnStatusSuccessFinishResult);
751     } else if (!bp) {
752       result.AppendError("Breakpoint creation failed: No breakpoint created.");
753       result.SetStatus(eReturnStatusFailed);
754     }
755 
756     return result.Succeeded();
757   }
758 
759 private:
760   bool GetDefaultFile(Target *target, FileSpec &file,
761                       CommandReturnObject &result) {
762     uint32_t default_line;
763     // First use the Source Manager's default file.
764     // Then use the current stack frame's file.
765     if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
766       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
767       if (cur_frame == nullptr) {
768         result.AppendError(
769             "No selected frame to use to find the default file.");
770         result.SetStatus(eReturnStatusFailed);
771         return false;
772       } else if (!cur_frame->HasDebugInformation()) {
773         result.AppendError("Cannot use the selected frame to find the default "
774                            "file, it has no debug info.");
775         result.SetStatus(eReturnStatusFailed);
776         return false;
777       } else {
778         const SymbolContext &sc =
779             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
780         if (sc.line_entry.file) {
781           file = sc.line_entry.file;
782         } else {
783           result.AppendError("Can't find the file for the selected frame to "
784                              "use as the default file.");
785           result.SetStatus(eReturnStatusFailed);
786           return false;
787         }
788       }
789     }
790     return true;
791   }
792 
793   CommandOptions m_options;
794 };
795 
796 //-------------------------------------------------------------------------
797 // CommandObjectBreakpointModify
798 //-------------------------------------------------------------------------
799 
800 #pragma mark Modify::CommandOptions
801 static OptionDefinition g_breakpoint_modify_options[] = {
802     // clang-format off
803   { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,       "Set the number of times this breakpoint is skipped before stopping." },
804   { LLDB_OPT_SET_ALL, false, "one-shot",     'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,     "The breakpoint is deleted the first time it stop causes a stop." },
805   { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
806   { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID,    "The breakpoint stops only for the thread whose TID matches this argument." },
807   { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName,  "The breakpoint stops only for the thread whose thread name matches this argument." },
808   { LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName,   "The breakpoint stops only for threads in the queue whose name is given by this argument." },
809   { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression,  "The breakpoint stops only if this condition expression evaluates to true." },
810   { LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Enable the breakpoint." },
811   { LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Disable the breakpoint." },
812   { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument,  nullptr, nullptr, 0, eArgTypeNone,        "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
813     // clang-format on
814 };
815 
816 #pragma mark Modify
817 
818 class CommandObjectBreakpointModify : public CommandObjectParsed {
819 public:
820   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
821       : CommandObjectParsed(interpreter, "breakpoint modify",
822                             "Modify the options on a breakpoint or set of "
823                             "breakpoints in the executable.  "
824                             "If no breakpoint is specified, acts on the last "
825                             "created breakpoint.  "
826                             "With the exception of -e, -d and -i, passing an "
827                             "empty argument clears the modification.",
828                             nullptr),
829         m_options() {
830     CommandArgumentEntry arg;
831     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
832                                       eArgTypeBreakpointIDRange);
833     // Add the entry for the first argument for this command to the object's
834     // arguments vector.
835     m_arguments.push_back(arg);
836   }
837 
838   ~CommandObjectBreakpointModify() override = default;
839 
840   Options *GetOptions() override { return &m_options; }
841 
842   class CommandOptions : public Options {
843   public:
844     CommandOptions()
845         : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
846           m_thread_id_passed(false), m_thread_index(UINT32_MAX),
847           m_thread_index_passed(false), m_thread_name(), m_queue_name(),
848           m_condition(), m_one_shot(false), m_enable_passed(false),
849           m_enable_value(false), m_name_passed(false), m_queue_passed(false),
850           m_condition_passed(false), m_one_shot_passed(false),
851           m_use_dummy(false) {}
852 
853     ~CommandOptions() override = default;
854 
855     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
856                          ExecutionContext *execution_context) override {
857       Error error;
858       const int short_option = m_getopt_table[option_idx].val;
859 
860       switch (short_option) {
861       case 'c':
862         if (option_arg != nullptr)
863           m_condition.assign(option_arg);
864         else
865           m_condition.clear();
866         m_condition_passed = true;
867         break;
868       case 'd':
869         m_enable_passed = true;
870         m_enable_value = false;
871         break;
872       case 'D':
873         m_use_dummy = true;
874         break;
875       case 'e':
876         m_enable_passed = true;
877         m_enable_value = true;
878         break;
879       case 'i':
880         m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
881         if (m_ignore_count == UINT32_MAX)
882           error.SetErrorStringWithFormat("invalid ignore count '%s'",
883                                          option_arg);
884         break;
885       case 'o': {
886         bool value, success;
887         value = Args::StringToBoolean(
888             llvm::StringRef::withNullAsEmpty(option_arg), false, &success);
889         if (success) {
890           m_one_shot_passed = true;
891           m_one_shot = value;
892         } else
893           error.SetErrorStringWithFormat(
894               "invalid boolean value '%s' passed for -o option", option_arg);
895       } break;
896       case 't':
897         if (option_arg[0] == '\0') {
898           m_thread_id = LLDB_INVALID_THREAD_ID;
899           m_thread_id_passed = true;
900         } else {
901           m_thread_id =
902               StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
903           if (m_thread_id == LLDB_INVALID_THREAD_ID)
904             error.SetErrorStringWithFormat("invalid thread id string '%s'",
905                                            option_arg);
906           else
907             m_thread_id_passed = true;
908         }
909         break;
910       case 'T':
911         if (option_arg != nullptr)
912           m_thread_name.assign(option_arg);
913         else
914           m_thread_name.clear();
915         m_name_passed = true;
916         break;
917       case 'q':
918         if (option_arg != nullptr)
919           m_queue_name.assign(option_arg);
920         else
921           m_queue_name.clear();
922         m_queue_passed = true;
923         break;
924       case 'x':
925         if (option_arg[0] == '\n') {
926           m_thread_index = UINT32_MAX;
927           m_thread_index_passed = true;
928         } else {
929           m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
930           if (m_thread_id == UINT32_MAX)
931             error.SetErrorStringWithFormat("invalid thread index string '%s'",
932                                            option_arg);
933           else
934             m_thread_index_passed = true;
935         }
936         break;
937       default:
938         error.SetErrorStringWithFormat("unrecognized option '%c'",
939                                        short_option);
940         break;
941       }
942 
943       return error;
944     }
945 
946     void OptionParsingStarting(ExecutionContext *execution_context) override {
947       m_ignore_count = 0;
948       m_thread_id = LLDB_INVALID_THREAD_ID;
949       m_thread_id_passed = false;
950       m_thread_index = UINT32_MAX;
951       m_thread_index_passed = false;
952       m_thread_name.clear();
953       m_queue_name.clear();
954       m_condition.clear();
955       m_one_shot = false;
956       m_enable_passed = false;
957       m_queue_passed = false;
958       m_name_passed = false;
959       m_condition_passed = false;
960       m_one_shot_passed = false;
961       m_use_dummy = false;
962     }
963 
964     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
965       return llvm::makeArrayRef(g_breakpoint_modify_options);
966     }
967 
968     // Instance variables to hold the values for command options.
969 
970     uint32_t m_ignore_count;
971     lldb::tid_t m_thread_id;
972     bool m_thread_id_passed;
973     uint32_t m_thread_index;
974     bool m_thread_index_passed;
975     std::string m_thread_name;
976     std::string m_queue_name;
977     std::string m_condition;
978     bool m_one_shot;
979     bool m_enable_passed;
980     bool m_enable_value;
981     bool m_name_passed;
982     bool m_queue_passed;
983     bool m_condition_passed;
984     bool m_one_shot_passed;
985     bool m_use_dummy;
986   };
987 
988 protected:
989   bool DoExecute(Args &command, CommandReturnObject &result) override {
990     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
991     if (target == nullptr) {
992       result.AppendError("Invalid target.  No existing target or breakpoints.");
993       result.SetStatus(eReturnStatusFailed);
994       return false;
995     }
996 
997     std::unique_lock<std::recursive_mutex> lock;
998     target->GetBreakpointList().GetListMutex(lock);
999 
1000     BreakpointIDList valid_bp_ids;
1001 
1002     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1003         command, target, result, &valid_bp_ids);
1004 
1005     if (result.Succeeded()) {
1006       const size_t count = valid_bp_ids.GetSize();
1007       for (size_t i = 0; i < count; ++i) {
1008         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1009 
1010         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1011           Breakpoint *bp =
1012               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1013           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1014             BreakpointLocation *location =
1015                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1016             if (location) {
1017               if (m_options.m_thread_id_passed)
1018                 location->SetThreadID(m_options.m_thread_id);
1019 
1020               if (m_options.m_thread_index_passed)
1021                 location->SetThreadIndex(m_options.m_thread_index);
1022 
1023               if (m_options.m_name_passed)
1024                 location->SetThreadName(m_options.m_thread_name.c_str());
1025 
1026               if (m_options.m_queue_passed)
1027                 location->SetQueueName(m_options.m_queue_name.c_str());
1028 
1029               if (m_options.m_ignore_count != 0)
1030                 location->SetIgnoreCount(m_options.m_ignore_count);
1031 
1032               if (m_options.m_enable_passed)
1033                 location->SetEnabled(m_options.m_enable_value);
1034 
1035               if (m_options.m_condition_passed)
1036                 location->SetCondition(m_options.m_condition.c_str());
1037             }
1038           } else {
1039             if (m_options.m_thread_id_passed)
1040               bp->SetThreadID(m_options.m_thread_id);
1041 
1042             if (m_options.m_thread_index_passed)
1043               bp->SetThreadIndex(m_options.m_thread_index);
1044 
1045             if (m_options.m_name_passed)
1046               bp->SetThreadName(m_options.m_thread_name.c_str());
1047 
1048             if (m_options.m_queue_passed)
1049               bp->SetQueueName(m_options.m_queue_name.c_str());
1050 
1051             if (m_options.m_ignore_count != 0)
1052               bp->SetIgnoreCount(m_options.m_ignore_count);
1053 
1054             if (m_options.m_enable_passed)
1055               bp->SetEnabled(m_options.m_enable_value);
1056 
1057             if (m_options.m_condition_passed)
1058               bp->SetCondition(m_options.m_condition.c_str());
1059           }
1060         }
1061       }
1062     }
1063 
1064     return result.Succeeded();
1065   }
1066 
1067 private:
1068   CommandOptions m_options;
1069 };
1070 
1071 //-------------------------------------------------------------------------
1072 // CommandObjectBreakpointEnable
1073 //-------------------------------------------------------------------------
1074 #pragma mark Enable
1075 
1076 class CommandObjectBreakpointEnable : public CommandObjectParsed {
1077 public:
1078   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1079       : CommandObjectParsed(interpreter, "enable",
1080                             "Enable the specified disabled breakpoint(s). If "
1081                             "no breakpoints are specified, enable all of them.",
1082                             nullptr) {
1083     CommandArgumentEntry arg;
1084     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1085                                       eArgTypeBreakpointIDRange);
1086     // Add the entry for the first argument for this command to the object's
1087     // arguments vector.
1088     m_arguments.push_back(arg);
1089   }
1090 
1091   ~CommandObjectBreakpointEnable() override = default;
1092 
1093 protected:
1094   bool DoExecute(Args &command, CommandReturnObject &result) override {
1095     Target *target = GetSelectedOrDummyTarget();
1096     if (target == nullptr) {
1097       result.AppendError("Invalid target.  No existing target or breakpoints.");
1098       result.SetStatus(eReturnStatusFailed);
1099       return false;
1100     }
1101 
1102     std::unique_lock<std::recursive_mutex> lock;
1103     target->GetBreakpointList().GetListMutex(lock);
1104 
1105     const BreakpointList &breakpoints = target->GetBreakpointList();
1106 
1107     size_t num_breakpoints = breakpoints.GetSize();
1108 
1109     if (num_breakpoints == 0) {
1110       result.AppendError("No breakpoints exist to be enabled.");
1111       result.SetStatus(eReturnStatusFailed);
1112       return false;
1113     }
1114 
1115     if (command.GetArgumentCount() == 0) {
1116       // No breakpoint selected; enable all currently set breakpoints.
1117       target->EnableAllBreakpoints();
1118       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1119                                      " breakpoints)\n",
1120                                      (uint64_t)num_breakpoints);
1121       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1122     } else {
1123       // Particular breakpoint selected; enable that breakpoint.
1124       BreakpointIDList valid_bp_ids;
1125       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1126           command, target, result, &valid_bp_ids);
1127 
1128       if (result.Succeeded()) {
1129         int enable_count = 0;
1130         int loc_count = 0;
1131         const size_t count = valid_bp_ids.GetSize();
1132         for (size_t i = 0; i < count; ++i) {
1133           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1134 
1135           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1136             Breakpoint *breakpoint =
1137                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1138             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1139               BreakpointLocation *location =
1140                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1141               if (location) {
1142                 location->SetEnabled(true);
1143                 ++loc_count;
1144               }
1145             } else {
1146               breakpoint->SetEnabled(true);
1147               ++enable_count;
1148             }
1149           }
1150         }
1151         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1152                                        enable_count + loc_count);
1153         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1154       }
1155     }
1156 
1157     return result.Succeeded();
1158   }
1159 };
1160 
1161 //-------------------------------------------------------------------------
1162 // CommandObjectBreakpointDisable
1163 //-------------------------------------------------------------------------
1164 #pragma mark Disable
1165 
1166 class CommandObjectBreakpointDisable : public CommandObjectParsed {
1167 public:
1168   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1169       : CommandObjectParsed(
1170             interpreter, "breakpoint disable",
1171             "Disable the specified breakpoint(s) without deleting "
1172             "them.  If none are specified, disable all "
1173             "breakpoints.",
1174             nullptr) {
1175     SetHelpLong(
1176         "Disable the specified breakpoint(s) without deleting them.  \
1177 If none are specified, disable all breakpoints."
1178         R"(
1179 
1180 )"
1181         "Note: disabling a breakpoint will cause none of its locations to be hit \
1182 regardless of whether individual locations are enabled or disabled.  After the sequence:"
1183         R"(
1184 
1185     (lldb) break disable 1
1186     (lldb) break enable 1.1
1187 
1188 execution will NOT stop at location 1.1.  To achieve that, type:
1189 
1190     (lldb) break disable 1.*
1191     (lldb) break enable 1.1
1192 
1193 )"
1194         "The first command disables all locations for breakpoint 1, \
1195 the second re-enables the first location.");
1196 
1197     CommandArgumentEntry arg;
1198     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1199                                       eArgTypeBreakpointIDRange);
1200     // Add the entry for the first argument for this command to the object's
1201     // arguments vector.
1202     m_arguments.push_back(arg);
1203   }
1204 
1205   ~CommandObjectBreakpointDisable() override = default;
1206 
1207 protected:
1208   bool DoExecute(Args &command, CommandReturnObject &result) override {
1209     Target *target = GetSelectedOrDummyTarget();
1210     if (target == nullptr) {
1211       result.AppendError("Invalid target.  No existing target or breakpoints.");
1212       result.SetStatus(eReturnStatusFailed);
1213       return false;
1214     }
1215 
1216     std::unique_lock<std::recursive_mutex> lock;
1217     target->GetBreakpointList().GetListMutex(lock);
1218 
1219     const BreakpointList &breakpoints = target->GetBreakpointList();
1220     size_t num_breakpoints = breakpoints.GetSize();
1221 
1222     if (num_breakpoints == 0) {
1223       result.AppendError("No breakpoints exist to be disabled.");
1224       result.SetStatus(eReturnStatusFailed);
1225       return false;
1226     }
1227 
1228     if (command.GetArgumentCount() == 0) {
1229       // No breakpoint selected; disable all currently set breakpoints.
1230       target->DisableAllBreakpoints();
1231       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1232                                      " breakpoints)\n",
1233                                      (uint64_t)num_breakpoints);
1234       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1235     } else {
1236       // Particular breakpoint selected; disable that breakpoint.
1237       BreakpointIDList valid_bp_ids;
1238 
1239       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1240           command, target, result, &valid_bp_ids);
1241 
1242       if (result.Succeeded()) {
1243         int disable_count = 0;
1244         int loc_count = 0;
1245         const size_t count = valid_bp_ids.GetSize();
1246         for (size_t i = 0; i < count; ++i) {
1247           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1248 
1249           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1250             Breakpoint *breakpoint =
1251                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1252             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1253               BreakpointLocation *location =
1254                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1255               if (location) {
1256                 location->SetEnabled(false);
1257                 ++loc_count;
1258               }
1259             } else {
1260               breakpoint->SetEnabled(false);
1261               ++disable_count;
1262             }
1263           }
1264         }
1265         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1266                                        disable_count + loc_count);
1267         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1268       }
1269     }
1270 
1271     return result.Succeeded();
1272   }
1273 };
1274 
1275 //-------------------------------------------------------------------------
1276 // CommandObjectBreakpointList
1277 //-------------------------------------------------------------------------
1278 
1279 #pragma mark List::CommandOptions
1280 static OptionDefinition g_breakpoint_list_options[] = {
1281     // clang-format off
1282   { LLDB_OPT_SET_ALL, false, "internal",          'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1283   { LLDB_OPT_SET_1,   false, "brief",             'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1284   // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1285   // But I need to see it for now, and don't want to wait.
1286   { LLDB_OPT_SET_2,   false, "full",              'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1287   { LLDB_OPT_SET_3,   false, "verbose",           'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1288   { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1289     // clang-format on
1290 };
1291 
1292 #pragma mark List
1293 
1294 class CommandObjectBreakpointList : public CommandObjectParsed {
1295 public:
1296   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1297       : CommandObjectParsed(
1298             interpreter, "breakpoint list",
1299             "List some or all breakpoints at configurable levels of detail.",
1300             nullptr),
1301         m_options() {
1302     CommandArgumentEntry arg;
1303     CommandArgumentData bp_id_arg;
1304 
1305     // Define the first (and only) variant of this arg.
1306     bp_id_arg.arg_type = eArgTypeBreakpointID;
1307     bp_id_arg.arg_repetition = eArgRepeatOptional;
1308 
1309     // There is only one variant this argument could be; put it into the
1310     // argument entry.
1311     arg.push_back(bp_id_arg);
1312 
1313     // Push the data for the first argument into the m_arguments vector.
1314     m_arguments.push_back(arg);
1315   }
1316 
1317   ~CommandObjectBreakpointList() override = default;
1318 
1319   Options *GetOptions() override { return &m_options; }
1320 
1321   class CommandOptions : public Options {
1322   public:
1323     CommandOptions()
1324         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1325     }
1326 
1327     ~CommandOptions() override = default;
1328 
1329     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1330                          ExecutionContext *execution_context) override {
1331       Error error;
1332       const int short_option = m_getopt_table[option_idx].val;
1333 
1334       switch (short_option) {
1335       case 'b':
1336         m_level = lldb::eDescriptionLevelBrief;
1337         break;
1338       case 'D':
1339         m_use_dummy = true;
1340         break;
1341       case 'f':
1342         m_level = lldb::eDescriptionLevelFull;
1343         break;
1344       case 'v':
1345         m_level = lldb::eDescriptionLevelVerbose;
1346         break;
1347       case 'i':
1348         m_internal = true;
1349         break;
1350       default:
1351         error.SetErrorStringWithFormat("unrecognized option '%c'",
1352                                        short_option);
1353         break;
1354       }
1355 
1356       return error;
1357     }
1358 
1359     void OptionParsingStarting(ExecutionContext *execution_context) override {
1360       m_level = lldb::eDescriptionLevelFull;
1361       m_internal = false;
1362       m_use_dummy = false;
1363     }
1364 
1365     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1366       return llvm::makeArrayRef(g_breakpoint_list_options);
1367     }
1368 
1369     // Instance variables to hold the values for command options.
1370 
1371     lldb::DescriptionLevel m_level;
1372 
1373     bool m_internal;
1374     bool m_use_dummy;
1375   };
1376 
1377 protected:
1378   bool DoExecute(Args &command, CommandReturnObject &result) override {
1379     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1380 
1381     if (target == nullptr) {
1382       result.AppendError("Invalid target. No current target or breakpoints.");
1383       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1384       return true;
1385     }
1386 
1387     const BreakpointList &breakpoints =
1388         target->GetBreakpointList(m_options.m_internal);
1389     std::unique_lock<std::recursive_mutex> lock;
1390     target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1391 
1392     size_t num_breakpoints = breakpoints.GetSize();
1393 
1394     if (num_breakpoints == 0) {
1395       result.AppendMessage("No breakpoints currently set.");
1396       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1397       return true;
1398     }
1399 
1400     Stream &output_stream = result.GetOutputStream();
1401 
1402     if (command.GetArgumentCount() == 0) {
1403       // No breakpoint selected; show info about all currently set breakpoints.
1404       result.AppendMessage("Current breakpoints:");
1405       for (size_t i = 0; i < num_breakpoints; ++i) {
1406         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1407         AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1408       }
1409       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1410     } else {
1411       // Particular breakpoints selected; show info about that breakpoint.
1412       BreakpointIDList valid_bp_ids;
1413       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1414           command, target, result, &valid_bp_ids);
1415 
1416       if (result.Succeeded()) {
1417         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1418           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1419           Breakpoint *breakpoint =
1420               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1421           AddBreakpointDescription(&output_stream, breakpoint,
1422                                    m_options.m_level);
1423         }
1424         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1425       } else {
1426         result.AppendError("Invalid breakpoint ID.");
1427         result.SetStatus(eReturnStatusFailed);
1428       }
1429     }
1430 
1431     return result.Succeeded();
1432   }
1433 
1434 private:
1435   CommandOptions m_options;
1436 };
1437 
1438 //-------------------------------------------------------------------------
1439 // CommandObjectBreakpointClear
1440 //-------------------------------------------------------------------------
1441 #pragma mark Clear::CommandOptions
1442 
1443 static OptionDefinition g_breakpoint_clear_options[] = {
1444     // clang-format off
1445   { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1446   { LLDB_OPT_SET_1, true,  "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,  "Specify the breakpoint by source location at this particular line." }
1447     // clang-format on
1448 };
1449 
1450 #pragma mark Clear
1451 
1452 class CommandObjectBreakpointClear : public CommandObjectParsed {
1453 public:
1454   typedef enum BreakpointClearType {
1455     eClearTypeInvalid,
1456     eClearTypeFileAndLine
1457   } BreakpointClearType;
1458 
1459   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1460       : CommandObjectParsed(interpreter, "breakpoint clear",
1461                             "Delete or disable breakpoints matching the "
1462                             "specified source file and line.",
1463                             "breakpoint clear <cmd-options>"),
1464         m_options() {}
1465 
1466   ~CommandObjectBreakpointClear() override = default;
1467 
1468   Options *GetOptions() override { return &m_options; }
1469 
1470   class CommandOptions : public Options {
1471   public:
1472     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1473 
1474     ~CommandOptions() override = default;
1475 
1476     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1477                          ExecutionContext *execution_context) override {
1478       Error error;
1479       const int short_option = m_getopt_table[option_idx].val;
1480 
1481       switch (short_option) {
1482       case 'f':
1483         m_filename.assign(option_arg);
1484         break;
1485 
1486       case 'l':
1487         m_line_num = StringConvert::ToUInt32(option_arg, 0);
1488         break;
1489 
1490       default:
1491         error.SetErrorStringWithFormat("unrecognized option '%c'",
1492                                        short_option);
1493         break;
1494       }
1495 
1496       return error;
1497     }
1498 
1499     void OptionParsingStarting(ExecutionContext *execution_context) override {
1500       m_filename.clear();
1501       m_line_num = 0;
1502     }
1503 
1504     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1505       return llvm::makeArrayRef(g_breakpoint_clear_options);
1506     }
1507 
1508     // Instance variables to hold the values for command options.
1509 
1510     std::string m_filename;
1511     uint32_t m_line_num;
1512   };
1513 
1514 protected:
1515   bool DoExecute(Args &command, CommandReturnObject &result) override {
1516     Target *target = GetSelectedOrDummyTarget();
1517     if (target == nullptr) {
1518       result.AppendError("Invalid target. No existing target or breakpoints.");
1519       result.SetStatus(eReturnStatusFailed);
1520       return false;
1521     }
1522 
1523     // The following are the various types of breakpoints that could be cleared:
1524     //   1). -f -l (clearing breakpoint by source location)
1525 
1526     BreakpointClearType break_type = eClearTypeInvalid;
1527 
1528     if (m_options.m_line_num != 0)
1529       break_type = eClearTypeFileAndLine;
1530 
1531     std::unique_lock<std::recursive_mutex> lock;
1532     target->GetBreakpointList().GetListMutex(lock);
1533 
1534     BreakpointList &breakpoints = target->GetBreakpointList();
1535     size_t num_breakpoints = breakpoints.GetSize();
1536 
1537     // Early return if there's no breakpoint at all.
1538     if (num_breakpoints == 0) {
1539       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1540       result.SetStatus(eReturnStatusFailed);
1541       return result.Succeeded();
1542     }
1543 
1544     // Find matching breakpoints and delete them.
1545 
1546     // First create a copy of all the IDs.
1547     std::vector<break_id_t> BreakIDs;
1548     for (size_t i = 0; i < num_breakpoints; ++i)
1549       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1550 
1551     int num_cleared = 0;
1552     StreamString ss;
1553     switch (break_type) {
1554     case eClearTypeFileAndLine: // Breakpoint by source position
1555     {
1556       const ConstString filename(m_options.m_filename.c_str());
1557       BreakpointLocationCollection loc_coll;
1558 
1559       for (size_t i = 0; i < num_breakpoints; ++i) {
1560         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1561 
1562         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1563           // If the collection size is 0, it's a full match and we can just
1564           // remove the breakpoint.
1565           if (loc_coll.GetSize() == 0) {
1566             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1567             ss.EOL();
1568             target->RemoveBreakpointByID(bp->GetID());
1569             ++num_cleared;
1570           }
1571         }
1572       }
1573     } break;
1574 
1575     default:
1576       break;
1577     }
1578 
1579     if (num_cleared > 0) {
1580       Stream &output_stream = result.GetOutputStream();
1581       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1582       output_stream << ss.GetData();
1583       output_stream.EOL();
1584       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1585     } else {
1586       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1587       result.SetStatus(eReturnStatusFailed);
1588     }
1589 
1590     return result.Succeeded();
1591   }
1592 
1593 private:
1594   CommandOptions m_options;
1595 };
1596 
1597 //-------------------------------------------------------------------------
1598 // CommandObjectBreakpointDelete
1599 //-------------------------------------------------------------------------
1600 static OptionDefinition g_breakpoint_delete_options[] = {
1601     // clang-format off
1602   { LLDB_OPT_SET_1, false, "force",             'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1603   { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1604     // clang-format on
1605 };
1606 
1607 #pragma mark Delete
1608 
1609 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1610 public:
1611   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1612       : CommandObjectParsed(interpreter, "breakpoint delete",
1613                             "Delete the specified breakpoint(s).  If no "
1614                             "breakpoints are specified, delete them all.",
1615                             nullptr),
1616         m_options() {
1617     CommandArgumentEntry arg;
1618     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1619                                       eArgTypeBreakpointIDRange);
1620     // Add the entry for the first argument for this command to the object's
1621     // arguments vector.
1622     m_arguments.push_back(arg);
1623   }
1624 
1625   ~CommandObjectBreakpointDelete() override = default;
1626 
1627   Options *GetOptions() override { return &m_options; }
1628 
1629   class CommandOptions : public Options {
1630   public:
1631     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1632 
1633     ~CommandOptions() override = default;
1634 
1635     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1636                          ExecutionContext *execution_context) override {
1637       Error error;
1638       const int short_option = m_getopt_table[option_idx].val;
1639 
1640       switch (short_option) {
1641       case 'f':
1642         m_force = true;
1643         break;
1644 
1645       case 'D':
1646         m_use_dummy = true;
1647         break;
1648 
1649       default:
1650         error.SetErrorStringWithFormat("unrecognized option '%c'",
1651                                        short_option);
1652         break;
1653       }
1654 
1655       return error;
1656     }
1657 
1658     void OptionParsingStarting(ExecutionContext *execution_context) override {
1659       m_use_dummy = false;
1660       m_force = false;
1661     }
1662 
1663     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1664       return llvm::makeArrayRef(g_breakpoint_delete_options);
1665     }
1666 
1667     // Instance variables to hold the values for command options.
1668     bool m_use_dummy;
1669     bool m_force;
1670   };
1671 
1672 protected:
1673   bool DoExecute(Args &command, CommandReturnObject &result) override {
1674     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1675 
1676     if (target == nullptr) {
1677       result.AppendError("Invalid target. No existing target or breakpoints.");
1678       result.SetStatus(eReturnStatusFailed);
1679       return false;
1680     }
1681 
1682     std::unique_lock<std::recursive_mutex> lock;
1683     target->GetBreakpointList().GetListMutex(lock);
1684 
1685     const BreakpointList &breakpoints = target->GetBreakpointList();
1686 
1687     size_t num_breakpoints = breakpoints.GetSize();
1688 
1689     if (num_breakpoints == 0) {
1690       result.AppendError("No breakpoints exist to be deleted.");
1691       result.SetStatus(eReturnStatusFailed);
1692       return false;
1693     }
1694 
1695     if (command.GetArgumentCount() == 0) {
1696       if (!m_options.m_force &&
1697           !m_interpreter.Confirm(
1698               "About to delete all breakpoints, do you want to do that?",
1699               true)) {
1700         result.AppendMessage("Operation cancelled...");
1701       } else {
1702         target->RemoveAllBreakpoints();
1703         result.AppendMessageWithFormat(
1704             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1705             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1706       }
1707       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1708     } else {
1709       // Particular breakpoint selected; disable that breakpoint.
1710       BreakpointIDList valid_bp_ids;
1711       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1712           command, target, result, &valid_bp_ids);
1713 
1714       if (result.Succeeded()) {
1715         int delete_count = 0;
1716         int disable_count = 0;
1717         const size_t count = valid_bp_ids.GetSize();
1718         for (size_t i = 0; i < count; ++i) {
1719           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1720 
1721           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1722             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1723               Breakpoint *breakpoint =
1724                   target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1725               BreakpointLocation *location =
1726                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1727               // It makes no sense to try to delete individual locations, so we
1728               // disable them instead.
1729               if (location) {
1730                 location->SetEnabled(false);
1731                 ++disable_count;
1732               }
1733             } else {
1734               target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1735               ++delete_count;
1736             }
1737           }
1738         }
1739         result.AppendMessageWithFormat(
1740             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1741             delete_count, disable_count);
1742         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1743       }
1744     }
1745     return result.Succeeded();
1746   }
1747 
1748 private:
1749   CommandOptions m_options;
1750 };
1751 
1752 //-------------------------------------------------------------------------
1753 // CommandObjectBreakpointName
1754 //-------------------------------------------------------------------------
1755 
1756 static OptionDefinition g_breakpoint_name_options[] = {
1757     // clang-format off
1758   {LLDB_OPT_SET_1,   false, "name",              'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1759   {LLDB_OPT_SET_2,   false, "breakpoint-id",     'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID,   "Specify a breakpoint ID to use."},
1760   {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,           "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1761     // clang-format on
1762 };
1763 class BreakpointNameOptionGroup : public OptionGroup {
1764 public:
1765   BreakpointNameOptionGroup()
1766       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1767   }
1768 
1769   ~BreakpointNameOptionGroup() override = default;
1770 
1771   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1772     return llvm::makeArrayRef(g_breakpoint_name_options);
1773   }
1774 
1775   Error SetOptionValue(uint32_t option_idx, const char *option_value,
1776                        ExecutionContext *execution_context) override {
1777     Error error;
1778     const int short_option = g_breakpoint_name_options[option_idx].short_option;
1779     llvm::StringRef option_strref(option_value ? option_value : "");
1780 
1781     switch (short_option) {
1782     case 'N':
1783       if (BreakpointID::StringIsBreakpointName(option_strref, error) &&
1784           error.Success())
1785         m_name.SetValueFromString(option_strref);
1786       break;
1787 
1788     case 'B':
1789       if (m_breakpoint.SetValueFromString(option_value).Fail())
1790         error.SetErrorStringWithFormat(
1791             "unrecognized value \"%s\" for breakpoint", option_value);
1792       break;
1793     case 'D':
1794       if (m_use_dummy.SetValueFromString(option_value).Fail())
1795         error.SetErrorStringWithFormat(
1796             "unrecognized value \"%s\" for use-dummy", option_value);
1797       break;
1798 
1799     default:
1800       error.SetErrorStringWithFormat("unrecognized short option '%c'",
1801                                      short_option);
1802       break;
1803     }
1804     return error;
1805   }
1806 
1807   void OptionParsingStarting(ExecutionContext *execution_context) override {
1808     m_name.Clear();
1809     m_breakpoint.Clear();
1810     m_use_dummy.Clear();
1811     m_use_dummy.SetDefaultValue(false);
1812   }
1813 
1814   OptionValueString m_name;
1815   OptionValueUInt64 m_breakpoint;
1816   OptionValueBoolean m_use_dummy;
1817 };
1818 
1819 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1820 public:
1821   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1822       : CommandObjectParsed(
1823             interpreter, "add", "Add a name to the breakpoints provided.",
1824             "breakpoint name add <command-options> <breakpoint-id-list>"),
1825         m_name_options(), m_option_group() {
1826     // Create the first variant for the first (and only) argument for this
1827     // command.
1828     CommandArgumentEntry arg1;
1829     CommandArgumentData id_arg;
1830     id_arg.arg_type = eArgTypeBreakpointID;
1831     id_arg.arg_repetition = eArgRepeatOptional;
1832     arg1.push_back(id_arg);
1833     m_arguments.push_back(arg1);
1834 
1835     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1836     m_option_group.Finalize();
1837   }
1838 
1839   ~CommandObjectBreakpointNameAdd() override = default;
1840 
1841   Options *GetOptions() override { return &m_option_group; }
1842 
1843 protected:
1844   bool DoExecute(Args &command, CommandReturnObject &result) override {
1845     if (!m_name_options.m_name.OptionWasSet()) {
1846       result.SetError("No name option provided.");
1847       return false;
1848     }
1849 
1850     Target *target =
1851         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1852 
1853     if (target == nullptr) {
1854       result.AppendError("Invalid target. No existing target or breakpoints.");
1855       result.SetStatus(eReturnStatusFailed);
1856       return false;
1857     }
1858 
1859     std::unique_lock<std::recursive_mutex> lock;
1860     target->GetBreakpointList().GetListMutex(lock);
1861 
1862     const BreakpointList &breakpoints = target->GetBreakpointList();
1863 
1864     size_t num_breakpoints = breakpoints.GetSize();
1865     if (num_breakpoints == 0) {
1866       result.SetError("No breakpoints, cannot add names.");
1867       result.SetStatus(eReturnStatusFailed);
1868       return false;
1869     }
1870 
1871     // Particular breakpoint selected; disable that breakpoint.
1872     BreakpointIDList valid_bp_ids;
1873     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1874         command, target, result, &valid_bp_ids);
1875 
1876     if (result.Succeeded()) {
1877       if (valid_bp_ids.GetSize() == 0) {
1878         result.SetError("No breakpoints specified, cannot add names.");
1879         result.SetStatus(eReturnStatusFailed);
1880         return false;
1881       }
1882       size_t num_valid_ids = valid_bp_ids.GetSize();
1883       for (size_t index = 0; index < num_valid_ids; index++) {
1884         lldb::break_id_t bp_id =
1885             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1886         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1887         Error error; // We don't need to check the error here, since the option
1888                      // parser checked it...
1889         bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1890       }
1891     }
1892 
1893     return true;
1894   }
1895 
1896 private:
1897   BreakpointNameOptionGroup m_name_options;
1898   OptionGroupOptions m_option_group;
1899 };
1900 
1901 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1902 public:
1903   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1904       : CommandObjectParsed(
1905             interpreter, "delete",
1906             "Delete a name from the breakpoints provided.",
1907             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1908         m_name_options(), m_option_group() {
1909     // Create the first variant for the first (and only) argument for this
1910     // command.
1911     CommandArgumentEntry arg1;
1912     CommandArgumentData id_arg;
1913     id_arg.arg_type = eArgTypeBreakpointID;
1914     id_arg.arg_repetition = eArgRepeatOptional;
1915     arg1.push_back(id_arg);
1916     m_arguments.push_back(arg1);
1917 
1918     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1919     m_option_group.Finalize();
1920   }
1921 
1922   ~CommandObjectBreakpointNameDelete() override = default;
1923 
1924   Options *GetOptions() override { return &m_option_group; }
1925 
1926 protected:
1927   bool DoExecute(Args &command, CommandReturnObject &result) override {
1928     if (!m_name_options.m_name.OptionWasSet()) {
1929       result.SetError("No name option provided.");
1930       return false;
1931     }
1932 
1933     Target *target =
1934         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1935 
1936     if (target == nullptr) {
1937       result.AppendError("Invalid target. No existing target or breakpoints.");
1938       result.SetStatus(eReturnStatusFailed);
1939       return false;
1940     }
1941 
1942     std::unique_lock<std::recursive_mutex> lock;
1943     target->GetBreakpointList().GetListMutex(lock);
1944 
1945     const BreakpointList &breakpoints = target->GetBreakpointList();
1946 
1947     size_t num_breakpoints = breakpoints.GetSize();
1948     if (num_breakpoints == 0) {
1949       result.SetError("No breakpoints, cannot delete names.");
1950       result.SetStatus(eReturnStatusFailed);
1951       return false;
1952     }
1953 
1954     // Particular breakpoint selected; disable that breakpoint.
1955     BreakpointIDList valid_bp_ids;
1956     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1957         command, target, result, &valid_bp_ids);
1958 
1959     if (result.Succeeded()) {
1960       if (valid_bp_ids.GetSize() == 0) {
1961         result.SetError("No breakpoints specified, cannot delete names.");
1962         result.SetStatus(eReturnStatusFailed);
1963         return false;
1964       }
1965       size_t num_valid_ids = valid_bp_ids.GetSize();
1966       for (size_t index = 0; index < num_valid_ids; index++) {
1967         lldb::break_id_t bp_id =
1968             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1969         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1970         bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1971       }
1972     }
1973 
1974     return true;
1975   }
1976 
1977 private:
1978   BreakpointNameOptionGroup m_name_options;
1979   OptionGroupOptions m_option_group;
1980 };
1981 
1982 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1983 public:
1984   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1985       : CommandObjectParsed(interpreter, "list",
1986                             "List either the names for a breakpoint or the "
1987                             "breakpoints for a given name.",
1988                             "breakpoint name list <command-options>"),
1989         m_name_options(), m_option_group() {
1990     m_option_group.Append(&m_name_options);
1991     m_option_group.Finalize();
1992   }
1993 
1994   ~CommandObjectBreakpointNameList() override = default;
1995 
1996   Options *GetOptions() override { return &m_option_group; }
1997 
1998 protected:
1999   bool DoExecute(Args &command, CommandReturnObject &result) override {
2000     Target *target =
2001         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2002 
2003     if (target == nullptr) {
2004       result.AppendError("Invalid target. No existing target or breakpoints.");
2005       result.SetStatus(eReturnStatusFailed);
2006       return false;
2007     }
2008 
2009     if (m_name_options.m_name.OptionWasSet()) {
2010       const char *name = m_name_options.m_name.GetCurrentValue();
2011       std::unique_lock<std::recursive_mutex> lock;
2012       target->GetBreakpointList().GetListMutex(lock);
2013 
2014       BreakpointList &breakpoints = target->GetBreakpointList();
2015       for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2016         if (bp_sp->MatchesName(name)) {
2017           StreamString s;
2018           bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2019           s.EOL();
2020           result.AppendMessage(s.GetData());
2021         }
2022       }
2023 
2024     } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2025       BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2026           m_name_options.m_breakpoint.GetCurrentValue());
2027       if (bp_sp) {
2028         std::vector<std::string> names;
2029         bp_sp->GetNames(names);
2030         result.AppendMessage("Names:");
2031         for (auto name : names)
2032           result.AppendMessageWithFormat("    %s\n", name.c_str());
2033       } else {
2034         result.AppendErrorWithFormat(
2035             "Could not find breakpoint %" PRId64 ".\n",
2036             m_name_options.m_breakpoint.GetCurrentValue());
2037         result.SetStatus(eReturnStatusFailed);
2038         return false;
2039       }
2040     } else {
2041       result.SetError("Must specify -N or -B option to list.");
2042       result.SetStatus(eReturnStatusFailed);
2043       return false;
2044     }
2045     return true;
2046   }
2047 
2048 private:
2049   BreakpointNameOptionGroup m_name_options;
2050   OptionGroupOptions m_option_group;
2051 };
2052 
2053 //-------------------------------------------------------------------------
2054 // CommandObjectBreakpointName
2055 //-------------------------------------------------------------------------
2056 class CommandObjectBreakpointName : public CommandObjectMultiword {
2057 public:
2058   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2059       : CommandObjectMultiword(
2060             interpreter, "name", "Commands to manage name tags for breakpoints",
2061             "breakpoint name <subcommand> [<command-options>]") {
2062     CommandObjectSP add_command_object(
2063         new CommandObjectBreakpointNameAdd(interpreter));
2064     CommandObjectSP delete_command_object(
2065         new CommandObjectBreakpointNameDelete(interpreter));
2066     CommandObjectSP list_command_object(
2067         new CommandObjectBreakpointNameList(interpreter));
2068 
2069     LoadSubCommand("add", add_command_object);
2070     LoadSubCommand("delete", delete_command_object);
2071     LoadSubCommand("list", list_command_object);
2072   }
2073 
2074   ~CommandObjectBreakpointName() override = default;
2075 };
2076 
2077 //-------------------------------------------------------------------------
2078 // CommandObjectBreakpointRead
2079 //-------------------------------------------------------------------------
2080 #pragma mark Read::CommandOptions
2081 static OptionDefinition g_breakpoint_read_options[] = {
2082     // clang-format off
2083   { LLDB_OPT_SET_ALL, true, "file",                   'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,       "The file from which to read the breakpoints." },
2084   {LLDB_OPT_SET_ALL, false, "breakpoint-name",        'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                       eArgTypeBreakpointName, "Only read in breakpoints with this name."},
2085     // clang-format on
2086 };
2087 
2088 #pragma mark Read
2089 
2090 class CommandObjectBreakpointRead : public CommandObjectParsed {
2091 public:
2092   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2093       : CommandObjectParsed(interpreter, "breakpoint read",
2094                             "Read and set the breakpoints previously saved to "
2095                             "a file with \"breakpoint write\".  ",
2096                             nullptr),
2097         m_options() {
2098     CommandArgumentEntry arg;
2099     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2100                                       eArgTypeBreakpointIDRange);
2101     // Add the entry for the first argument for this command to the object's
2102     // arguments vector.
2103     m_arguments.push_back(arg);
2104   }
2105 
2106   ~CommandObjectBreakpointRead() override = default;
2107 
2108   Options *GetOptions() override { return &m_options; }
2109 
2110   class CommandOptions : public Options {
2111   public:
2112     CommandOptions() : Options() {}
2113 
2114     ~CommandOptions() override = default;
2115 
2116     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2117                          ExecutionContext *execution_context) override {
2118       Error error;
2119       const int short_option = m_getopt_table[option_idx].val;
2120 
2121       switch (short_option) {
2122       case 'f':
2123         m_filename.assign(option_arg);
2124         break;
2125       case 'N': {
2126         Error name_error;
2127         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2128                                                   name_error)) {
2129           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2130                                          name_error.AsCString());
2131         }
2132         m_names.push_back(option_arg);
2133         break;
2134       }
2135       default:
2136         error.SetErrorStringWithFormat("unrecognized option '%c'",
2137                                        short_option);
2138         break;
2139       }
2140 
2141       return error;
2142     }
2143 
2144     void OptionParsingStarting(ExecutionContext *execution_context) override {
2145       m_filename.clear();
2146       m_names.clear();
2147     }
2148 
2149     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2150       return llvm::makeArrayRef(g_breakpoint_read_options);
2151     }
2152 
2153     // Instance variables to hold the values for command options.
2154 
2155     std::string m_filename;
2156     std::vector<std::string> m_names;
2157   };
2158 
2159 protected:
2160   bool DoExecute(Args &command, CommandReturnObject &result) override {
2161     Target *target = GetSelectedOrDummyTarget();
2162     if (target == nullptr) {
2163       result.AppendError("Invalid target.  No existing target or breakpoints.");
2164       result.SetStatus(eReturnStatusFailed);
2165       return false;
2166     }
2167 
2168     std::unique_lock<std::recursive_mutex> lock;
2169     target->GetBreakpointList().GetListMutex(lock);
2170 
2171     FileSpec input_spec(m_options.m_filename, true);
2172     BreakpointIDList new_bps;
2173     Error error = target->CreateBreakpointsFromFile(input_spec,
2174                                                     m_options.m_names, new_bps);
2175 
2176     if (!error.Success()) {
2177       result.AppendError(error.AsCString());
2178       result.SetStatus(eReturnStatusFailed);
2179       return false;
2180     }
2181 
2182     Stream &output_stream = result.GetOutputStream();
2183 
2184     size_t num_breakpoints = new_bps.GetSize();
2185     if (num_breakpoints == 0) {
2186       result.AppendMessage("No breakpoints added.");
2187     } else {
2188       // No breakpoint selected; show info about all currently set breakpoints.
2189       result.AppendMessage("New breakpoints:");
2190       for (size_t i = 0; i < num_breakpoints; ++i) {
2191         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2192         Breakpoint *bp = target->GetBreakpointList()
2193                              .FindBreakpointByID(bp_id.GetBreakpointID())
2194                              .get();
2195         if (bp)
2196           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2197                              false);
2198       }
2199     }
2200     return result.Succeeded();
2201   }
2202 
2203 private:
2204   CommandOptions m_options;
2205 };
2206 
2207 //-------------------------------------------------------------------------
2208 // CommandObjectBreakpointWrite
2209 //-------------------------------------------------------------------------
2210 #pragma mark Write::CommandOptions
2211 static OptionDefinition g_breakpoint_write_options[] = {
2212     // clang-format off
2213   { LLDB_OPT_SET_ALL, true,  "file",  'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,    "The file into which to write the breakpoints." },
2214   { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                       eArgTypeNone,        "Append to saved breakpoints file if it exists."},
2215     // clang-format on
2216 };
2217 
2218 #pragma mark Write
2219 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2220 public:
2221   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2222       : CommandObjectParsed(interpreter, "breakpoint write",
2223                             "Write the breakpoints listed to a file that can "
2224                             "be read in with \"breakpoint read\".  "
2225                             "If given no arguments, writes all breakpoints.",
2226                             nullptr),
2227         m_options() {
2228     CommandArgumentEntry arg;
2229     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2230                                       eArgTypeBreakpointIDRange);
2231     // Add the entry for the first argument for this command to the object's
2232     // arguments vector.
2233     m_arguments.push_back(arg);
2234   }
2235 
2236   ~CommandObjectBreakpointWrite() override = default;
2237 
2238   Options *GetOptions() override { return &m_options; }
2239 
2240   class CommandOptions : public Options {
2241   public:
2242     CommandOptions() : Options() {}
2243 
2244     ~CommandOptions() override = default;
2245 
2246     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2247                          ExecutionContext *execution_context) override {
2248       Error error;
2249       const int short_option = m_getopt_table[option_idx].val;
2250 
2251       switch (short_option) {
2252       case 'f':
2253         m_filename.assign(option_arg);
2254         break;
2255       case 'a':
2256         m_append = true;
2257         break;
2258       default:
2259         error.SetErrorStringWithFormat("unrecognized option '%c'",
2260                                        short_option);
2261         break;
2262       }
2263 
2264       return error;
2265     }
2266 
2267     void OptionParsingStarting(ExecutionContext *execution_context) override {
2268       m_filename.clear();
2269       m_append = false;
2270     }
2271 
2272     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2273       return llvm::makeArrayRef(g_breakpoint_write_options);
2274     }
2275 
2276     // Instance variables to hold the values for command options.
2277 
2278     std::string m_filename;
2279     bool m_append = false;
2280   };
2281 
2282 protected:
2283   bool DoExecute(Args &command, CommandReturnObject &result) override {
2284     Target *target = GetSelectedOrDummyTarget();
2285     if (target == nullptr) {
2286       result.AppendError("Invalid target.  No existing target or breakpoints.");
2287       result.SetStatus(eReturnStatusFailed);
2288       return false;
2289     }
2290 
2291     std::unique_lock<std::recursive_mutex> lock;
2292     target->GetBreakpointList().GetListMutex(lock);
2293 
2294     BreakpointIDList valid_bp_ids;
2295     if (command.GetArgumentCount() > 0) {
2296       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2297           command, target, result, &valid_bp_ids);
2298 
2299       if (!result.Succeeded()) {
2300         result.SetStatus(eReturnStatusFailed);
2301         return false;
2302       }
2303     }
2304     Error error = target->SerializeBreakpointsToFile(
2305         FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids,
2306         m_options.m_append);
2307     if (!error.Success()) {
2308       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2309                                    error.AsCString());
2310       result.SetStatus(eReturnStatusFailed);
2311     }
2312     return result.Succeeded();
2313   }
2314 
2315 private:
2316   CommandOptions m_options;
2317 };
2318 
2319 //-------------------------------------------------------------------------
2320 // CommandObjectMultiwordBreakpoint
2321 //-------------------------------------------------------------------------
2322 #pragma mark MultiwordBreakpoint
2323 
2324 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2325     CommandInterpreter &interpreter)
2326     : CommandObjectMultiword(
2327           interpreter, "breakpoint",
2328           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2329           "breakpoint <subcommand> [<command-options>]") {
2330   CommandObjectSP list_command_object(
2331       new CommandObjectBreakpointList(interpreter));
2332   CommandObjectSP enable_command_object(
2333       new CommandObjectBreakpointEnable(interpreter));
2334   CommandObjectSP disable_command_object(
2335       new CommandObjectBreakpointDisable(interpreter));
2336   CommandObjectSP clear_command_object(
2337       new CommandObjectBreakpointClear(interpreter));
2338   CommandObjectSP delete_command_object(
2339       new CommandObjectBreakpointDelete(interpreter));
2340   CommandObjectSP set_command_object(
2341       new CommandObjectBreakpointSet(interpreter));
2342   CommandObjectSP command_command_object(
2343       new CommandObjectBreakpointCommand(interpreter));
2344   CommandObjectSP modify_command_object(
2345       new CommandObjectBreakpointModify(interpreter));
2346   CommandObjectSP name_command_object(
2347       new CommandObjectBreakpointName(interpreter));
2348   CommandObjectSP write_command_object(
2349       new CommandObjectBreakpointWrite(interpreter));
2350   CommandObjectSP read_command_object(
2351       new CommandObjectBreakpointRead(interpreter));
2352 
2353   list_command_object->SetCommandName("breakpoint list");
2354   enable_command_object->SetCommandName("breakpoint enable");
2355   disable_command_object->SetCommandName("breakpoint disable");
2356   clear_command_object->SetCommandName("breakpoint clear");
2357   delete_command_object->SetCommandName("breakpoint delete");
2358   set_command_object->SetCommandName("breakpoint set");
2359   command_command_object->SetCommandName("breakpoint command");
2360   modify_command_object->SetCommandName("breakpoint modify");
2361   name_command_object->SetCommandName("breakpoint name");
2362   write_command_object->SetCommandName("breakpoint write");
2363   read_command_object->SetCommandName("breakpoint read");
2364 
2365   LoadSubCommand("list", list_command_object);
2366   LoadSubCommand("enable", enable_command_object);
2367   LoadSubCommand("disable", disable_command_object);
2368   LoadSubCommand("clear", clear_command_object);
2369   LoadSubCommand("delete", delete_command_object);
2370   LoadSubCommand("set", set_command_object);
2371   LoadSubCommand("command", command_command_object);
2372   LoadSubCommand("modify", modify_command_object);
2373   LoadSubCommand("name", name_command_object);
2374   LoadSubCommand("write", write_command_object);
2375   LoadSubCommand("read", read_command_object);
2376 }
2377 
2378 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2379 
2380 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2381                                                  bool allow_locations,
2382                                                  CommandReturnObject &result,
2383                                                  BreakpointIDList *valid_ids) {
2384   // args can be strings representing 1). integers (for breakpoint ids)
2385   //                                  2). the full breakpoint & location
2386   //                                  canonical representation
2387   //                                  3). the word "to" or a hyphen,
2388   //                                  representing a range (in which case there
2389   //                                      had *better* be an entry both before &
2390   //                                      after of one of the first two types.
2391   //                                  4). A breakpoint name
2392   // If args is empty, we will use the last created breakpoint (if there is
2393   // one.)
2394 
2395   Args temp_args;
2396 
2397   if (args.GetArgumentCount() == 0) {
2398     if (target->GetLastCreatedBreakpoint()) {
2399       valid_ids->AddBreakpointID(BreakpointID(
2400           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2401       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2402     } else {
2403       result.AppendError(
2404           "No breakpoint specified and no last created breakpoint.");
2405       result.SetStatus(eReturnStatusFailed);
2406     }
2407     return;
2408   }
2409 
2410   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2411   // directly from the old ARGS to
2412   // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead
2413   // generate a list of strings for
2414   // all the breakpoint ids in the range, and shove all of those breakpoint id
2415   // strings into TEMP_ARGS.
2416 
2417   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2418                                            result, temp_args);
2419 
2420   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2421   // BreakpointIDList:
2422 
2423   valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2424                                temp_args.GetArgumentCount(), result);
2425 
2426   // At this point,  all of the breakpoint ids that the user passed in have been
2427   // converted to breakpoint IDs
2428   // and put into valid_ids.
2429 
2430   if (result.Succeeded()) {
2431     // Now that we've converted everything from args into a list of breakpoint
2432     // ids, go through our tentative list
2433     // of breakpoint id's and verify that they correspond to valid/currently set
2434     // breakpoints.
2435 
2436     const size_t count = valid_ids->GetSize();
2437     for (size_t i = 0; i < count; ++i) {
2438       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2439       Breakpoint *breakpoint =
2440           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2441       if (breakpoint != nullptr) {
2442         const size_t num_locations = breakpoint->GetNumLocations();
2443         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2444           StreamString id_str;
2445           BreakpointID::GetCanonicalReference(
2446               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2447           i = valid_ids->GetSize() + 1;
2448           result.AppendErrorWithFormat(
2449               "'%s' is not a currently valid breakpoint/location id.\n",
2450               id_str.GetData());
2451           result.SetStatus(eReturnStatusFailed);
2452         }
2453       } else {
2454         i = valid_ids->GetSize() + 1;
2455         result.AppendErrorWithFormat(
2456             "'%d' is not a currently valid breakpoint ID.\n",
2457             cur_bp_id.GetBreakpointID());
2458         result.SetStatus(eReturnStatusFailed);
2459       }
2460     }
2461   }
2462 }
2463