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