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