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     if (command.empty() && !m_options.m_delete_disabled) {
1462       if (!m_options.m_force &&
1463           !m_interpreter.Confirm(
1464               "About to delete all breakpoints, do you want to do that?",
1465               true)) {
1466         result.AppendMessage("Operation cancelled...");
1467       } else {
1468         target.RemoveAllowedBreakpoints();
1469         result.AppendMessageWithFormat(
1470             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1471             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1472       }
1473       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1474     } else {
1475       // Particular breakpoint selected; disable that breakpoint.
1476       BreakpointIDList valid_bp_ids;
1477 
1478       if (m_options.m_delete_disabled) {
1479         BreakpointIDList excluded_bp_ids;
1480 
1481         if (!command.empty()) {
1482           CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1483               command, &target, result, &excluded_bp_ids,
1484               BreakpointName::Permissions::PermissionKinds::deletePerm);
1485         }
1486         for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1487           if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1488             BreakpointID bp_id(breakpoint_sp->GetID());
1489             size_t pos = 0;
1490             if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
1491               valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
1492           }
1493         }
1494         if (valid_bp_ids.GetSize() == 0) {
1495           result.AppendError("No disabled breakpoints.");
1496           return false;
1497         }
1498       } else {
1499         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1500             command, &target, result, &valid_bp_ids,
1501             BreakpointName::Permissions::PermissionKinds::deletePerm);
1502       }
1503 
1504       if (result.Succeeded()) {
1505         int delete_count = 0;
1506         int disable_count = 0;
1507         const size_t count = valid_bp_ids.GetSize();
1508         for (size_t i = 0; i < count; ++i) {
1509           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1510 
1511           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1512             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1513               Breakpoint *breakpoint =
1514                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1515               BreakpointLocation *location =
1516                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1517               // It makes no sense to try to delete individual locations, so we
1518               // disable them instead.
1519               if (location) {
1520                 location->SetEnabled(false);
1521                 ++disable_count;
1522               }
1523             } else {
1524               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1525               ++delete_count;
1526             }
1527           }
1528         }
1529         result.AppendMessageWithFormat(
1530             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1531             delete_count, disable_count);
1532         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1533       }
1534     }
1535     return result.Succeeded();
1536   }
1537 
1538 private:
1539   CommandOptions m_options;
1540 };
1541 
1542 // CommandObjectBreakpointName
1543 #define LLDB_OPTIONS_breakpoint_name
1544 #include "CommandOptions.inc"
1545 
1546 class BreakpointNameOptionGroup : public OptionGroup {
1547 public:
1548   BreakpointNameOptionGroup()
1549       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1550   }
1551 
1552   ~BreakpointNameOptionGroup() override = default;
1553 
1554   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1555     return llvm::makeArrayRef(g_breakpoint_name_options);
1556   }
1557 
1558   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1559                         ExecutionContext *execution_context) override {
1560     Status error;
1561     const int short_option = g_breakpoint_name_options[option_idx].short_option;
1562 
1563     switch (short_option) {
1564     case 'N':
1565       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1566           error.Success())
1567         m_name.SetValueFromString(option_arg);
1568       break;
1569     case 'B':
1570       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1571         error.SetErrorStringWithFormat(
1572             "unrecognized value \"%s\" for breakpoint",
1573             option_arg.str().c_str());
1574       break;
1575     case 'D':
1576       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1577         error.SetErrorStringWithFormat(
1578             "unrecognized value \"%s\" for use-dummy",
1579             option_arg.str().c_str());
1580       break;
1581     case 'H':
1582       m_help_string.SetValueFromString(option_arg);
1583       break;
1584 
1585     default:
1586       llvm_unreachable("Unimplemented option");
1587     }
1588     return error;
1589   }
1590 
1591   void OptionParsingStarting(ExecutionContext *execution_context) override {
1592     m_name.Clear();
1593     m_breakpoint.Clear();
1594     m_use_dummy.Clear();
1595     m_use_dummy.SetDefaultValue(false);
1596     m_help_string.Clear();
1597   }
1598 
1599   OptionValueString m_name;
1600   OptionValueUInt64 m_breakpoint;
1601   OptionValueBoolean m_use_dummy;
1602   OptionValueString m_help_string;
1603 };
1604 
1605 #define LLDB_OPTIONS_breakpoint_access
1606 #include "CommandOptions.inc"
1607 
1608 class BreakpointAccessOptionGroup : public OptionGroup {
1609 public:
1610   BreakpointAccessOptionGroup() : OptionGroup() {}
1611 
1612   ~BreakpointAccessOptionGroup() override = default;
1613 
1614   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1615     return llvm::makeArrayRef(g_breakpoint_access_options);
1616   }
1617   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1618                         ExecutionContext *execution_context) override {
1619     Status error;
1620     const int short_option =
1621         g_breakpoint_access_options[option_idx].short_option;
1622 
1623     switch (short_option) {
1624     case 'L': {
1625       bool value, success;
1626       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1627       if (success) {
1628         m_permissions.SetAllowList(value);
1629       } else
1630         error.SetErrorStringWithFormat(
1631             "invalid boolean value '%s' passed for -L option",
1632             option_arg.str().c_str());
1633     } break;
1634     case 'A': {
1635       bool value, success;
1636       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1637       if (success) {
1638         m_permissions.SetAllowDisable(value);
1639       } else
1640         error.SetErrorStringWithFormat(
1641             "invalid boolean value '%s' passed for -L option",
1642             option_arg.str().c_str());
1643     } break;
1644     case 'D': {
1645       bool value, success;
1646       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1647       if (success) {
1648         m_permissions.SetAllowDelete(value);
1649       } else
1650         error.SetErrorStringWithFormat(
1651             "invalid boolean value '%s' passed for -L option",
1652             option_arg.str().c_str());
1653     } break;
1654     default:
1655       llvm_unreachable("Unimplemented option");
1656     }
1657 
1658     return error;
1659   }
1660 
1661   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1662 
1663   const BreakpointName::Permissions &GetPermissions() const {
1664     return m_permissions;
1665   }
1666   BreakpointName::Permissions m_permissions;
1667 };
1668 
1669 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1670 public:
1671   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1672       : CommandObjectParsed(
1673             interpreter, "configure",
1674             "Configure the options for the breakpoint"
1675             " name provided.  "
1676             "If you provide a breakpoint id, the options will be copied from "
1677             "the breakpoint, otherwise only the options specified will be set "
1678             "on the name.",
1679             "breakpoint name configure <command-options> "
1680             "<breakpoint-name-list>"),
1681         m_bp_opts(), m_option_group() {
1682     // Create the first variant for the first (and only) argument for this
1683     // command.
1684     CommandArgumentEntry arg1;
1685     CommandArgumentData id_arg;
1686     id_arg.arg_type = eArgTypeBreakpointName;
1687     id_arg.arg_repetition = eArgRepeatOptional;
1688     arg1.push_back(id_arg);
1689     m_arguments.push_back(arg1);
1690 
1691     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1692     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1693                           LLDB_OPT_SET_ALL);
1694     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1695                           LLDB_OPT_SET_ALL);
1696     m_option_group.Finalize();
1697   }
1698 
1699   ~CommandObjectBreakpointNameConfigure() override = default;
1700 
1701   Options *GetOptions() override { return &m_option_group; }
1702 
1703 protected:
1704   bool DoExecute(Args &command, CommandReturnObject &result) override {
1705 
1706     const size_t argc = command.GetArgumentCount();
1707     if (argc == 0) {
1708       result.AppendError("No names provided.");
1709       return false;
1710     }
1711 
1712     Target &target = GetSelectedOrDummyTarget(false);
1713 
1714     std::unique_lock<std::recursive_mutex> lock;
1715     target.GetBreakpointList().GetListMutex(lock);
1716 
1717     // Make a pass through first to see that all the names are legal.
1718     for (auto &entry : command.entries()) {
1719       Status error;
1720       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1721         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1722                                      entry.c_str(), error.AsCString());
1723         return false;
1724       }
1725     }
1726     // Now configure them, we already pre-checked the names so we don't need to
1727     // check the error:
1728     BreakpointSP bp_sp;
1729     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1730       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1731       bp_sp = target.GetBreakpointByID(bp_id);
1732       if (!bp_sp) {
1733         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1734                                       bp_id);
1735         return false;
1736       }
1737     }
1738 
1739     Status error;
1740     for (auto &entry : command.entries()) {
1741       ConstString name(entry.c_str());
1742       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1743       if (!bp_name)
1744         continue;
1745       if (m_bp_id.m_help_string.OptionWasSet())
1746         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1747 
1748       if (bp_sp)
1749         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1750                                        m_access_options.GetPermissions());
1751       else
1752         target.ConfigureBreakpointName(*bp_name,
1753                                        m_bp_opts.GetBreakpointOptions(),
1754                                        m_access_options.GetPermissions());
1755     }
1756     return true;
1757   }
1758 
1759 private:
1760   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1761   BreakpointOptionGroup m_bp_opts;
1762   BreakpointAccessOptionGroup m_access_options;
1763   OptionGroupOptions m_option_group;
1764 };
1765 
1766 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1767 public:
1768   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1769       : CommandObjectParsed(
1770             interpreter, "add", "Add a name to the breakpoints provided.",
1771             "breakpoint name add <command-options> <breakpoint-id-list>"),
1772         m_name_options(), m_option_group() {
1773     // Create the first variant for the first (and only) argument for this
1774     // command.
1775     CommandArgumentEntry arg1;
1776     CommandArgumentData id_arg;
1777     id_arg.arg_type = eArgTypeBreakpointID;
1778     id_arg.arg_repetition = eArgRepeatOptional;
1779     arg1.push_back(id_arg);
1780     m_arguments.push_back(arg1);
1781 
1782     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1783     m_option_group.Finalize();
1784   }
1785 
1786   ~CommandObjectBreakpointNameAdd() override = default;
1787 
1788   void
1789   HandleArgumentCompletion(CompletionRequest &request,
1790                            OptionElementVector &opt_element_vector) override {
1791     CommandCompletions::InvokeCommonCompletionCallbacks(
1792         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1793         request, nullptr);
1794   }
1795 
1796   Options *GetOptions() override { return &m_option_group; }
1797 
1798 protected:
1799   bool DoExecute(Args &command, CommandReturnObject &result) override {
1800     if (!m_name_options.m_name.OptionWasSet()) {
1801       result.SetError("No name option provided.");
1802       return false;
1803     }
1804 
1805     Target &target =
1806         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1807 
1808     std::unique_lock<std::recursive_mutex> lock;
1809     target.GetBreakpointList().GetListMutex(lock);
1810 
1811     const BreakpointList &breakpoints = target.GetBreakpointList();
1812 
1813     size_t num_breakpoints = breakpoints.GetSize();
1814     if (num_breakpoints == 0) {
1815       result.SetError("No breakpoints, cannot add names.");
1816       return false;
1817     }
1818 
1819     // Particular breakpoint selected; disable that breakpoint.
1820     BreakpointIDList valid_bp_ids;
1821     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1822         command, &target, result, &valid_bp_ids,
1823         BreakpointName::Permissions::PermissionKinds::listPerm);
1824 
1825     if (result.Succeeded()) {
1826       if (valid_bp_ids.GetSize() == 0) {
1827         result.SetError("No breakpoints specified, cannot add names.");
1828         return false;
1829       }
1830       size_t num_valid_ids = valid_bp_ids.GetSize();
1831       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1832       Status error; // This error reports illegal names, but we've already
1833                     // checked that, so we don't need to check it again here.
1834       for (size_t index = 0; index < num_valid_ids; index++) {
1835         lldb::break_id_t bp_id =
1836             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1837         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1838         target.AddNameToBreakpoint(bp_sp, bp_name, error);
1839       }
1840     }
1841 
1842     return true;
1843   }
1844 
1845 private:
1846   BreakpointNameOptionGroup m_name_options;
1847   OptionGroupOptions m_option_group;
1848 };
1849 
1850 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1851 public:
1852   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1853       : CommandObjectParsed(
1854             interpreter, "delete",
1855             "Delete a name from the breakpoints provided.",
1856             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1857         m_name_options(), m_option_group() {
1858     // Create the first variant for the first (and only) argument for this
1859     // command.
1860     CommandArgumentEntry arg1;
1861     CommandArgumentData id_arg;
1862     id_arg.arg_type = eArgTypeBreakpointID;
1863     id_arg.arg_repetition = eArgRepeatOptional;
1864     arg1.push_back(id_arg);
1865     m_arguments.push_back(arg1);
1866 
1867     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1868     m_option_group.Finalize();
1869   }
1870 
1871   ~CommandObjectBreakpointNameDelete() override = default;
1872 
1873   void
1874   HandleArgumentCompletion(CompletionRequest &request,
1875                            OptionElementVector &opt_element_vector) override {
1876     CommandCompletions::InvokeCommonCompletionCallbacks(
1877         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1878         request, nullptr);
1879   }
1880 
1881   Options *GetOptions() override { return &m_option_group; }
1882 
1883 protected:
1884   bool DoExecute(Args &command, CommandReturnObject &result) override {
1885     if (!m_name_options.m_name.OptionWasSet()) {
1886       result.SetError("No name option provided.");
1887       return false;
1888     }
1889 
1890     Target &target =
1891         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1892 
1893     std::unique_lock<std::recursive_mutex> lock;
1894     target.GetBreakpointList().GetListMutex(lock);
1895 
1896     const BreakpointList &breakpoints = target.GetBreakpointList();
1897 
1898     size_t num_breakpoints = breakpoints.GetSize();
1899     if (num_breakpoints == 0) {
1900       result.SetError("No breakpoints, cannot delete names.");
1901       return false;
1902     }
1903 
1904     // Particular breakpoint selected; disable that breakpoint.
1905     BreakpointIDList valid_bp_ids;
1906     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1907         command, &target, result, &valid_bp_ids,
1908         BreakpointName::Permissions::PermissionKinds::deletePerm);
1909 
1910     if (result.Succeeded()) {
1911       if (valid_bp_ids.GetSize() == 0) {
1912         result.SetError("No breakpoints specified, cannot delete names.");
1913         return false;
1914       }
1915       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1916       size_t num_valid_ids = valid_bp_ids.GetSize();
1917       for (size_t index = 0; index < num_valid_ids; index++) {
1918         lldb::break_id_t bp_id =
1919             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1920         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1921         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1922       }
1923     }
1924 
1925     return true;
1926   }
1927 
1928 private:
1929   BreakpointNameOptionGroup m_name_options;
1930   OptionGroupOptions m_option_group;
1931 };
1932 
1933 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1934 public:
1935   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1936       : CommandObjectParsed(interpreter, "list",
1937                             "List either the names for a breakpoint or info "
1938                             "about a given name.  With no arguments, lists all "
1939                             "names",
1940                             "breakpoint name list <command-options>"),
1941         m_name_options(), m_option_group() {
1942     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1943     m_option_group.Finalize();
1944   }
1945 
1946   ~CommandObjectBreakpointNameList() override = default;
1947 
1948   Options *GetOptions() override { return &m_option_group; }
1949 
1950 protected:
1951   bool DoExecute(Args &command, CommandReturnObject &result) override {
1952     Target &target =
1953         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1954 
1955     std::vector<std::string> name_list;
1956     if (command.empty()) {
1957       target.GetBreakpointNames(name_list);
1958     } else {
1959       for (const Args::ArgEntry &arg : command) {
1960         name_list.push_back(arg.c_str());
1961       }
1962     }
1963 
1964     if (name_list.empty()) {
1965       result.AppendMessage("No breakpoint names found.");
1966     } else {
1967       for (const std::string &name_str : name_list) {
1968         const char *name = name_str.c_str();
1969         // First print out the options for the name:
1970         Status error;
1971         BreakpointName *bp_name =
1972             target.FindBreakpointName(ConstString(name), false, error);
1973         if (bp_name) {
1974           StreamString s;
1975           result.AppendMessageWithFormat("Name: %s\n", name);
1976           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1977             result.AppendMessage(s.GetString());
1978           }
1979 
1980           std::unique_lock<std::recursive_mutex> lock;
1981           target.GetBreakpointList().GetListMutex(lock);
1982 
1983           BreakpointList &breakpoints = target.GetBreakpointList();
1984           bool any_set = false;
1985           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1986             if (bp_sp->MatchesName(name)) {
1987               StreamString s;
1988               any_set = true;
1989               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1990               s.EOL();
1991               result.AppendMessage(s.GetString());
1992             }
1993           }
1994           if (!any_set)
1995             result.AppendMessage("No breakpoints using this name.");
1996         } else {
1997           result.AppendMessageWithFormat("Name: %s not found.\n", name);
1998         }
1999       }
2000     }
2001     return true;
2002   }
2003 
2004 private:
2005   BreakpointNameOptionGroup m_name_options;
2006   OptionGroupOptions m_option_group;
2007 };
2008 
2009 // CommandObjectBreakpointName
2010 class CommandObjectBreakpointName : public CommandObjectMultiword {
2011 public:
2012   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2013       : CommandObjectMultiword(
2014             interpreter, "name", "Commands to manage name tags for breakpoints",
2015             "breakpoint name <subcommand> [<command-options>]") {
2016     CommandObjectSP add_command_object(
2017         new CommandObjectBreakpointNameAdd(interpreter));
2018     CommandObjectSP delete_command_object(
2019         new CommandObjectBreakpointNameDelete(interpreter));
2020     CommandObjectSP list_command_object(
2021         new CommandObjectBreakpointNameList(interpreter));
2022     CommandObjectSP configure_command_object(
2023         new CommandObjectBreakpointNameConfigure(interpreter));
2024 
2025     LoadSubCommand("add", add_command_object);
2026     LoadSubCommand("delete", delete_command_object);
2027     LoadSubCommand("list", list_command_object);
2028     LoadSubCommand("configure", configure_command_object);
2029   }
2030 
2031   ~CommandObjectBreakpointName() override = default;
2032 };
2033 
2034 // CommandObjectBreakpointRead
2035 #pragma mark Read::CommandOptions
2036 #define LLDB_OPTIONS_breakpoint_read
2037 #include "CommandOptions.inc"
2038 
2039 #pragma mark Read
2040 
2041 class CommandObjectBreakpointRead : public CommandObjectParsed {
2042 public:
2043   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2044       : CommandObjectParsed(interpreter, "breakpoint read",
2045                             "Read and set the breakpoints previously saved to "
2046                             "a file with \"breakpoint write\".  ",
2047                             nullptr),
2048         m_options() {}
2049 
2050   ~CommandObjectBreakpointRead() override = default;
2051 
2052   Options *GetOptions() override { return &m_options; }
2053 
2054   class CommandOptions : public Options {
2055   public:
2056     CommandOptions() : Options() {}
2057 
2058     ~CommandOptions() override = default;
2059 
2060     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2061                           ExecutionContext *execution_context) override {
2062       Status error;
2063       const int short_option = m_getopt_table[option_idx].val;
2064 
2065       switch (short_option) {
2066       case 'f':
2067         m_filename.assign(std::string(option_arg));
2068         break;
2069       case 'N': {
2070         Status name_error;
2071         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2072                                                   name_error)) {
2073           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2074                                          name_error.AsCString());
2075         }
2076         m_names.push_back(std::string(option_arg));
2077         break;
2078       }
2079       default:
2080         llvm_unreachable("Unimplemented option");
2081       }
2082 
2083       return error;
2084     }
2085 
2086     void OptionParsingStarting(ExecutionContext *execution_context) override {
2087       m_filename.clear();
2088       m_names.clear();
2089     }
2090 
2091     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2092       return llvm::makeArrayRef(g_breakpoint_read_options);
2093     }
2094 
2095     void HandleOptionArgumentCompletion(
2096         CompletionRequest &request, OptionElementVector &opt_element_vector,
2097         int opt_element_index, CommandInterpreter &interpreter) override {
2098       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2099       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2100 
2101       switch (GetDefinitions()[opt_defs_index].short_option) {
2102       case 'f':
2103         CommandCompletions::InvokeCommonCompletionCallbacks(
2104             interpreter, CommandCompletions::eDiskFileCompletion, request,
2105             nullptr);
2106         break;
2107 
2108       case 'N':
2109         llvm::Optional<FileSpec> file_spec;
2110         const llvm::StringRef dash_f("-f");
2111         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2112           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2113             file_spec.emplace(
2114                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2115             break;
2116           }
2117         }
2118         if (!file_spec)
2119           return;
2120 
2121         FileSystem::Instance().Resolve(*file_spec);
2122         Status error;
2123         StructuredData::ObjectSP input_data_sp =
2124             StructuredData::ParseJSONFromFile(*file_spec, error);
2125         if (!error.Success())
2126           return;
2127 
2128         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2129         if (!bkpt_array)
2130           return;
2131 
2132         const size_t num_bkpts = bkpt_array->GetSize();
2133         for (size_t i = 0; i < num_bkpts; i++) {
2134           StructuredData::ObjectSP bkpt_object_sp =
2135               bkpt_array->GetItemAtIndex(i);
2136           if (!bkpt_object_sp)
2137             return;
2138 
2139           StructuredData::Dictionary *bkpt_dict =
2140               bkpt_object_sp->GetAsDictionary();
2141           if (!bkpt_dict)
2142             return;
2143 
2144           StructuredData::ObjectSP bkpt_data_sp =
2145               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2146           if (!bkpt_data_sp)
2147             return;
2148 
2149           bkpt_dict = bkpt_data_sp->GetAsDictionary();
2150           if (!bkpt_dict)
2151             return;
2152 
2153           StructuredData::Array *names_array;
2154 
2155           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2156             return;
2157 
2158           size_t num_names = names_array->GetSize();
2159 
2160           for (size_t i = 0; i < num_names; i++) {
2161             llvm::StringRef name;
2162             if (names_array->GetItemAtIndexAsString(i, name))
2163               request.TryCompleteCurrentArg(name);
2164           }
2165         }
2166       }
2167     }
2168 
2169     std::string m_filename;
2170     std::vector<std::string> m_names;
2171   };
2172 
2173 protected:
2174   bool DoExecute(Args &command, CommandReturnObject &result) override {
2175     Target &target = GetSelectedOrDummyTarget();
2176 
2177     std::unique_lock<std::recursive_mutex> lock;
2178     target.GetBreakpointList().GetListMutex(lock);
2179 
2180     FileSpec input_spec(m_options.m_filename);
2181     FileSystem::Instance().Resolve(input_spec);
2182     BreakpointIDList new_bps;
2183     Status error = target.CreateBreakpointsFromFile(input_spec,
2184                                                     m_options.m_names, new_bps);
2185 
2186     if (!error.Success()) {
2187       result.AppendError(error.AsCString());
2188       return false;
2189     }
2190 
2191     Stream &output_stream = result.GetOutputStream();
2192 
2193     size_t num_breakpoints = new_bps.GetSize();
2194     if (num_breakpoints == 0) {
2195       result.AppendMessage("No breakpoints added.");
2196     } else {
2197       // No breakpoint selected; show info about all currently set breakpoints.
2198       result.AppendMessage("New breakpoints:");
2199       for (size_t i = 0; i < num_breakpoints; ++i) {
2200         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2201         Breakpoint *bp = target.GetBreakpointList()
2202                              .FindBreakpointByID(bp_id.GetBreakpointID())
2203                              .get();
2204         if (bp)
2205           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2206                              false);
2207       }
2208     }
2209     return result.Succeeded();
2210   }
2211 
2212 private:
2213   CommandOptions m_options;
2214 };
2215 
2216 // CommandObjectBreakpointWrite
2217 #pragma mark Write::CommandOptions
2218 #define LLDB_OPTIONS_breakpoint_write
2219 #include "CommandOptions.inc"
2220 
2221 #pragma mark Write
2222 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2223 public:
2224   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2225       : CommandObjectParsed(interpreter, "breakpoint write",
2226                             "Write the breakpoints listed to a file that can "
2227                             "be read in with \"breakpoint read\".  "
2228                             "If given no arguments, writes all breakpoints.",
2229                             nullptr),
2230         m_options() {
2231     CommandArgumentEntry arg;
2232     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2233                                       eArgTypeBreakpointIDRange);
2234     // Add the entry for the first argument for this command to the object's
2235     // arguments vector.
2236     m_arguments.push_back(arg);
2237   }
2238 
2239   ~CommandObjectBreakpointWrite() override = default;
2240 
2241   void
2242   HandleArgumentCompletion(CompletionRequest &request,
2243                            OptionElementVector &opt_element_vector) override {
2244     CommandCompletions::InvokeCommonCompletionCallbacks(
2245         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2246         request, nullptr);
2247   }
2248 
2249   Options *GetOptions() override { return &m_options; }
2250 
2251   class CommandOptions : public Options {
2252   public:
2253     CommandOptions() : Options() {}
2254 
2255     ~CommandOptions() override = default;
2256 
2257     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2258                           ExecutionContext *execution_context) override {
2259       Status error;
2260       const int short_option = m_getopt_table[option_idx].val;
2261 
2262       switch (short_option) {
2263       case 'f':
2264         m_filename.assign(std::string(option_arg));
2265         break;
2266       case 'a':
2267         m_append = true;
2268         break;
2269       default:
2270         llvm_unreachable("Unimplemented option");
2271       }
2272 
2273       return error;
2274     }
2275 
2276     void OptionParsingStarting(ExecutionContext *execution_context) override {
2277       m_filename.clear();
2278       m_append = false;
2279     }
2280 
2281     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2282       return llvm::makeArrayRef(g_breakpoint_write_options);
2283     }
2284 
2285     // Instance variables to hold the values for command options.
2286 
2287     std::string m_filename;
2288     bool m_append = false;
2289   };
2290 
2291 protected:
2292   bool DoExecute(Args &command, CommandReturnObject &result) override {
2293     Target &target = GetSelectedOrDummyTarget();
2294 
2295     std::unique_lock<std::recursive_mutex> lock;
2296     target.GetBreakpointList().GetListMutex(lock);
2297 
2298     BreakpointIDList valid_bp_ids;
2299     if (!command.empty()) {
2300       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2301           command, &target, result, &valid_bp_ids,
2302           BreakpointName::Permissions::PermissionKinds::listPerm);
2303 
2304       if (!result.Succeeded()) {
2305         result.SetStatus(eReturnStatusFailed);
2306         return false;
2307       }
2308     }
2309     FileSpec file_spec(m_options.m_filename);
2310     FileSystem::Instance().Resolve(file_spec);
2311     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2312                                                      m_options.m_append);
2313     if (!error.Success()) {
2314       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2315                                    error.AsCString());
2316     }
2317     return result.Succeeded();
2318   }
2319 
2320 private:
2321   CommandOptions m_options;
2322 };
2323 
2324 // CommandObjectMultiwordBreakpoint
2325 #pragma mark MultiwordBreakpoint
2326 
2327 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2328     CommandInterpreter &interpreter)
2329     : CommandObjectMultiword(
2330           interpreter, "breakpoint",
2331           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2332           "breakpoint <subcommand> [<command-options>]") {
2333   CommandObjectSP list_command_object(
2334       new CommandObjectBreakpointList(interpreter));
2335   CommandObjectSP enable_command_object(
2336       new CommandObjectBreakpointEnable(interpreter));
2337   CommandObjectSP disable_command_object(
2338       new CommandObjectBreakpointDisable(interpreter));
2339   CommandObjectSP clear_command_object(
2340       new CommandObjectBreakpointClear(interpreter));
2341   CommandObjectSP delete_command_object(
2342       new CommandObjectBreakpointDelete(interpreter));
2343   CommandObjectSP set_command_object(
2344       new CommandObjectBreakpointSet(interpreter));
2345   CommandObjectSP command_command_object(
2346       new CommandObjectBreakpointCommand(interpreter));
2347   CommandObjectSP modify_command_object(
2348       new CommandObjectBreakpointModify(interpreter));
2349   CommandObjectSP name_command_object(
2350       new CommandObjectBreakpointName(interpreter));
2351   CommandObjectSP write_command_object(
2352       new CommandObjectBreakpointWrite(interpreter));
2353   CommandObjectSP read_command_object(
2354       new CommandObjectBreakpointRead(interpreter));
2355 
2356   list_command_object->SetCommandName("breakpoint list");
2357   enable_command_object->SetCommandName("breakpoint enable");
2358   disable_command_object->SetCommandName("breakpoint disable");
2359   clear_command_object->SetCommandName("breakpoint clear");
2360   delete_command_object->SetCommandName("breakpoint delete");
2361   set_command_object->SetCommandName("breakpoint set");
2362   command_command_object->SetCommandName("breakpoint command");
2363   modify_command_object->SetCommandName("breakpoint modify");
2364   name_command_object->SetCommandName("breakpoint name");
2365   write_command_object->SetCommandName("breakpoint write");
2366   read_command_object->SetCommandName("breakpoint read");
2367 
2368   LoadSubCommand("list", list_command_object);
2369   LoadSubCommand("enable", enable_command_object);
2370   LoadSubCommand("disable", disable_command_object);
2371   LoadSubCommand("clear", clear_command_object);
2372   LoadSubCommand("delete", delete_command_object);
2373   LoadSubCommand("set", set_command_object);
2374   LoadSubCommand("command", command_command_object);
2375   LoadSubCommand("modify", modify_command_object);
2376   LoadSubCommand("name", name_command_object);
2377   LoadSubCommand("write", write_command_object);
2378   LoadSubCommand("read", read_command_object);
2379 }
2380 
2381 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2382 
2383 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2384     Args &args, Target *target, bool allow_locations,
2385     CommandReturnObject &result, BreakpointIDList *valid_ids,
2386     BreakpointName::Permissions ::PermissionKinds purpose) {
2387   // args can be strings representing 1). integers (for breakpoint ids)
2388   //                                  2). the full breakpoint & location
2389   //                                  canonical representation
2390   //                                  3). the word "to" or a hyphen,
2391   //                                  representing a range (in which case there
2392   //                                      had *better* be an entry both before &
2393   //                                      after of one of the first two types.
2394   //                                  4). A breakpoint name
2395   // If args is empty, we will use the last created breakpoint (if there is
2396   // one.)
2397 
2398   Args temp_args;
2399 
2400   if (args.empty()) {
2401     if (target->GetLastCreatedBreakpoint()) {
2402       valid_ids->AddBreakpointID(BreakpointID(
2403           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2404       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2405     } else {
2406       result.AppendError(
2407           "No breakpoint specified and no last created breakpoint.");
2408     }
2409     return;
2410   }
2411 
2412   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2413   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
2414   // id range strings over; instead generate a list of strings for all the
2415   // breakpoint ids in the range, and shove all of those breakpoint id strings
2416   // into TEMP_ARGS.
2417 
2418   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2419                                            purpose, result, temp_args);
2420 
2421   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2422   // BreakpointIDList:
2423 
2424   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2425 
2426   // At this point,  all of the breakpoint ids that the user passed in have
2427   // been converted to breakpoint IDs and put into valid_ids.
2428 
2429   if (result.Succeeded()) {
2430     // Now that we've converted everything from args into a list of breakpoint
2431     // ids, go through our tentative list of breakpoint id's and verify that
2432     // they correspond to valid/currently set breakpoints.
2433 
2434     const size_t count = valid_ids->GetSize();
2435     for (size_t i = 0; i < count; ++i) {
2436       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2437       Breakpoint *breakpoint =
2438           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2439       if (breakpoint != nullptr) {
2440         const size_t num_locations = breakpoint->GetNumLocations();
2441         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2442           StreamString id_str;
2443           BreakpointID::GetCanonicalReference(
2444               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2445           i = valid_ids->GetSize() + 1;
2446           result.AppendErrorWithFormat(
2447               "'%s' is not a currently valid breakpoint/location id.\n",
2448               id_str.GetData());
2449         }
2450       } else {
2451         i = valid_ids->GetSize() + 1;
2452         result.AppendErrorWithFormat(
2453             "'%d' is not a currently valid breakpoint ID.\n",
2454             cur_bp_id.GetBreakpointID());
2455       }
2456     }
2457   }
2458 }
2459