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