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