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