1 //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
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(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(option_arg);
274         m_func_name_type_mask |= eFunctionNameTypeBase;
275         break;
276 
277       case 'C':
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(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(option_arg);
387         m_func_name_type_mask |= eFunctionNameTypeMethod;
388         break;
389 
390       case 'n':
391         m_func_names.push_back(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(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(option_arg);
419         break;
420 
421       case 'r':
422         m_func_regexp.assign(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(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(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         result.SetStatus(eReturnStatusFailed);
626         return false;
627       }
628 
629       bp_sp = target.CreateFuncRegexBreakpoint(
630           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
631           m_options.m_language, m_options.m_skip_prologue, internal,
632           m_options.m_hardware);
633     } break;
634     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
635     {
636       const size_t num_files = m_options.m_filenames.GetSize();
637 
638       if (num_files == 0 && !m_options.m_all_files) {
639         FileSpec file;
640         if (!GetDefaultFile(target, file, result)) {
641           result.AppendError(
642               "No files provided and could not find default file.");
643           result.SetStatus(eReturnStatusFailed);
644           return false;
645         } else {
646           m_options.m_filenames.Append(file);
647         }
648       }
649 
650       RegularExpression regexp(m_options.m_source_text_regexp);
651       if (llvm::Error err = regexp.GetError()) {
652         result.AppendErrorWithFormat(
653             "Source text regular expression could not be compiled: \"%s\"",
654             llvm::toString(std::move(err)).c_str());
655         result.SetStatus(eReturnStatusFailed);
656         return false;
657       }
658       bp_sp = target.CreateSourceRegexBreakpoint(
659           &(m_options.m_modules), &(m_options.m_filenames),
660           m_options.m_source_regex_func_names, std::move(regexp), internal,
661           m_options.m_hardware, m_options.m_move_to_nearest_code);
662     } break;
663     case eSetTypeException: {
664       Status precond_error;
665       bp_sp = target.CreateExceptionBreakpoint(
666           m_options.m_exception_language, m_options.m_catch_bp,
667           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
668           &precond_error);
669       if (precond_error.Fail()) {
670         result.AppendErrorWithFormat(
671             "Error setting extra exception arguments: %s",
672             precond_error.AsCString());
673         target.RemoveBreakpointByID(bp_sp->GetID());
674         result.SetStatus(eReturnStatusFailed);
675         return false;
676       }
677     } break;
678     case eSetTypeScripted: {
679 
680       Status error;
681       bp_sp = target.CreateScriptedBreakpoint(
682           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
683           &(m_options.m_filenames), false, m_options.m_hardware,
684           m_python_class_options.GetStructuredData(), &error);
685       if (error.Fail()) {
686         result.AppendErrorWithFormat(
687             "Error setting extra exception arguments: %s", error.AsCString());
688         target.RemoveBreakpointByID(bp_sp->GetID());
689         result.SetStatus(eReturnStatusFailed);
690         return false;
691       }
692     } break;
693     default:
694       break;
695     }
696 
697     // Now set the various options that were passed in:
698     if (bp_sp) {
699       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
700 
701       if (!m_options.m_breakpoint_names.empty()) {
702         Status name_error;
703         for (auto name : m_options.m_breakpoint_names) {
704           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
705           if (name_error.Fail()) {
706             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
707                                          name.c_str());
708             target.RemoveBreakpointByID(bp_sp->GetID());
709             result.SetStatus(eReturnStatusFailed);
710             return false;
711           }
712         }
713       }
714     }
715 
716     if (bp_sp) {
717       Stream &output_stream = result.GetOutputStream();
718       const bool show_locations = false;
719       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
720                             show_locations);
721       if (&target == &GetDummyTarget())
722         output_stream.Printf("Breakpoint set in dummy target, will get copied "
723                              "into future targets.\n");
724       else {
725         // Don't print out this warning for exception breakpoints.  They can
726         // get set before the target is set, but we won't know how to actually
727         // set the breakpoint till we run.
728         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
729           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
730                                "actual locations.\n");
731         }
732       }
733       result.SetStatus(eReturnStatusSuccessFinishResult);
734     } else if (!bp_sp) {
735       result.AppendError("Breakpoint creation failed: No breakpoint created.");
736       result.SetStatus(eReturnStatusFailed);
737     }
738 
739     return result.Succeeded();
740   }
741 
742 private:
743   bool GetDefaultFile(Target &target, FileSpec &file,
744                       CommandReturnObject &result) {
745     uint32_t default_line;
746     // First use the Source Manager's default file. Then use the current stack
747     // frame's file.
748     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
749       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
750       if (cur_frame == nullptr) {
751         result.AppendError(
752             "No selected frame to use to find the default file.");
753         result.SetStatus(eReturnStatusFailed);
754         return false;
755       } else if (!cur_frame->HasDebugInformation()) {
756         result.AppendError("Cannot use the selected frame to find the default "
757                            "file, it has no debug info.");
758         result.SetStatus(eReturnStatusFailed);
759         return false;
760       } else {
761         const SymbolContext &sc =
762             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
763         if (sc.line_entry.file) {
764           file = sc.line_entry.file;
765         } else {
766           result.AppendError("Can't find the file for the selected frame to "
767                              "use as the default file.");
768           result.SetStatus(eReturnStatusFailed);
769           return false;
770         }
771       }
772     }
773     return true;
774   }
775 
776   BreakpointOptionGroup m_bp_opts;
777   BreakpointDummyOptionGroup m_dummy_options;
778   OptionGroupPythonClassWithDict m_python_class_options;
779   CommandOptions m_options;
780   OptionGroupOptions m_all_options;
781 };
782 
783 // CommandObjectBreakpointModify
784 #pragma mark Modify
785 
786 class CommandObjectBreakpointModify : public CommandObjectParsed {
787 public:
788   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
789       : CommandObjectParsed(interpreter, "breakpoint modify",
790                             "Modify the options on a breakpoint or set of "
791                             "breakpoints in the executable.  "
792                             "If no breakpoint is specified, acts on the last "
793                             "created breakpoint.  "
794                             "With the exception of -e, -d and -i, passing an "
795                             "empty argument clears the modification.",
796                             nullptr),
797         m_options() {
798     CommandArgumentEntry arg;
799     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
800                                       eArgTypeBreakpointIDRange);
801     // Add the entry for the first argument for this command to the object's
802     // arguments vector.
803     m_arguments.push_back(arg);
804 
805     m_options.Append(&m_bp_opts,
806                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
807                      LLDB_OPT_SET_ALL);
808     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
809     m_options.Finalize();
810   }
811 
812   ~CommandObjectBreakpointModify() override = default;
813 
814   Options *GetOptions() override { return &m_options; }
815 
816 protected:
817   bool DoExecute(Args &command, CommandReturnObject &result) override {
818     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
819 
820     std::unique_lock<std::recursive_mutex> lock;
821     target.GetBreakpointList().GetListMutex(lock);
822 
823     BreakpointIDList valid_bp_ids;
824 
825     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
826         command, &target, result, &valid_bp_ids,
827         BreakpointName::Permissions::PermissionKinds::disablePerm);
828 
829     if (result.Succeeded()) {
830       const size_t count = valid_bp_ids.GetSize();
831       for (size_t i = 0; i < count; ++i) {
832         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
833 
834         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
835           Breakpoint *bp =
836               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
837           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
838             BreakpointLocation *location =
839                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
840             if (location)
841               location->GetLocationOptions()->CopyOverSetOptions(
842                   m_bp_opts.GetBreakpointOptions());
843           } else {
844             bp->GetOptions()->CopyOverSetOptions(
845                 m_bp_opts.GetBreakpointOptions());
846           }
847         }
848       }
849     }
850 
851     return result.Succeeded();
852   }
853 
854 private:
855   BreakpointOptionGroup m_bp_opts;
856   BreakpointDummyOptionGroup m_dummy_opts;
857   OptionGroupOptions m_options;
858 };
859 
860 // CommandObjectBreakpointEnable
861 #pragma mark Enable
862 
863 class CommandObjectBreakpointEnable : public CommandObjectParsed {
864 public:
865   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
866       : CommandObjectParsed(interpreter, "enable",
867                             "Enable the specified disabled breakpoint(s). If "
868                             "no breakpoints are specified, enable all of them.",
869                             nullptr) {
870     CommandArgumentEntry arg;
871     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
872                                       eArgTypeBreakpointIDRange);
873     // Add the entry for the first argument for this command to the object's
874     // arguments vector.
875     m_arguments.push_back(arg);
876   }
877 
878   ~CommandObjectBreakpointEnable() override = default;
879 
880 protected:
881   bool DoExecute(Args &command, CommandReturnObject &result) override {
882     Target &target = GetSelectedOrDummyTarget();
883 
884     std::unique_lock<std::recursive_mutex> lock;
885     target.GetBreakpointList().GetListMutex(lock);
886 
887     const BreakpointList &breakpoints = target.GetBreakpointList();
888 
889     size_t num_breakpoints = breakpoints.GetSize();
890 
891     if (num_breakpoints == 0) {
892       result.AppendError("No breakpoints exist to be enabled.");
893       result.SetStatus(eReturnStatusFailed);
894       return false;
895     }
896 
897     if (command.empty()) {
898       // No breakpoint selected; enable all currently set breakpoints.
899       target.EnableAllowedBreakpoints();
900       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
901                                      " breakpoints)\n",
902                                      (uint64_t)num_breakpoints);
903       result.SetStatus(eReturnStatusSuccessFinishNoResult);
904     } else {
905       // Particular breakpoint selected; enable that breakpoint.
906       BreakpointIDList valid_bp_ids;
907       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
908           command, &target, result, &valid_bp_ids,
909           BreakpointName::Permissions::PermissionKinds::disablePerm);
910 
911       if (result.Succeeded()) {
912         int enable_count = 0;
913         int loc_count = 0;
914         const size_t count = valid_bp_ids.GetSize();
915         for (size_t i = 0; i < count; ++i) {
916           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
917 
918           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
919             Breakpoint *breakpoint =
920                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
921             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
922               BreakpointLocation *location =
923                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
924               if (location) {
925                 location->SetEnabled(true);
926                 ++loc_count;
927               }
928             } else {
929               breakpoint->SetEnabled(true);
930               ++enable_count;
931             }
932           }
933         }
934         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
935                                        enable_count + loc_count);
936         result.SetStatus(eReturnStatusSuccessFinishNoResult);
937       }
938     }
939 
940     return result.Succeeded();
941   }
942 };
943 
944 // CommandObjectBreakpointDisable
945 #pragma mark Disable
946 
947 class CommandObjectBreakpointDisable : public CommandObjectParsed {
948 public:
949   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
950       : CommandObjectParsed(
951             interpreter, "breakpoint disable",
952             "Disable the specified breakpoint(s) without deleting "
953             "them.  If none are specified, disable all "
954             "breakpoints.",
955             nullptr) {
956     SetHelpLong(
957         "Disable the specified breakpoint(s) without deleting them.  \
958 If none are specified, disable all breakpoints."
959         R"(
960 
961 )"
962         "Note: disabling a breakpoint will cause none of its locations to be hit \
963 regardless of whether individual locations are enabled or disabled.  After the sequence:"
964         R"(
965 
966     (lldb) break disable 1
967     (lldb) break enable 1.1
968 
969 execution will NOT stop at location 1.1.  To achieve that, type:
970 
971     (lldb) break disable 1.*
972     (lldb) break enable 1.1
973 
974 )"
975         "The first command disables all locations for breakpoint 1, \
976 the second re-enables the first location.");
977 
978     CommandArgumentEntry arg;
979     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
980                                       eArgTypeBreakpointIDRange);
981     // Add the entry for the first argument for this command to the object's
982     // arguments vector.
983     m_arguments.push_back(arg);
984   }
985 
986   ~CommandObjectBreakpointDisable() override = default;
987 
988 protected:
989   bool DoExecute(Args &command, CommandReturnObject &result) override {
990     Target &target = GetSelectedOrDummyTarget();
991     std::unique_lock<std::recursive_mutex> lock;
992     target.GetBreakpointList().GetListMutex(lock);
993 
994     const BreakpointList &breakpoints = target.GetBreakpointList();
995     size_t num_breakpoints = breakpoints.GetSize();
996 
997     if (num_breakpoints == 0) {
998       result.AppendError("No breakpoints exist to be disabled.");
999       result.SetStatus(eReturnStatusFailed);
1000       return false;
1001     }
1002 
1003     if (command.empty()) {
1004       // No breakpoint selected; disable all currently set breakpoints.
1005       target.DisableAllowedBreakpoints();
1006       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1007                                      " breakpoints)\n",
1008                                      (uint64_t)num_breakpoints);
1009       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1010     } else {
1011       // Particular breakpoint selected; disable that breakpoint.
1012       BreakpointIDList valid_bp_ids;
1013 
1014       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1015           command, &target, result, &valid_bp_ids,
1016           BreakpointName::Permissions::PermissionKinds::disablePerm);
1017 
1018       if (result.Succeeded()) {
1019         int disable_count = 0;
1020         int loc_count = 0;
1021         const size_t count = valid_bp_ids.GetSize();
1022         for (size_t i = 0; i < count; ++i) {
1023           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1024 
1025           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1026             Breakpoint *breakpoint =
1027                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1028             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1029               BreakpointLocation *location =
1030                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1031               if (location) {
1032                 location->SetEnabled(false);
1033                 ++loc_count;
1034               }
1035             } else {
1036               breakpoint->SetEnabled(false);
1037               ++disable_count;
1038             }
1039           }
1040         }
1041         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1042                                        disable_count + loc_count);
1043         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1044       }
1045     }
1046 
1047     return result.Succeeded();
1048   }
1049 };
1050 
1051 // CommandObjectBreakpointList
1052 
1053 #pragma mark List::CommandOptions
1054 #define LLDB_OPTIONS_breakpoint_list
1055 #include "CommandOptions.inc"
1056 
1057 #pragma mark List
1058 
1059 class CommandObjectBreakpointList : public CommandObjectParsed {
1060 public:
1061   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1062       : CommandObjectParsed(
1063             interpreter, "breakpoint list",
1064             "List some or all breakpoints at configurable levels of detail.",
1065             nullptr),
1066         m_options() {
1067     CommandArgumentEntry arg;
1068     CommandArgumentData bp_id_arg;
1069 
1070     // Define the first (and only) variant of this arg.
1071     bp_id_arg.arg_type = eArgTypeBreakpointID;
1072     bp_id_arg.arg_repetition = eArgRepeatOptional;
1073 
1074     // There is only one variant this argument could be; put it into the
1075     // argument entry.
1076     arg.push_back(bp_id_arg);
1077 
1078     // Push the data for the first argument into the m_arguments vector.
1079     m_arguments.push_back(arg);
1080   }
1081 
1082   ~CommandObjectBreakpointList() override = default;
1083 
1084   Options *GetOptions() override { return &m_options; }
1085 
1086   class CommandOptions : public Options {
1087   public:
1088     CommandOptions()
1089         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1090     }
1091 
1092     ~CommandOptions() override = default;
1093 
1094     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1095                           ExecutionContext *execution_context) override {
1096       Status error;
1097       const int short_option = m_getopt_table[option_idx].val;
1098 
1099       switch (short_option) {
1100       case 'b':
1101         m_level = lldb::eDescriptionLevelBrief;
1102         break;
1103       case 'D':
1104         m_use_dummy = true;
1105         break;
1106       case 'f':
1107         m_level = lldb::eDescriptionLevelFull;
1108         break;
1109       case 'v':
1110         m_level = lldb::eDescriptionLevelVerbose;
1111         break;
1112       case 'i':
1113         m_internal = true;
1114         break;
1115       default:
1116         llvm_unreachable("Unimplemented option");
1117       }
1118 
1119       return error;
1120     }
1121 
1122     void OptionParsingStarting(ExecutionContext *execution_context) override {
1123       m_level = lldb::eDescriptionLevelFull;
1124       m_internal = false;
1125       m_use_dummy = false;
1126     }
1127 
1128     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1129       return llvm::makeArrayRef(g_breakpoint_list_options);
1130     }
1131 
1132     // Instance variables to hold the values for command options.
1133 
1134     lldb::DescriptionLevel m_level;
1135 
1136     bool m_internal;
1137     bool m_use_dummy;
1138   };
1139 
1140 protected:
1141   bool DoExecute(Args &command, CommandReturnObject &result) override {
1142     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1143 
1144     const BreakpointList &breakpoints =
1145         target.GetBreakpointList(m_options.m_internal);
1146     std::unique_lock<std::recursive_mutex> lock;
1147     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1148 
1149     size_t num_breakpoints = breakpoints.GetSize();
1150 
1151     if (num_breakpoints == 0) {
1152       result.AppendMessage("No breakpoints currently set.");
1153       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1154       return true;
1155     }
1156 
1157     Stream &output_stream = result.GetOutputStream();
1158 
1159     if (command.empty()) {
1160       // No breakpoint selected; show info about all currently set breakpoints.
1161       result.AppendMessage("Current breakpoints:");
1162       for (size_t i = 0; i < num_breakpoints; ++i) {
1163         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1164         if (breakpoint->AllowList())
1165           AddBreakpointDescription(&output_stream, breakpoint,
1166                                    m_options.m_level);
1167       }
1168       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1169     } else {
1170       // Particular breakpoints selected; show info about that breakpoint.
1171       BreakpointIDList valid_bp_ids;
1172       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1173           command, &target, result, &valid_bp_ids,
1174           BreakpointName::Permissions::PermissionKinds::listPerm);
1175 
1176       if (result.Succeeded()) {
1177         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1178           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1179           Breakpoint *breakpoint =
1180               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1181           AddBreakpointDescription(&output_stream, breakpoint,
1182                                    m_options.m_level);
1183         }
1184         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1185       } else {
1186         result.AppendError("Invalid breakpoint ID.");
1187         result.SetStatus(eReturnStatusFailed);
1188       }
1189     }
1190 
1191     return result.Succeeded();
1192   }
1193 
1194 private:
1195   CommandOptions m_options;
1196 };
1197 
1198 // CommandObjectBreakpointClear
1199 #pragma mark Clear::CommandOptions
1200 
1201 #define LLDB_OPTIONS_breakpoint_clear
1202 #include "CommandOptions.inc"
1203 
1204 #pragma mark Clear
1205 
1206 class CommandObjectBreakpointClear : public CommandObjectParsed {
1207 public:
1208   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1209 
1210   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1211       : CommandObjectParsed(interpreter, "breakpoint clear",
1212                             "Delete or disable breakpoints matching the "
1213                             "specified source file and line.",
1214                             "breakpoint clear <cmd-options>"),
1215         m_options() {}
1216 
1217   ~CommandObjectBreakpointClear() override = default;
1218 
1219   Options *GetOptions() override { return &m_options; }
1220 
1221   class CommandOptions : public Options {
1222   public:
1223     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1224 
1225     ~CommandOptions() override = default;
1226 
1227     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1228                           ExecutionContext *execution_context) override {
1229       Status error;
1230       const int short_option = m_getopt_table[option_idx].val;
1231 
1232       switch (short_option) {
1233       case 'f':
1234         m_filename.assign(option_arg);
1235         break;
1236 
1237       case 'l':
1238         option_arg.getAsInteger(0, m_line_num);
1239         break;
1240 
1241       default:
1242         llvm_unreachable("Unimplemented option");
1243       }
1244 
1245       return error;
1246     }
1247 
1248     void OptionParsingStarting(ExecutionContext *execution_context) override {
1249       m_filename.clear();
1250       m_line_num = 0;
1251     }
1252 
1253     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1254       return llvm::makeArrayRef(g_breakpoint_clear_options);
1255     }
1256 
1257     // Instance variables to hold the values for command options.
1258 
1259     std::string m_filename;
1260     uint32_t m_line_num;
1261   };
1262 
1263 protected:
1264   bool DoExecute(Args &command, CommandReturnObject &result) override {
1265     Target &target = GetSelectedOrDummyTarget();
1266 
1267     // The following are the various types of breakpoints that could be
1268     // cleared:
1269     //   1). -f -l (clearing breakpoint by source location)
1270 
1271     BreakpointClearType break_type = eClearTypeInvalid;
1272 
1273     if (m_options.m_line_num != 0)
1274       break_type = eClearTypeFileAndLine;
1275 
1276     std::unique_lock<std::recursive_mutex> lock;
1277     target.GetBreakpointList().GetListMutex(lock);
1278 
1279     BreakpointList &breakpoints = target.GetBreakpointList();
1280     size_t num_breakpoints = breakpoints.GetSize();
1281 
1282     // Early return if there's no breakpoint at all.
1283     if (num_breakpoints == 0) {
1284       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1285       result.SetStatus(eReturnStatusFailed);
1286       return result.Succeeded();
1287     }
1288 
1289     // Find matching breakpoints and delete them.
1290 
1291     // First create a copy of all the IDs.
1292     std::vector<break_id_t> BreakIDs;
1293     for (size_t i = 0; i < num_breakpoints; ++i)
1294       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1295 
1296     int num_cleared = 0;
1297     StreamString ss;
1298     switch (break_type) {
1299     case eClearTypeFileAndLine: // Breakpoint by source position
1300     {
1301       const ConstString filename(m_options.m_filename.c_str());
1302       BreakpointLocationCollection loc_coll;
1303 
1304       for (size_t i = 0; i < num_breakpoints; ++i) {
1305         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1306 
1307         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1308           // If the collection size is 0, it's a full match and we can just
1309           // remove the breakpoint.
1310           if (loc_coll.GetSize() == 0) {
1311             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1312             ss.EOL();
1313             target.RemoveBreakpointByID(bp->GetID());
1314             ++num_cleared;
1315           }
1316         }
1317       }
1318     } break;
1319 
1320     default:
1321       break;
1322     }
1323 
1324     if (num_cleared > 0) {
1325       Stream &output_stream = result.GetOutputStream();
1326       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1327       output_stream << ss.GetString();
1328       output_stream.EOL();
1329       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1330     } else {
1331       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1332       result.SetStatus(eReturnStatusFailed);
1333     }
1334 
1335     return result.Succeeded();
1336   }
1337 
1338 private:
1339   CommandOptions m_options;
1340 };
1341 
1342 // CommandObjectBreakpointDelete
1343 #define LLDB_OPTIONS_breakpoint_delete
1344 #include "CommandOptions.inc"
1345 
1346 #pragma mark Delete
1347 
1348 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1349 public:
1350   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1351       : CommandObjectParsed(interpreter, "breakpoint delete",
1352                             "Delete the specified breakpoint(s).  If no "
1353                             "breakpoints are specified, delete them all.",
1354                             nullptr),
1355         m_options() {
1356     CommandArgumentEntry arg;
1357     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1358                                       eArgTypeBreakpointIDRange);
1359     // Add the entry for the first argument for this command to the object's
1360     // arguments vector.
1361     m_arguments.push_back(arg);
1362   }
1363 
1364   ~CommandObjectBreakpointDelete() override = default;
1365 
1366   Options *GetOptions() override { return &m_options; }
1367 
1368   class CommandOptions : public Options {
1369   public:
1370     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1371 
1372     ~CommandOptions() override = default;
1373 
1374     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1375                           ExecutionContext *execution_context) override {
1376       Status error;
1377       const int short_option = m_getopt_table[option_idx].val;
1378 
1379       switch (short_option) {
1380       case 'f':
1381         m_force = true;
1382         break;
1383 
1384       case 'D':
1385         m_use_dummy = true;
1386         break;
1387 
1388       default:
1389         llvm_unreachable("Unimplemented option");
1390       }
1391 
1392       return error;
1393     }
1394 
1395     void OptionParsingStarting(ExecutionContext *execution_context) override {
1396       m_use_dummy = false;
1397       m_force = false;
1398     }
1399 
1400     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1401       return llvm::makeArrayRef(g_breakpoint_delete_options);
1402     }
1403 
1404     // Instance variables to hold the values for command options.
1405     bool m_use_dummy;
1406     bool m_force;
1407   };
1408 
1409 protected:
1410   bool DoExecute(Args &command, CommandReturnObject &result) override {
1411     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1412 
1413     std::unique_lock<std::recursive_mutex> lock;
1414     target.GetBreakpointList().GetListMutex(lock);
1415 
1416     const BreakpointList &breakpoints = target.GetBreakpointList();
1417 
1418     size_t num_breakpoints = breakpoints.GetSize();
1419 
1420     if (num_breakpoints == 0) {
1421       result.AppendError("No breakpoints exist to be deleted.");
1422       result.SetStatus(eReturnStatusFailed);
1423       return false;
1424     }
1425 
1426     if (command.empty()) {
1427       if (!m_options.m_force &&
1428           !m_interpreter.Confirm(
1429               "About to delete all breakpoints, do you want to do that?",
1430               true)) {
1431         result.AppendMessage("Operation cancelled...");
1432       } else {
1433         target.RemoveAllowedBreakpoints();
1434         result.AppendMessageWithFormat(
1435             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1436             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1437       }
1438       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1439     } else {
1440       // Particular breakpoint selected; disable that breakpoint.
1441       BreakpointIDList valid_bp_ids;
1442       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1443           command, &target, result, &valid_bp_ids,
1444           BreakpointName::Permissions::PermissionKinds::deletePerm);
1445 
1446       if (result.Succeeded()) {
1447         int delete_count = 0;
1448         int disable_count = 0;
1449         const size_t count = valid_bp_ids.GetSize();
1450         for (size_t i = 0; i < count; ++i) {
1451           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1452 
1453           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1454             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1455               Breakpoint *breakpoint =
1456                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1457               BreakpointLocation *location =
1458                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1459               // It makes no sense to try to delete individual locations, so we
1460               // disable them instead.
1461               if (location) {
1462                 location->SetEnabled(false);
1463                 ++disable_count;
1464               }
1465             } else {
1466               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1467               ++delete_count;
1468             }
1469           }
1470         }
1471         result.AppendMessageWithFormat(
1472             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1473             delete_count, disable_count);
1474         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1475       }
1476     }
1477     return result.Succeeded();
1478   }
1479 
1480 private:
1481   CommandOptions m_options;
1482 };
1483 
1484 // CommandObjectBreakpointName
1485 #define LLDB_OPTIONS_breakpoint_name
1486 #include "CommandOptions.inc"
1487 
1488 class BreakpointNameOptionGroup : public OptionGroup {
1489 public:
1490   BreakpointNameOptionGroup()
1491       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1492   }
1493 
1494   ~BreakpointNameOptionGroup() override = default;
1495 
1496   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1497     return llvm::makeArrayRef(g_breakpoint_name_options);
1498   }
1499 
1500   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1501                         ExecutionContext *execution_context) override {
1502     Status error;
1503     const int short_option = g_breakpoint_name_options[option_idx].short_option;
1504 
1505     switch (short_option) {
1506     case 'N':
1507       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1508           error.Success())
1509         m_name.SetValueFromString(option_arg);
1510       break;
1511     case 'B':
1512       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1513         error.SetErrorStringWithFormat(
1514             "unrecognized value \"%s\" for breakpoint",
1515             option_arg.str().c_str());
1516       break;
1517     case 'D':
1518       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1519         error.SetErrorStringWithFormat(
1520             "unrecognized value \"%s\" for use-dummy",
1521             option_arg.str().c_str());
1522       break;
1523     case 'H':
1524       m_help_string.SetValueFromString(option_arg);
1525       break;
1526 
1527     default:
1528       llvm_unreachable("Unimplemented option");
1529     }
1530     return error;
1531   }
1532 
1533   void OptionParsingStarting(ExecutionContext *execution_context) override {
1534     m_name.Clear();
1535     m_breakpoint.Clear();
1536     m_use_dummy.Clear();
1537     m_use_dummy.SetDefaultValue(false);
1538     m_help_string.Clear();
1539   }
1540 
1541   OptionValueString m_name;
1542   OptionValueUInt64 m_breakpoint;
1543   OptionValueBoolean m_use_dummy;
1544   OptionValueString m_help_string;
1545 };
1546 
1547 #define LLDB_OPTIONS_breakpoint_access
1548 #include "CommandOptions.inc"
1549 
1550 class BreakpointAccessOptionGroup : public OptionGroup {
1551 public:
1552   BreakpointAccessOptionGroup() : OptionGroup() {}
1553 
1554   ~BreakpointAccessOptionGroup() override = default;
1555 
1556   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1557     return llvm::makeArrayRef(g_breakpoint_access_options);
1558   }
1559   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1560                         ExecutionContext *execution_context) override {
1561     Status error;
1562     const int short_option =
1563         g_breakpoint_access_options[option_idx].short_option;
1564 
1565     switch (short_option) {
1566     case 'L': {
1567       bool value, success;
1568       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1569       if (success) {
1570         m_permissions.SetAllowList(value);
1571       } else
1572         error.SetErrorStringWithFormat(
1573             "invalid boolean value '%s' passed for -L option",
1574             option_arg.str().c_str());
1575     } break;
1576     case 'A': {
1577       bool value, success;
1578       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1579       if (success) {
1580         m_permissions.SetAllowDisable(value);
1581       } else
1582         error.SetErrorStringWithFormat(
1583             "invalid boolean value '%s' passed for -L option",
1584             option_arg.str().c_str());
1585     } break;
1586     case 'D': {
1587       bool value, success;
1588       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1589       if (success) {
1590         m_permissions.SetAllowDelete(value);
1591       } else
1592         error.SetErrorStringWithFormat(
1593             "invalid boolean value '%s' passed for -L option",
1594             option_arg.str().c_str());
1595     } break;
1596     default:
1597       llvm_unreachable("Unimplemented option");
1598     }
1599 
1600     return error;
1601   }
1602 
1603   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1604 
1605   const BreakpointName::Permissions &GetPermissions() const {
1606     return m_permissions;
1607   }
1608   BreakpointName::Permissions m_permissions;
1609 };
1610 
1611 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1612 public:
1613   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1614       : CommandObjectParsed(
1615             interpreter, "configure",
1616             "Configure the options for the breakpoint"
1617             " name provided.  "
1618             "If you provide a breakpoint id, the options will be copied from "
1619             "the breakpoint, otherwise only the options specified will be set "
1620             "on the name.",
1621             "breakpoint name configure <command-options> "
1622             "<breakpoint-name-list>"),
1623         m_bp_opts(), m_option_group() {
1624     // Create the first variant for the first (and only) argument for this
1625     // command.
1626     CommandArgumentEntry arg1;
1627     CommandArgumentData id_arg;
1628     id_arg.arg_type = eArgTypeBreakpointName;
1629     id_arg.arg_repetition = eArgRepeatOptional;
1630     arg1.push_back(id_arg);
1631     m_arguments.push_back(arg1);
1632 
1633     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1634     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1635                           LLDB_OPT_SET_ALL);
1636     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1637                           LLDB_OPT_SET_ALL);
1638     m_option_group.Finalize();
1639   }
1640 
1641   ~CommandObjectBreakpointNameConfigure() override = default;
1642 
1643   Options *GetOptions() override { return &m_option_group; }
1644 
1645 protected:
1646   bool DoExecute(Args &command, CommandReturnObject &result) override {
1647 
1648     const size_t argc = command.GetArgumentCount();
1649     if (argc == 0) {
1650       result.AppendError("No names provided.");
1651       result.SetStatus(eReturnStatusFailed);
1652       return false;
1653     }
1654 
1655     Target &target = GetSelectedOrDummyTarget(false);
1656 
1657     std::unique_lock<std::recursive_mutex> lock;
1658     target.GetBreakpointList().GetListMutex(lock);
1659 
1660     // Make a pass through first to see that all the names are legal.
1661     for (auto &entry : command.entries()) {
1662       Status error;
1663       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1664         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1665                                      entry.c_str(), error.AsCString());
1666         result.SetStatus(eReturnStatusFailed);
1667         return false;
1668       }
1669     }
1670     // Now configure them, we already pre-checked the names so we don't need to
1671     // check the error:
1672     BreakpointSP bp_sp;
1673     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1674       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1675       bp_sp = target.GetBreakpointByID(bp_id);
1676       if (!bp_sp) {
1677         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1678                                       bp_id);
1679         result.SetStatus(eReturnStatusFailed);
1680         return false;
1681       }
1682     }
1683 
1684     Status error;
1685     for (auto &entry : command.entries()) {
1686       ConstString name(entry.c_str());
1687       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1688       if (!bp_name)
1689         continue;
1690       if (m_bp_id.m_help_string.OptionWasSet())
1691         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1692 
1693       if (bp_sp)
1694         target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1695                                        m_access_options.GetPermissions());
1696       else
1697         target.ConfigureBreakpointName(*bp_name,
1698                                        m_bp_opts.GetBreakpointOptions(),
1699                                        m_access_options.GetPermissions());
1700     }
1701     return true;
1702   }
1703 
1704 private:
1705   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1706   BreakpointOptionGroup m_bp_opts;
1707   BreakpointAccessOptionGroup m_access_options;
1708   OptionGroupOptions m_option_group;
1709 };
1710 
1711 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1712 public:
1713   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1714       : CommandObjectParsed(
1715             interpreter, "add", "Add a name to the breakpoints provided.",
1716             "breakpoint name add <command-options> <breakpoint-id-list>"),
1717         m_name_options(), m_option_group() {
1718     // Create the first variant for the first (and only) argument for this
1719     // command.
1720     CommandArgumentEntry arg1;
1721     CommandArgumentData id_arg;
1722     id_arg.arg_type = eArgTypeBreakpointID;
1723     id_arg.arg_repetition = eArgRepeatOptional;
1724     arg1.push_back(id_arg);
1725     m_arguments.push_back(arg1);
1726 
1727     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1728     m_option_group.Finalize();
1729   }
1730 
1731   ~CommandObjectBreakpointNameAdd() override = default;
1732 
1733   Options *GetOptions() override { return &m_option_group; }
1734 
1735 protected:
1736   bool DoExecute(Args &command, CommandReturnObject &result) override {
1737     if (!m_name_options.m_name.OptionWasSet()) {
1738       result.SetError("No name option provided.");
1739       return false;
1740     }
1741 
1742     Target &target =
1743         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1744 
1745     std::unique_lock<std::recursive_mutex> lock;
1746     target.GetBreakpointList().GetListMutex(lock);
1747 
1748     const BreakpointList &breakpoints = target.GetBreakpointList();
1749 
1750     size_t num_breakpoints = breakpoints.GetSize();
1751     if (num_breakpoints == 0) {
1752       result.SetError("No breakpoints, cannot add names.");
1753       result.SetStatus(eReturnStatusFailed);
1754       return false;
1755     }
1756 
1757     // Particular breakpoint selected; disable that breakpoint.
1758     BreakpointIDList valid_bp_ids;
1759     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1760         command, &target, result, &valid_bp_ids,
1761         BreakpointName::Permissions::PermissionKinds::listPerm);
1762 
1763     if (result.Succeeded()) {
1764       if (valid_bp_ids.GetSize() == 0) {
1765         result.SetError("No breakpoints specified, cannot add names.");
1766         result.SetStatus(eReturnStatusFailed);
1767         return false;
1768       }
1769       size_t num_valid_ids = valid_bp_ids.GetSize();
1770       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1771       Status error; // This error reports illegal names, but we've already
1772                     // checked that, so we don't need to check it again here.
1773       for (size_t index = 0; index < num_valid_ids; index++) {
1774         lldb::break_id_t bp_id =
1775             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1776         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1777         target.AddNameToBreakpoint(bp_sp, bp_name, error);
1778       }
1779     }
1780 
1781     return true;
1782   }
1783 
1784 private:
1785   BreakpointNameOptionGroup m_name_options;
1786   OptionGroupOptions m_option_group;
1787 };
1788 
1789 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1790 public:
1791   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1792       : CommandObjectParsed(
1793             interpreter, "delete",
1794             "Delete a name from the breakpoints provided.",
1795             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1796         m_name_options(), m_option_group() {
1797     // Create the first variant for the first (and only) argument for this
1798     // command.
1799     CommandArgumentEntry arg1;
1800     CommandArgumentData id_arg;
1801     id_arg.arg_type = eArgTypeBreakpointID;
1802     id_arg.arg_repetition = eArgRepeatOptional;
1803     arg1.push_back(id_arg);
1804     m_arguments.push_back(arg1);
1805 
1806     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1807     m_option_group.Finalize();
1808   }
1809 
1810   ~CommandObjectBreakpointNameDelete() override = default;
1811 
1812   Options *GetOptions() override { return &m_option_group; }
1813 
1814 protected:
1815   bool DoExecute(Args &command, CommandReturnObject &result) override {
1816     if (!m_name_options.m_name.OptionWasSet()) {
1817       result.SetError("No name option provided.");
1818       return false;
1819     }
1820 
1821     Target &target =
1822         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1823 
1824     std::unique_lock<std::recursive_mutex> lock;
1825     target.GetBreakpointList().GetListMutex(lock);
1826 
1827     const BreakpointList &breakpoints = target.GetBreakpointList();
1828 
1829     size_t num_breakpoints = breakpoints.GetSize();
1830     if (num_breakpoints == 0) {
1831       result.SetError("No breakpoints, cannot delete names.");
1832       result.SetStatus(eReturnStatusFailed);
1833       return false;
1834     }
1835 
1836     // Particular breakpoint selected; disable that breakpoint.
1837     BreakpointIDList valid_bp_ids;
1838     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1839         command, &target, result, &valid_bp_ids,
1840         BreakpointName::Permissions::PermissionKinds::deletePerm);
1841 
1842     if (result.Succeeded()) {
1843       if (valid_bp_ids.GetSize() == 0) {
1844         result.SetError("No breakpoints specified, cannot delete names.");
1845         result.SetStatus(eReturnStatusFailed);
1846         return false;
1847       }
1848       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1849       size_t num_valid_ids = valid_bp_ids.GetSize();
1850       for (size_t index = 0; index < num_valid_ids; index++) {
1851         lldb::break_id_t bp_id =
1852             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1853         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1854         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1855       }
1856     }
1857 
1858     return true;
1859   }
1860 
1861 private:
1862   BreakpointNameOptionGroup m_name_options;
1863   OptionGroupOptions m_option_group;
1864 };
1865 
1866 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1867 public:
1868   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1869       : CommandObjectParsed(interpreter, "list",
1870                             "List either the names for a breakpoint or info "
1871                             "about a given name.  With no arguments, lists all "
1872                             "names",
1873                             "breakpoint name list <command-options>"),
1874         m_name_options(), m_option_group() {
1875     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1876     m_option_group.Finalize();
1877   }
1878 
1879   ~CommandObjectBreakpointNameList() override = default;
1880 
1881   Options *GetOptions() override { return &m_option_group; }
1882 
1883 protected:
1884   bool DoExecute(Args &command, CommandReturnObject &result) override {
1885     Target &target =
1886         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1887 
1888     std::vector<std::string> name_list;
1889     if (command.empty()) {
1890       target.GetBreakpointNames(name_list);
1891     } else {
1892       for (const Args::ArgEntry &arg : command) {
1893         name_list.push_back(arg.c_str());
1894       }
1895     }
1896 
1897     if (name_list.empty()) {
1898       result.AppendMessage("No breakpoint names found.");
1899     } else {
1900       for (const std::string &name_str : name_list) {
1901         const char *name = name_str.c_str();
1902         // First print out the options for the name:
1903         Status error;
1904         BreakpointName *bp_name =
1905             target.FindBreakpointName(ConstString(name), false, error);
1906         if (bp_name) {
1907           StreamString s;
1908           result.AppendMessageWithFormat("Name: %s\n", name);
1909           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1910             result.AppendMessage(s.GetString());
1911           }
1912 
1913           std::unique_lock<std::recursive_mutex> lock;
1914           target.GetBreakpointList().GetListMutex(lock);
1915 
1916           BreakpointList &breakpoints = target.GetBreakpointList();
1917           bool any_set = false;
1918           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1919             if (bp_sp->MatchesName(name)) {
1920               StreamString s;
1921               any_set = true;
1922               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1923               s.EOL();
1924               result.AppendMessage(s.GetString());
1925             }
1926           }
1927           if (!any_set)
1928             result.AppendMessage("No breakpoints using this name.");
1929         } else {
1930           result.AppendMessageWithFormat("Name: %s not found.\n", name);
1931         }
1932       }
1933     }
1934     return true;
1935   }
1936 
1937 private:
1938   BreakpointNameOptionGroup m_name_options;
1939   OptionGroupOptions m_option_group;
1940 };
1941 
1942 // CommandObjectBreakpointName
1943 class CommandObjectBreakpointName : public CommandObjectMultiword {
1944 public:
1945   CommandObjectBreakpointName(CommandInterpreter &interpreter)
1946       : CommandObjectMultiword(
1947             interpreter, "name", "Commands to manage name tags for breakpoints",
1948             "breakpoint name <subcommand> [<command-options>]") {
1949     CommandObjectSP add_command_object(
1950         new CommandObjectBreakpointNameAdd(interpreter));
1951     CommandObjectSP delete_command_object(
1952         new CommandObjectBreakpointNameDelete(interpreter));
1953     CommandObjectSP list_command_object(
1954         new CommandObjectBreakpointNameList(interpreter));
1955     CommandObjectSP configure_command_object(
1956         new CommandObjectBreakpointNameConfigure(interpreter));
1957 
1958     LoadSubCommand("add", add_command_object);
1959     LoadSubCommand("delete", delete_command_object);
1960     LoadSubCommand("list", list_command_object);
1961     LoadSubCommand("configure", configure_command_object);
1962   }
1963 
1964   ~CommandObjectBreakpointName() override = default;
1965 };
1966 
1967 // CommandObjectBreakpointRead
1968 #pragma mark Read::CommandOptions
1969 #define LLDB_OPTIONS_breakpoint_read
1970 #include "CommandOptions.inc"
1971 
1972 #pragma mark Read
1973 
1974 class CommandObjectBreakpointRead : public CommandObjectParsed {
1975 public:
1976   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
1977       : CommandObjectParsed(interpreter, "breakpoint read",
1978                             "Read and set the breakpoints previously saved to "
1979                             "a file with \"breakpoint write\".  ",
1980                             nullptr),
1981         m_options() {
1982     CommandArgumentEntry arg;
1983     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1984                                       eArgTypeBreakpointIDRange);
1985     // Add the entry for the first argument for this command to the object's
1986     // arguments vector.
1987     m_arguments.push_back(arg);
1988   }
1989 
1990   ~CommandObjectBreakpointRead() override = default;
1991 
1992   Options *GetOptions() override { return &m_options; }
1993 
1994   class CommandOptions : public Options {
1995   public:
1996     CommandOptions() : Options() {}
1997 
1998     ~CommandOptions() override = default;
1999 
2000     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2001                           ExecutionContext *execution_context) override {
2002       Status error;
2003       const int short_option = m_getopt_table[option_idx].val;
2004 
2005       switch (short_option) {
2006       case 'f':
2007         m_filename.assign(option_arg);
2008         break;
2009       case 'N': {
2010         Status name_error;
2011         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2012                                                   name_error)) {
2013           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2014                                          name_error.AsCString());
2015         }
2016         m_names.push_back(option_arg);
2017         break;
2018       }
2019       default:
2020         llvm_unreachable("Unimplemented option");
2021       }
2022 
2023       return error;
2024     }
2025 
2026     void OptionParsingStarting(ExecutionContext *execution_context) override {
2027       m_filename.clear();
2028       m_names.clear();
2029     }
2030 
2031     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2032       return llvm::makeArrayRef(g_breakpoint_read_options);
2033     }
2034 
2035     // Instance variables to hold the values for command options.
2036 
2037     std::string m_filename;
2038     std::vector<std::string> m_names;
2039   };
2040 
2041 protected:
2042   bool DoExecute(Args &command, CommandReturnObject &result) override {
2043     Target &target = GetSelectedOrDummyTarget();
2044 
2045     std::unique_lock<std::recursive_mutex> lock;
2046     target.GetBreakpointList().GetListMutex(lock);
2047 
2048     FileSpec input_spec(m_options.m_filename);
2049     FileSystem::Instance().Resolve(input_spec);
2050     BreakpointIDList new_bps;
2051     Status error = target.CreateBreakpointsFromFile(input_spec,
2052                                                     m_options.m_names, new_bps);
2053 
2054     if (!error.Success()) {
2055       result.AppendError(error.AsCString());
2056       result.SetStatus(eReturnStatusFailed);
2057       return false;
2058     }
2059 
2060     Stream &output_stream = result.GetOutputStream();
2061 
2062     size_t num_breakpoints = new_bps.GetSize();
2063     if (num_breakpoints == 0) {
2064       result.AppendMessage("No breakpoints added.");
2065     } else {
2066       // No breakpoint selected; show info about all currently set breakpoints.
2067       result.AppendMessage("New breakpoints:");
2068       for (size_t i = 0; i < num_breakpoints; ++i) {
2069         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2070         Breakpoint *bp = target.GetBreakpointList()
2071                              .FindBreakpointByID(bp_id.GetBreakpointID())
2072                              .get();
2073         if (bp)
2074           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2075                              false);
2076       }
2077     }
2078     return result.Succeeded();
2079   }
2080 
2081 private:
2082   CommandOptions m_options;
2083 };
2084 
2085 // CommandObjectBreakpointWrite
2086 #pragma mark Write::CommandOptions
2087 #define LLDB_OPTIONS_breakpoint_write
2088 #include "CommandOptions.inc"
2089 
2090 #pragma mark Write
2091 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2092 public:
2093   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2094       : CommandObjectParsed(interpreter, "breakpoint write",
2095                             "Write the breakpoints listed to a file that can "
2096                             "be read in with \"breakpoint read\".  "
2097                             "If given no arguments, writes all breakpoints.",
2098                             nullptr),
2099         m_options() {
2100     CommandArgumentEntry arg;
2101     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2102                                       eArgTypeBreakpointIDRange);
2103     // Add the entry for the first argument for this command to the object's
2104     // arguments vector.
2105     m_arguments.push_back(arg);
2106   }
2107 
2108   ~CommandObjectBreakpointWrite() override = default;
2109 
2110   Options *GetOptions() override { return &m_options; }
2111 
2112   class CommandOptions : public Options {
2113   public:
2114     CommandOptions() : Options() {}
2115 
2116     ~CommandOptions() override = default;
2117 
2118     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2119                           ExecutionContext *execution_context) override {
2120       Status error;
2121       const int short_option = m_getopt_table[option_idx].val;
2122 
2123       switch (short_option) {
2124       case 'f':
2125         m_filename.assign(option_arg);
2126         break;
2127       case 'a':
2128         m_append = true;
2129         break;
2130       default:
2131         llvm_unreachable("Unimplemented option");
2132       }
2133 
2134       return error;
2135     }
2136 
2137     void OptionParsingStarting(ExecutionContext *execution_context) override {
2138       m_filename.clear();
2139       m_append = false;
2140     }
2141 
2142     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2143       return llvm::makeArrayRef(g_breakpoint_write_options);
2144     }
2145 
2146     // Instance variables to hold the values for command options.
2147 
2148     std::string m_filename;
2149     bool m_append = false;
2150   };
2151 
2152 protected:
2153   bool DoExecute(Args &command, CommandReturnObject &result) override {
2154     Target &target = GetSelectedOrDummyTarget();
2155 
2156     std::unique_lock<std::recursive_mutex> lock;
2157     target.GetBreakpointList().GetListMutex(lock);
2158 
2159     BreakpointIDList valid_bp_ids;
2160     if (!command.empty()) {
2161       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2162           command, &target, result, &valid_bp_ids,
2163           BreakpointName::Permissions::PermissionKinds::listPerm);
2164 
2165       if (!result.Succeeded()) {
2166         result.SetStatus(eReturnStatusFailed);
2167         return false;
2168       }
2169     }
2170     FileSpec file_spec(m_options.m_filename);
2171     FileSystem::Instance().Resolve(file_spec);
2172     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2173                                                      m_options.m_append);
2174     if (!error.Success()) {
2175       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2176                                    error.AsCString());
2177       result.SetStatus(eReturnStatusFailed);
2178     }
2179     return result.Succeeded();
2180   }
2181 
2182 private:
2183   CommandOptions m_options;
2184 };
2185 
2186 // CommandObjectMultiwordBreakpoint
2187 #pragma mark MultiwordBreakpoint
2188 
2189 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2190     CommandInterpreter &interpreter)
2191     : CommandObjectMultiword(
2192           interpreter, "breakpoint",
2193           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2194           "breakpoint <subcommand> [<command-options>]") {
2195   CommandObjectSP list_command_object(
2196       new CommandObjectBreakpointList(interpreter));
2197   CommandObjectSP enable_command_object(
2198       new CommandObjectBreakpointEnable(interpreter));
2199   CommandObjectSP disable_command_object(
2200       new CommandObjectBreakpointDisable(interpreter));
2201   CommandObjectSP clear_command_object(
2202       new CommandObjectBreakpointClear(interpreter));
2203   CommandObjectSP delete_command_object(
2204       new CommandObjectBreakpointDelete(interpreter));
2205   CommandObjectSP set_command_object(
2206       new CommandObjectBreakpointSet(interpreter));
2207   CommandObjectSP command_command_object(
2208       new CommandObjectBreakpointCommand(interpreter));
2209   CommandObjectSP modify_command_object(
2210       new CommandObjectBreakpointModify(interpreter));
2211   CommandObjectSP name_command_object(
2212       new CommandObjectBreakpointName(interpreter));
2213   CommandObjectSP write_command_object(
2214       new CommandObjectBreakpointWrite(interpreter));
2215   CommandObjectSP read_command_object(
2216       new CommandObjectBreakpointRead(interpreter));
2217 
2218   list_command_object->SetCommandName("breakpoint list");
2219   enable_command_object->SetCommandName("breakpoint enable");
2220   disable_command_object->SetCommandName("breakpoint disable");
2221   clear_command_object->SetCommandName("breakpoint clear");
2222   delete_command_object->SetCommandName("breakpoint delete");
2223   set_command_object->SetCommandName("breakpoint set");
2224   command_command_object->SetCommandName("breakpoint command");
2225   modify_command_object->SetCommandName("breakpoint modify");
2226   name_command_object->SetCommandName("breakpoint name");
2227   write_command_object->SetCommandName("breakpoint write");
2228   read_command_object->SetCommandName("breakpoint read");
2229 
2230   LoadSubCommand("list", list_command_object);
2231   LoadSubCommand("enable", enable_command_object);
2232   LoadSubCommand("disable", disable_command_object);
2233   LoadSubCommand("clear", clear_command_object);
2234   LoadSubCommand("delete", delete_command_object);
2235   LoadSubCommand("set", set_command_object);
2236   LoadSubCommand("command", command_command_object);
2237   LoadSubCommand("modify", modify_command_object);
2238   LoadSubCommand("name", name_command_object);
2239   LoadSubCommand("write", write_command_object);
2240   LoadSubCommand("read", read_command_object);
2241 }
2242 
2243 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2244 
2245 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2246     Args &args, Target *target, bool allow_locations,
2247     CommandReturnObject &result, BreakpointIDList *valid_ids,
2248     BreakpointName::Permissions ::PermissionKinds purpose) {
2249   // args can be strings representing 1). integers (for breakpoint ids)
2250   //                                  2). the full breakpoint & location
2251   //                                  canonical representation
2252   //                                  3). the word "to" or a hyphen,
2253   //                                  representing a range (in which case there
2254   //                                      had *better* be an entry both before &
2255   //                                      after of one of the first two types.
2256   //                                  4). A breakpoint name
2257   // If args is empty, we will use the last created breakpoint (if there is
2258   // one.)
2259 
2260   Args temp_args;
2261 
2262   if (args.empty()) {
2263     if (target->GetLastCreatedBreakpoint()) {
2264       valid_ids->AddBreakpointID(BreakpointID(
2265           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2266       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2267     } else {
2268       result.AppendError(
2269           "No breakpoint specified and no last created breakpoint.");
2270       result.SetStatus(eReturnStatusFailed);
2271     }
2272     return;
2273   }
2274 
2275   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2276   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
2277   // id range strings over; instead generate a list of strings for all the
2278   // breakpoint ids in the range, and shove all of those breakpoint id strings
2279   // into TEMP_ARGS.
2280 
2281   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2282                                            purpose, result, temp_args);
2283 
2284   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2285   // BreakpointIDList:
2286 
2287   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2288 
2289   // At this point,  all of the breakpoint ids that the user passed in have
2290   // been converted to breakpoint IDs and put into valid_ids.
2291 
2292   if (result.Succeeded()) {
2293     // Now that we've converted everything from args into a list of breakpoint
2294     // ids, go through our tentative list of breakpoint id's and verify that
2295     // they correspond to valid/currently set breakpoints.
2296 
2297     const size_t count = valid_ids->GetSize();
2298     for (size_t i = 0; i < count; ++i) {
2299       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2300       Breakpoint *breakpoint =
2301           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2302       if (breakpoint != nullptr) {
2303         const size_t num_locations = breakpoint->GetNumLocations();
2304         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2305           StreamString id_str;
2306           BreakpointID::GetCanonicalReference(
2307               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2308           i = valid_ids->GetSize() + 1;
2309           result.AppendErrorWithFormat(
2310               "'%s' is not a currently valid breakpoint/location id.\n",
2311               id_str.GetData());
2312           result.SetStatus(eReturnStatusFailed);
2313         }
2314       } else {
2315         i = valid_ids->GetSize() + 1;
2316         result.AppendErrorWithFormat(
2317             "'%d' is not a currently valid breakpoint ID.\n",
2318             cur_bp_id.GetBreakpointID());
2319         result.SetStatus(eReturnStatusFailed);
2320       }
2321     }
2322   }
2323 }
2324