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