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