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