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