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