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