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 = llvm::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 (!regexp.IsValid()) {
686           char err_str[1024];
687           regexp.GetErrorAsCString(err_str, sizeof(err_str));
688           result.AppendErrorWithFormat(
689               "Function name regular expression could not be compiled: \"%s\"",
690               err_str);
691           result.SetStatus(eReturnStatusFailed);
692           return false;
693         }
694 
695         bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
696                                                   &(m_options.m_filenames),
697                                                   regexp,
698                                                   m_options.m_language,
699                                                   m_options.m_skip_prologue,
700                                                   internal,
701                                                   m_options.m_hardware);
702       }
703       break;
704     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
705     {
706       const size_t num_files = m_options.m_filenames.GetSize();
707 
708       if (num_files == 0 && !m_options.m_all_files) {
709         FileSpec file;
710         if (!GetDefaultFile(target, file, result)) {
711           result.AppendError(
712               "No files provided and could not find default file.");
713           result.SetStatus(eReturnStatusFailed);
714           return false;
715         } else {
716           m_options.m_filenames.Append(file);
717         }
718       }
719 
720       RegularExpression regexp(m_options.m_source_text_regexp);
721       if (!regexp.IsValid()) {
722         char err_str[1024];
723         regexp.GetErrorAsCString(err_str, sizeof(err_str));
724         result.AppendErrorWithFormat(
725             "Source text regular expression could not be compiled: \"%s\"",
726             err_str);
727         result.SetStatus(eReturnStatusFailed);
728         return false;
729       }
730       bp_sp =
731           target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
732                                               &(m_options.m_filenames),
733                                               m_options
734                                                   .m_source_regex_func_names,
735                                               regexp,
736                                               internal,
737                                               m_options.m_hardware,
738                                               m_options.m_move_to_nearest_code);
739     } break;
740     case eSetTypeException: {
741       Status precond_error;
742       bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
743                                                 m_options.m_catch_bp,
744                                                 m_options.m_throw_bp,
745                                                 internal,
746                                                 &m_options
747                                                     .m_exception_extra_args,
748                                                 &precond_error);
749       if (precond_error.Fail()) {
750         result.AppendErrorWithFormat(
751             "Error setting extra exception arguments: %s",
752             precond_error.AsCString());
753         target->RemoveBreakpointByID(bp_sp->GetID());
754         result.SetStatus(eReturnStatusFailed);
755         return false;
756       }
757     } break;
758     case eSetTypeScripted: {
759 
760       Status error;
761       bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
762                                                &(m_options.m_modules),
763                                                &(m_options.m_filenames),
764                                                false,
765                                                m_options.m_hardware,
766                                                m_options.m_extra_args_sp,
767                                                &error);
768       if (error.Fail()) {
769         result.AppendErrorWithFormat(
770             "Error setting extra exception arguments: %s",
771             error.AsCString());
772         target->RemoveBreakpointByID(bp_sp->GetID());
773         result.SetStatus(eReturnStatusFailed);
774         return false;
775       }
776     } break;
777     default:
778       break;
779     }
780 
781     // Now set the various options that were passed in:
782     if (bp_sp) {
783       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
784 
785       if (!m_options.m_breakpoint_names.empty()) {
786         Status name_error;
787         for (auto name : m_options.m_breakpoint_names) {
788           target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
789           if (name_error.Fail()) {
790             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
791                                          name.c_str());
792             target->RemoveBreakpointByID(bp_sp->GetID());
793             result.SetStatus(eReturnStatusFailed);
794             return false;
795           }
796         }
797       }
798     }
799 
800     if (bp_sp) {
801       Stream &output_stream = result.GetOutputStream();
802       const bool show_locations = false;
803       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
804                          show_locations);
805       if (target == GetDebugger().GetDummyTarget())
806         output_stream.Printf("Breakpoint set in dummy target, will get copied "
807                              "into future targets.\n");
808       else {
809         // Don't print out this warning for exception breakpoints.  They can
810         // get set before the target is set, but we won't know how to actually
811         // set the breakpoint till we run.
812         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
813           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
814                                "actual locations.\n");
815         }
816       }
817       result.SetStatus(eReturnStatusSuccessFinishResult);
818     } else if (!bp_sp) {
819       result.AppendError("Breakpoint creation failed: No breakpoint created.");
820       result.SetStatus(eReturnStatusFailed);
821     }
822 
823     return result.Succeeded();
824   }
825 
826 private:
827   bool GetDefaultFile(Target *target, FileSpec &file,
828                       CommandReturnObject &result) {
829     uint32_t default_line;
830     // First use the Source Manager's default file. Then use the current stack
831     // frame's file.
832     if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
833       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
834       if (cur_frame == nullptr) {
835         result.AppendError(
836             "No selected frame to use to find the default file.");
837         result.SetStatus(eReturnStatusFailed);
838         return false;
839       } else if (!cur_frame->HasDebugInformation()) {
840         result.AppendError("Cannot use the selected frame to find the default "
841                            "file, it has no debug info.");
842         result.SetStatus(eReturnStatusFailed);
843         return false;
844       } else {
845         const SymbolContext &sc =
846             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
847         if (sc.line_entry.file) {
848           file = sc.line_entry.file;
849         } else {
850           result.AppendError("Can't find the file for the selected frame to "
851                              "use as the default file.");
852           result.SetStatus(eReturnStatusFailed);
853           return false;
854         }
855       }
856     }
857     return true;
858   }
859 
860   BreakpointOptionGroup m_bp_opts;
861   BreakpointDummyOptionGroup m_dummy_options;
862   CommandOptions m_options;
863   OptionGroupOptions m_all_options;
864 };
865 
866 // CommandObjectBreakpointModify
867 #pragma mark Modify
868 
869 class CommandObjectBreakpointModify : public CommandObjectParsed {
870 public:
871   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
872       : CommandObjectParsed(interpreter, "breakpoint modify",
873                             "Modify the options on a breakpoint or set of "
874                             "breakpoints in the executable.  "
875                             "If no breakpoint is specified, acts on the last "
876                             "created breakpoint.  "
877                             "With the exception of -e, -d and -i, passing an "
878                             "empty argument clears the modification.",
879                             nullptr),
880         m_options() {
881     CommandArgumentEntry arg;
882     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
883                                       eArgTypeBreakpointIDRange);
884     // Add the entry for the first argument for this command to the object's
885     // arguments vector.
886     m_arguments.push_back(arg);
887 
888     m_options.Append(&m_bp_opts,
889                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
890                      LLDB_OPT_SET_ALL);
891     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
892     m_options.Finalize();
893   }
894 
895   ~CommandObjectBreakpointModify() override = default;
896 
897   Options *GetOptions() override { return &m_options; }
898 
899 protected:
900   bool DoExecute(Args &command, CommandReturnObject &result) override {
901     Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
902     if (target == nullptr) {
903       result.AppendError("Invalid target.  No existing target or breakpoints.");
904       result.SetStatus(eReturnStatusFailed);
905       return false;
906     }
907 
908     std::unique_lock<std::recursive_mutex> lock;
909     target->GetBreakpointList().GetListMutex(lock);
910 
911     BreakpointIDList valid_bp_ids;
912 
913     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
914         command, target, result, &valid_bp_ids,
915         BreakpointName::Permissions::PermissionKinds::disablePerm);
916 
917     if (result.Succeeded()) {
918       const size_t count = valid_bp_ids.GetSize();
919       for (size_t i = 0; i < count; ++i) {
920         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
921 
922         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
923           Breakpoint *bp =
924               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
925           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
926             BreakpointLocation *location =
927                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
928             if (location)
929               location->GetLocationOptions()
930                   ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
931           } else {
932             bp->GetOptions()
933                 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
934           }
935         }
936       }
937     }
938 
939     return result.Succeeded();
940   }
941 
942 private:
943   BreakpointOptionGroup m_bp_opts;
944   BreakpointDummyOptionGroup m_dummy_opts;
945   OptionGroupOptions m_options;
946 };
947 
948 // CommandObjectBreakpointEnable
949 #pragma mark Enable
950 
951 class CommandObjectBreakpointEnable : public CommandObjectParsed {
952 public:
953   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
954       : CommandObjectParsed(interpreter, "enable",
955                             "Enable the specified disabled breakpoint(s). If "
956                             "no breakpoints are specified, enable all of them.",
957                             nullptr) {
958     CommandArgumentEntry arg;
959     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
960                                       eArgTypeBreakpointIDRange);
961     // Add the entry for the first argument for this command to the object's
962     // arguments vector.
963     m_arguments.push_back(arg);
964   }
965 
966   ~CommandObjectBreakpointEnable() override = default;
967 
968 protected:
969   bool DoExecute(Args &command, CommandReturnObject &result) override {
970     Target *target = GetSelectedOrDummyTarget();
971     if (target == nullptr) {
972       result.AppendError("Invalid target.  No existing target or breakpoints.");
973       result.SetStatus(eReturnStatusFailed);
974       return false;
975     }
976 
977     std::unique_lock<std::recursive_mutex> lock;
978     target->GetBreakpointList().GetListMutex(lock);
979 
980     const BreakpointList &breakpoints = target->GetBreakpointList();
981 
982     size_t num_breakpoints = breakpoints.GetSize();
983 
984     if (num_breakpoints == 0) {
985       result.AppendError("No breakpoints exist to be enabled.");
986       result.SetStatus(eReturnStatusFailed);
987       return false;
988     }
989 
990     if (command.empty()) {
991       // No breakpoint selected; enable all currently set breakpoints.
992       target->EnableAllowedBreakpoints();
993       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
994                                      " breakpoints)\n",
995                                      (uint64_t)num_breakpoints);
996       result.SetStatus(eReturnStatusSuccessFinishNoResult);
997     } else {
998       // Particular breakpoint selected; enable that breakpoint.
999       BreakpointIDList valid_bp_ids;
1000       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1001           command, target, result, &valid_bp_ids,
1002           BreakpointName::Permissions::PermissionKinds::disablePerm);
1003 
1004       if (result.Succeeded()) {
1005         int enable_count = 0;
1006         int loc_count = 0;
1007         const size_t count = valid_bp_ids.GetSize();
1008         for (size_t i = 0; i < count; ++i) {
1009           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1010 
1011           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1012             Breakpoint *breakpoint =
1013                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1014             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1015               BreakpointLocation *location =
1016                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1017               if (location) {
1018                 location->SetEnabled(true);
1019                 ++loc_count;
1020               }
1021             } else {
1022               breakpoint->SetEnabled(true);
1023               ++enable_count;
1024             }
1025           }
1026         }
1027         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1028                                        enable_count + loc_count);
1029         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1030       }
1031     }
1032 
1033     return result.Succeeded();
1034   }
1035 };
1036 
1037 // CommandObjectBreakpointDisable
1038 #pragma mark Disable
1039 
1040 class CommandObjectBreakpointDisable : public CommandObjectParsed {
1041 public:
1042   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1043       : CommandObjectParsed(
1044             interpreter, "breakpoint disable",
1045             "Disable the specified breakpoint(s) without deleting "
1046             "them.  If none are specified, disable all "
1047             "breakpoints.",
1048             nullptr) {
1049     SetHelpLong(
1050         "Disable the specified breakpoint(s) without deleting them.  \
1051 If none are specified, disable all breakpoints."
1052         R"(
1053 
1054 )"
1055         "Note: disabling a breakpoint will cause none of its locations to be hit \
1056 regardless of whether individual locations are enabled or disabled.  After the sequence:"
1057         R"(
1058 
1059     (lldb) break disable 1
1060     (lldb) break enable 1.1
1061 
1062 execution will NOT stop at location 1.1.  To achieve that, type:
1063 
1064     (lldb) break disable 1.*
1065     (lldb) break enable 1.1
1066 
1067 )"
1068         "The first command disables all locations for breakpoint 1, \
1069 the second re-enables the first location.");
1070 
1071     CommandArgumentEntry arg;
1072     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1073                                       eArgTypeBreakpointIDRange);
1074     // Add the entry for the first argument for this command to the object's
1075     // arguments vector.
1076     m_arguments.push_back(arg);
1077   }
1078 
1079   ~CommandObjectBreakpointDisable() override = default;
1080 
1081 protected:
1082   bool DoExecute(Args &command, CommandReturnObject &result) override {
1083     Target *target = GetSelectedOrDummyTarget();
1084     if (target == nullptr) {
1085       result.AppendError("Invalid target.  No existing target or breakpoints.");
1086       result.SetStatus(eReturnStatusFailed);
1087       return false;
1088     }
1089 
1090     std::unique_lock<std::recursive_mutex> lock;
1091     target->GetBreakpointList().GetListMutex(lock);
1092 
1093     const BreakpointList &breakpoints = target->GetBreakpointList();
1094     size_t num_breakpoints = breakpoints.GetSize();
1095 
1096     if (num_breakpoints == 0) {
1097       result.AppendError("No breakpoints exist to be disabled.");
1098       result.SetStatus(eReturnStatusFailed);
1099       return false;
1100     }
1101 
1102     if (command.empty()) {
1103       // No breakpoint selected; disable all currently set breakpoints.
1104       target->DisableAllowedBreakpoints();
1105       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1106                                      " breakpoints)\n",
1107                                      (uint64_t)num_breakpoints);
1108       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1109     } else {
1110       // Particular breakpoint selected; disable that breakpoint.
1111       BreakpointIDList valid_bp_ids;
1112 
1113       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1114           command, target, result, &valid_bp_ids,
1115           BreakpointName::Permissions::PermissionKinds::disablePerm);
1116 
1117       if (result.Succeeded()) {
1118         int disable_count = 0;
1119         int loc_count = 0;
1120         const size_t count = valid_bp_ids.GetSize();
1121         for (size_t i = 0; i < count; ++i) {
1122           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1123 
1124           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1125             Breakpoint *breakpoint =
1126                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1127             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1128               BreakpointLocation *location =
1129                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1130               if (location) {
1131                 location->SetEnabled(false);
1132                 ++loc_count;
1133               }
1134             } else {
1135               breakpoint->SetEnabled(false);
1136               ++disable_count;
1137             }
1138           }
1139         }
1140         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1141                                        disable_count + loc_count);
1142         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1143       }
1144     }
1145 
1146     return result.Succeeded();
1147   }
1148 };
1149 
1150 // CommandObjectBreakpointList
1151 
1152 #pragma mark List::CommandOptions
1153 #define LLDB_OPTIONS_breakpoint_list
1154 #include "CommandOptions.inc"
1155 
1156 #pragma mark List
1157 
1158 class CommandObjectBreakpointList : public CommandObjectParsed {
1159 public:
1160   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1161       : CommandObjectParsed(
1162             interpreter, "breakpoint list",
1163             "List some or all breakpoints at configurable levels of detail.",
1164             nullptr),
1165         m_options() {
1166     CommandArgumentEntry arg;
1167     CommandArgumentData bp_id_arg;
1168 
1169     // Define the first (and only) variant of this arg.
1170     bp_id_arg.arg_type = eArgTypeBreakpointID;
1171     bp_id_arg.arg_repetition = eArgRepeatOptional;
1172 
1173     // There is only one variant this argument could be; put it into the
1174     // argument entry.
1175     arg.push_back(bp_id_arg);
1176 
1177     // Push the data for the first argument into the m_arguments vector.
1178     m_arguments.push_back(arg);
1179   }
1180 
1181   ~CommandObjectBreakpointList() override = default;
1182 
1183   Options *GetOptions() override { return &m_options; }
1184 
1185   class CommandOptions : public Options {
1186   public:
1187     CommandOptions()
1188         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1189     }
1190 
1191     ~CommandOptions() override = default;
1192 
1193     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1194                           ExecutionContext *execution_context) override {
1195       Status error;
1196       const int short_option = m_getopt_table[option_idx].val;
1197 
1198       switch (short_option) {
1199       case 'b':
1200         m_level = lldb::eDescriptionLevelBrief;
1201         break;
1202       case 'D':
1203         m_use_dummy = true;
1204         break;
1205       case 'f':
1206         m_level = lldb::eDescriptionLevelFull;
1207         break;
1208       case 'v':
1209         m_level = lldb::eDescriptionLevelVerbose;
1210         break;
1211       case 'i':
1212         m_internal = true;
1213         break;
1214       default:
1215         error.SetErrorStringWithFormat("unrecognized option '%c'",
1216                                        short_option);
1217         break;
1218       }
1219 
1220       return error;
1221     }
1222 
1223     void OptionParsingStarting(ExecutionContext *execution_context) override {
1224       m_level = lldb::eDescriptionLevelFull;
1225       m_internal = false;
1226       m_use_dummy = false;
1227     }
1228 
1229     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1230       return llvm::makeArrayRef(g_breakpoint_list_options);
1231     }
1232 
1233     // Instance variables to hold the values for command options.
1234 
1235     lldb::DescriptionLevel m_level;
1236 
1237     bool m_internal;
1238     bool m_use_dummy;
1239   };
1240 
1241 protected:
1242   bool DoExecute(Args &command, CommandReturnObject &result) override {
1243     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1244 
1245     if (target == nullptr) {
1246       result.AppendError("Invalid target. No current target or breakpoints.");
1247       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1248       return true;
1249     }
1250 
1251     const BreakpointList &breakpoints =
1252         target->GetBreakpointList(m_options.m_internal);
1253     std::unique_lock<std::recursive_mutex> lock;
1254     target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1255 
1256     size_t num_breakpoints = breakpoints.GetSize();
1257 
1258     if (num_breakpoints == 0) {
1259       result.AppendMessage("No breakpoints currently set.");
1260       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1261       return true;
1262     }
1263 
1264     Stream &output_stream = result.GetOutputStream();
1265 
1266     if (command.empty()) {
1267       // No breakpoint selected; show info about all currently set breakpoints.
1268       result.AppendMessage("Current breakpoints:");
1269       for (size_t i = 0; i < num_breakpoints; ++i) {
1270         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1271         if (breakpoint->AllowList())
1272           AddBreakpointDescription(&output_stream, breakpoint,
1273                                    m_options.m_level);
1274       }
1275       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1276     } else {
1277       // Particular breakpoints selected; show info about that breakpoint.
1278       BreakpointIDList valid_bp_ids;
1279       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1280           command, target, result, &valid_bp_ids,
1281           BreakpointName::Permissions::PermissionKinds::listPerm);
1282 
1283       if (result.Succeeded()) {
1284         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1285           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1286           Breakpoint *breakpoint =
1287               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1288           AddBreakpointDescription(&output_stream, breakpoint,
1289                                    m_options.m_level);
1290         }
1291         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1292       } else {
1293         result.AppendError("Invalid breakpoint ID.");
1294         result.SetStatus(eReturnStatusFailed);
1295       }
1296     }
1297 
1298     return result.Succeeded();
1299   }
1300 
1301 private:
1302   CommandOptions m_options;
1303 };
1304 
1305 // CommandObjectBreakpointClear
1306 #pragma mark Clear::CommandOptions
1307 
1308 #define LLDB_OPTIONS_breakpoint_clear
1309 #include "CommandOptions.inc"
1310 
1311 #pragma mark Clear
1312 
1313 class CommandObjectBreakpointClear : public CommandObjectParsed {
1314 public:
1315   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1316 
1317   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1318       : CommandObjectParsed(interpreter, "breakpoint clear",
1319                             "Delete or disable breakpoints matching the "
1320                             "specified source file and line.",
1321                             "breakpoint clear <cmd-options>"),
1322         m_options() {}
1323 
1324   ~CommandObjectBreakpointClear() override = default;
1325 
1326   Options *GetOptions() override { return &m_options; }
1327 
1328   class CommandOptions : public Options {
1329   public:
1330     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1331 
1332     ~CommandOptions() override = default;
1333 
1334     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1335                           ExecutionContext *execution_context) override {
1336       Status error;
1337       const int short_option = m_getopt_table[option_idx].val;
1338 
1339       switch (short_option) {
1340       case 'f':
1341         m_filename.assign(option_arg);
1342         break;
1343 
1344       case 'l':
1345         option_arg.getAsInteger(0, m_line_num);
1346         break;
1347 
1348       default:
1349         error.SetErrorStringWithFormat("unrecognized option '%c'",
1350                                        short_option);
1351         break;
1352       }
1353 
1354       return error;
1355     }
1356 
1357     void OptionParsingStarting(ExecutionContext *execution_context) override {
1358       m_filename.clear();
1359       m_line_num = 0;
1360     }
1361 
1362     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1363       return llvm::makeArrayRef(g_breakpoint_clear_options);
1364     }
1365 
1366     // Instance variables to hold the values for command options.
1367 
1368     std::string m_filename;
1369     uint32_t m_line_num;
1370   };
1371 
1372 protected:
1373   bool DoExecute(Args &command, CommandReturnObject &result) override {
1374     Target *target = GetSelectedOrDummyTarget();
1375     if (target == nullptr) {
1376       result.AppendError("Invalid target. No existing target or breakpoints.");
1377       result.SetStatus(eReturnStatusFailed);
1378       return false;
1379     }
1380 
1381     // The following are the various types of breakpoints that could be
1382     // cleared:
1383     //   1). -f -l (clearing breakpoint by source location)
1384 
1385     BreakpointClearType break_type = eClearTypeInvalid;
1386 
1387     if (m_options.m_line_num != 0)
1388       break_type = eClearTypeFileAndLine;
1389 
1390     std::unique_lock<std::recursive_mutex> lock;
1391     target->GetBreakpointList().GetListMutex(lock);
1392 
1393     BreakpointList &breakpoints = target->GetBreakpointList();
1394     size_t num_breakpoints = breakpoints.GetSize();
1395 
1396     // Early return if there's no breakpoint at all.
1397     if (num_breakpoints == 0) {
1398       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1399       result.SetStatus(eReturnStatusFailed);
1400       return result.Succeeded();
1401     }
1402 
1403     // Find matching breakpoints and delete them.
1404 
1405     // First create a copy of all the IDs.
1406     std::vector<break_id_t> BreakIDs;
1407     for (size_t i = 0; i < num_breakpoints; ++i)
1408       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1409 
1410     int num_cleared = 0;
1411     StreamString ss;
1412     switch (break_type) {
1413     case eClearTypeFileAndLine: // Breakpoint by source position
1414     {
1415       const ConstString filename(m_options.m_filename.c_str());
1416       BreakpointLocationCollection loc_coll;
1417 
1418       for (size_t i = 0; i < num_breakpoints; ++i) {
1419         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1420 
1421         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1422           // If the collection size is 0, it's a full match and we can just
1423           // remove the breakpoint.
1424           if (loc_coll.GetSize() == 0) {
1425             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1426             ss.EOL();
1427             target->RemoveBreakpointByID(bp->GetID());
1428             ++num_cleared;
1429           }
1430         }
1431       }
1432     } break;
1433 
1434     default:
1435       break;
1436     }
1437 
1438     if (num_cleared > 0) {
1439       Stream &output_stream = result.GetOutputStream();
1440       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1441       output_stream << ss.GetString();
1442       output_stream.EOL();
1443       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1444     } else {
1445       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1446       result.SetStatus(eReturnStatusFailed);
1447     }
1448 
1449     return result.Succeeded();
1450   }
1451 
1452 private:
1453   CommandOptions m_options;
1454 };
1455 
1456 // CommandObjectBreakpointDelete
1457 #define LLDB_OPTIONS_breakpoint_delete
1458 #include "CommandOptions.inc"
1459 
1460 #pragma mark Delete
1461 
1462 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1463 public:
1464   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1465       : CommandObjectParsed(interpreter, "breakpoint delete",
1466                             "Delete the specified breakpoint(s).  If no "
1467                             "breakpoints are specified, delete them all.",
1468                             nullptr),
1469         m_options() {
1470     CommandArgumentEntry arg;
1471     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1472                                       eArgTypeBreakpointIDRange);
1473     // Add the entry for the first argument for this command to the object's
1474     // arguments vector.
1475     m_arguments.push_back(arg);
1476   }
1477 
1478   ~CommandObjectBreakpointDelete() override = default;
1479 
1480   Options *GetOptions() override { return &m_options; }
1481 
1482   class CommandOptions : public Options {
1483   public:
1484     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1485 
1486     ~CommandOptions() override = default;
1487 
1488     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1489                           ExecutionContext *execution_context) override {
1490       Status error;
1491       const int short_option = m_getopt_table[option_idx].val;
1492 
1493       switch (short_option) {
1494       case 'f':
1495         m_force = true;
1496         break;
1497 
1498       case 'D':
1499         m_use_dummy = true;
1500         break;
1501 
1502       default:
1503         error.SetErrorStringWithFormat("unrecognized option '%c'",
1504                                        short_option);
1505         break;
1506       }
1507 
1508       return error;
1509     }
1510 
1511     void OptionParsingStarting(ExecutionContext *execution_context) override {
1512       m_use_dummy = false;
1513       m_force = false;
1514     }
1515 
1516     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1517       return llvm::makeArrayRef(g_breakpoint_delete_options);
1518     }
1519 
1520     // Instance variables to hold the values for command options.
1521     bool m_use_dummy;
1522     bool m_force;
1523   };
1524 
1525 protected:
1526   bool DoExecute(Args &command, CommandReturnObject &result) override {
1527     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1528 
1529     if (target == nullptr) {
1530       result.AppendError("Invalid target. No existing target or breakpoints.");
1531       result.SetStatus(eReturnStatusFailed);
1532       return false;
1533     }
1534 
1535     std::unique_lock<std::recursive_mutex> lock;
1536     target->GetBreakpointList().GetListMutex(lock);
1537 
1538     const BreakpointList &breakpoints = target->GetBreakpointList();
1539 
1540     size_t num_breakpoints = breakpoints.GetSize();
1541 
1542     if (num_breakpoints == 0) {
1543       result.AppendError("No breakpoints exist to be deleted.");
1544       result.SetStatus(eReturnStatusFailed);
1545       return false;
1546     }
1547 
1548     if (command.empty()) {
1549       if (!m_options.m_force &&
1550           !m_interpreter.Confirm(
1551               "About to delete all breakpoints, do you want to do that?",
1552               true)) {
1553         result.AppendMessage("Operation cancelled...");
1554       } else {
1555         target->RemoveAllowedBreakpoints();
1556         result.AppendMessageWithFormat(
1557             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1558             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1559       }
1560       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1561     } else {
1562       // Particular breakpoint selected; disable that breakpoint.
1563       BreakpointIDList valid_bp_ids;
1564       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1565           command, target, result, &valid_bp_ids,
1566           BreakpointName::Permissions::PermissionKinds::deletePerm);
1567 
1568       if (result.Succeeded()) {
1569         int delete_count = 0;
1570         int disable_count = 0;
1571         const size_t count = valid_bp_ids.GetSize();
1572         for (size_t i = 0; i < count; ++i) {
1573           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1574 
1575           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1576             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1577               Breakpoint *breakpoint =
1578                   target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1579               BreakpointLocation *location =
1580                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1581               // It makes no sense to try to delete individual locations, so we
1582               // disable them instead.
1583               if (location) {
1584                 location->SetEnabled(false);
1585                 ++disable_count;
1586               }
1587             } else {
1588               target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1589               ++delete_count;
1590             }
1591           }
1592         }
1593         result.AppendMessageWithFormat(
1594             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1595             delete_count, disable_count);
1596         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1597       }
1598     }
1599     return result.Succeeded();
1600   }
1601 
1602 private:
1603   CommandOptions m_options;
1604 };
1605 
1606 // CommandObjectBreakpointName
1607 #define LLDB_OPTIONS_breakpoint_name
1608 #include "CommandOptions.inc"
1609 
1610 class BreakpointNameOptionGroup : public OptionGroup {
1611 public:
1612   BreakpointNameOptionGroup()
1613       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1614   }
1615 
1616   ~BreakpointNameOptionGroup() override = default;
1617 
1618   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1619     return llvm::makeArrayRef(g_breakpoint_name_options);
1620   }
1621 
1622   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1623                         ExecutionContext *execution_context) override {
1624     Status error;
1625     const int short_option = g_breakpoint_name_options[option_idx].short_option;
1626 
1627     switch (short_option) {
1628     case 'N':
1629       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1630           error.Success())
1631         m_name.SetValueFromString(option_arg);
1632       break;
1633     case 'B':
1634       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1635         error.SetErrorStringWithFormat(
1636             "unrecognized value \"%s\" for breakpoint",
1637             option_arg.str().c_str());
1638       break;
1639     case 'D':
1640       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1641         error.SetErrorStringWithFormat(
1642             "unrecognized value \"%s\" for use-dummy",
1643             option_arg.str().c_str());
1644       break;
1645     case 'H':
1646       m_help_string.SetValueFromString(option_arg);
1647       break;
1648 
1649     default:
1650       error.SetErrorStringWithFormat("unrecognized short option '%c'",
1651                                      short_option);
1652       break;
1653     }
1654     return error;
1655   }
1656 
1657   void OptionParsingStarting(ExecutionContext *execution_context) override {
1658     m_name.Clear();
1659     m_breakpoint.Clear();
1660     m_use_dummy.Clear();
1661     m_use_dummy.SetDefaultValue(false);
1662     m_help_string.Clear();
1663   }
1664 
1665   OptionValueString m_name;
1666   OptionValueUInt64 m_breakpoint;
1667   OptionValueBoolean m_use_dummy;
1668   OptionValueString m_help_string;
1669 };
1670 
1671 #define LLDB_OPTIONS_breakpoint_access
1672 #include "CommandOptions.inc"
1673 
1674 class BreakpointAccessOptionGroup : public OptionGroup {
1675 public:
1676   BreakpointAccessOptionGroup() : OptionGroup() {}
1677 
1678   ~BreakpointAccessOptionGroup() override = default;
1679 
1680   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1681     return llvm::makeArrayRef(g_breakpoint_access_options);
1682   }
1683   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1684                         ExecutionContext *execution_context) override {
1685     Status error;
1686     const int short_option
1687         = g_breakpoint_access_options[option_idx].short_option;
1688 
1689     switch (short_option) {
1690       case 'L': {
1691         bool value, success;
1692         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1693         if (success) {
1694           m_permissions.SetAllowList(value);
1695         } else
1696           error.SetErrorStringWithFormat(
1697               "invalid boolean value '%s' passed for -L option",
1698               option_arg.str().c_str());
1699       } break;
1700       case 'A': {
1701         bool value, success;
1702         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1703         if (success) {
1704           m_permissions.SetAllowDisable(value);
1705         } else
1706           error.SetErrorStringWithFormat(
1707               "invalid boolean value '%s' passed for -L option",
1708               option_arg.str().c_str());
1709       } break;
1710       case 'D': {
1711         bool value, success;
1712         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1713         if (success) {
1714           m_permissions.SetAllowDelete(value);
1715         } else
1716           error.SetErrorStringWithFormat(
1717               "invalid boolean value '%s' passed for -L option",
1718               option_arg.str().c_str());
1719       } break;
1720 
1721     }
1722 
1723     return error;
1724   }
1725 
1726   void OptionParsingStarting(ExecutionContext *execution_context) override {
1727   }
1728 
1729   const BreakpointName::Permissions &GetPermissions() const
1730   {
1731     return m_permissions;
1732   }
1733   BreakpointName::Permissions m_permissions;
1734 };
1735 
1736 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1737 public:
1738   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1739       : CommandObjectParsed(
1740             interpreter, "configure", "Configure the options for the breakpoint"
1741             " name provided.  "
1742             "If you provide a breakpoint id, the options will be copied from "
1743             "the breakpoint, otherwise only the options specified will be set "
1744             "on the name.",
1745             "breakpoint name configure <command-options> "
1746             "<breakpoint-name-list>"),
1747         m_bp_opts(), m_option_group() {
1748     // Create the first variant for the first (and only) argument for this
1749     // command.
1750     CommandArgumentEntry arg1;
1751     CommandArgumentData id_arg;
1752     id_arg.arg_type = eArgTypeBreakpointName;
1753     id_arg.arg_repetition = eArgRepeatOptional;
1754     arg1.push_back(id_arg);
1755     m_arguments.push_back(arg1);
1756 
1757     m_option_group.Append(&m_bp_opts,
1758                           LLDB_OPT_SET_ALL,
1759                           LLDB_OPT_SET_1);
1760     m_option_group.Append(&m_access_options,
1761                           LLDB_OPT_SET_ALL,
1762                           LLDB_OPT_SET_ALL);
1763     m_option_group.Append(&m_bp_id,
1764                           LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1765                           LLDB_OPT_SET_ALL);
1766     m_option_group.Finalize();
1767   }
1768 
1769   ~CommandObjectBreakpointNameConfigure() override = default;
1770 
1771   Options *GetOptions() override { return &m_option_group; }
1772 
1773 protected:
1774   bool DoExecute(Args &command, CommandReturnObject &result) override {
1775 
1776     const size_t argc = command.GetArgumentCount();
1777     if (argc == 0) {
1778       result.AppendError("No names provided.");
1779       result.SetStatus(eReturnStatusFailed);
1780       return false;
1781     }
1782 
1783     Target *target =
1784         GetSelectedOrDummyTarget(false);
1785 
1786     if (target == nullptr) {
1787       result.AppendError("Invalid target. No existing target or breakpoints.");
1788       result.SetStatus(eReturnStatusFailed);
1789       return false;
1790     }
1791 
1792     std::unique_lock<std::recursive_mutex> lock;
1793     target->GetBreakpointList().GetListMutex(lock);
1794 
1795     // Make a pass through first to see that all the names are legal.
1796     for (auto &entry : command.entries()) {
1797       Status error;
1798       if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1799       {
1800         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1801                                      entry.c_str(), error.AsCString());
1802         result.SetStatus(eReturnStatusFailed);
1803         return false;
1804       }
1805     }
1806     // Now configure them, we already pre-checked the names so we don't need to
1807     // check the error:
1808     BreakpointSP bp_sp;
1809     if (m_bp_id.m_breakpoint.OptionWasSet())
1810     {
1811       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1812       bp_sp = target->GetBreakpointByID(bp_id);
1813       if (!bp_sp)
1814       {
1815         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1816                            bp_id);
1817         result.SetStatus(eReturnStatusFailed);
1818         return false;
1819       }
1820     }
1821 
1822     Status error;
1823     for (auto &entry : command.entries()) {
1824       ConstString name(entry.c_str());
1825       BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1826       if (!bp_name)
1827         continue;
1828       if (m_bp_id.m_help_string.OptionWasSet())
1829         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1830 
1831       if (bp_sp)
1832         target->ConfigureBreakpointName(*bp_name,
1833                                        *bp_sp->GetOptions(),
1834                                        m_access_options.GetPermissions());
1835       else
1836         target->ConfigureBreakpointName(*bp_name,
1837                                        m_bp_opts.GetBreakpointOptions(),
1838                                        m_access_options.GetPermissions());
1839     }
1840     return true;
1841   }
1842 
1843 private:
1844   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1845   BreakpointOptionGroup m_bp_opts;
1846   BreakpointAccessOptionGroup m_access_options;
1847   OptionGroupOptions m_option_group;
1848 };
1849 
1850 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1851 public:
1852   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1853       : CommandObjectParsed(
1854             interpreter, "add", "Add a name to the breakpoints provided.",
1855             "breakpoint name add <command-options> <breakpoint-id-list>"),
1856         m_name_options(), m_option_group() {
1857     // Create the first variant for the first (and only) argument for this
1858     // command.
1859     CommandArgumentEntry arg1;
1860     CommandArgumentData id_arg;
1861     id_arg.arg_type = eArgTypeBreakpointID;
1862     id_arg.arg_repetition = eArgRepeatOptional;
1863     arg1.push_back(id_arg);
1864     m_arguments.push_back(arg1);
1865 
1866     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1867     m_option_group.Finalize();
1868   }
1869 
1870   ~CommandObjectBreakpointNameAdd() override = default;
1871 
1872   Options *GetOptions() override { return &m_option_group; }
1873 
1874 protected:
1875   bool DoExecute(Args &command, CommandReturnObject &result) override {
1876     if (!m_name_options.m_name.OptionWasSet()) {
1877       result.SetError("No name option provided.");
1878       return false;
1879     }
1880 
1881     Target *target =
1882         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1883 
1884     if (target == nullptr) {
1885       result.AppendError("Invalid target. No existing target or breakpoints.");
1886       result.SetStatus(eReturnStatusFailed);
1887       return false;
1888     }
1889 
1890     std::unique_lock<std::recursive_mutex> lock;
1891     target->GetBreakpointList().GetListMutex(lock);
1892 
1893     const BreakpointList &breakpoints = target->GetBreakpointList();
1894 
1895     size_t num_breakpoints = breakpoints.GetSize();
1896     if (num_breakpoints == 0) {
1897       result.SetError("No breakpoints, cannot add names.");
1898       result.SetStatus(eReturnStatusFailed);
1899       return false;
1900     }
1901 
1902     // Particular breakpoint selected; disable that breakpoint.
1903     BreakpointIDList valid_bp_ids;
1904     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1905         command, target, result, &valid_bp_ids,
1906         BreakpointName::Permissions::PermissionKinds::listPerm);
1907 
1908     if (result.Succeeded()) {
1909       if (valid_bp_ids.GetSize() == 0) {
1910         result.SetError("No breakpoints specified, cannot add names.");
1911         result.SetStatus(eReturnStatusFailed);
1912         return false;
1913       }
1914       size_t num_valid_ids = valid_bp_ids.GetSize();
1915       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1916       Status error; // This error reports illegal names, but we've already
1917                     // checked that, so we don't need to check it again here.
1918       for (size_t index = 0; index < num_valid_ids; index++) {
1919         lldb::break_id_t bp_id =
1920             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1921         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1922         target->AddNameToBreakpoint(bp_sp, bp_name, error);
1923       }
1924     }
1925 
1926     return true;
1927   }
1928 
1929 private:
1930   BreakpointNameOptionGroup m_name_options;
1931   OptionGroupOptions m_option_group;
1932 };
1933 
1934 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1935 public:
1936   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1937       : CommandObjectParsed(
1938             interpreter, "delete",
1939             "Delete a name from the breakpoints provided.",
1940             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1941         m_name_options(), m_option_group() {
1942     // Create the first variant for the first (and only) argument for this
1943     // command.
1944     CommandArgumentEntry arg1;
1945     CommandArgumentData id_arg;
1946     id_arg.arg_type = eArgTypeBreakpointID;
1947     id_arg.arg_repetition = eArgRepeatOptional;
1948     arg1.push_back(id_arg);
1949     m_arguments.push_back(arg1);
1950 
1951     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1952     m_option_group.Finalize();
1953   }
1954 
1955   ~CommandObjectBreakpointNameDelete() override = default;
1956 
1957   Options *GetOptions() override { return &m_option_group; }
1958 
1959 protected:
1960   bool DoExecute(Args &command, CommandReturnObject &result) override {
1961     if (!m_name_options.m_name.OptionWasSet()) {
1962       result.SetError("No name option provided.");
1963       return false;
1964     }
1965 
1966     Target *target =
1967         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1968 
1969     if (target == nullptr) {
1970       result.AppendError("Invalid target. No existing target or breakpoints.");
1971       result.SetStatus(eReturnStatusFailed);
1972       return false;
1973     }
1974 
1975     std::unique_lock<std::recursive_mutex> lock;
1976     target->GetBreakpointList().GetListMutex(lock);
1977 
1978     const BreakpointList &breakpoints = target->GetBreakpointList();
1979 
1980     size_t num_breakpoints = breakpoints.GetSize();
1981     if (num_breakpoints == 0) {
1982       result.SetError("No breakpoints, cannot delete names.");
1983       result.SetStatus(eReturnStatusFailed);
1984       return false;
1985     }
1986 
1987     // Particular breakpoint selected; disable that breakpoint.
1988     BreakpointIDList valid_bp_ids;
1989     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1990         command, target, result, &valid_bp_ids,
1991         BreakpointName::Permissions::PermissionKinds::deletePerm);
1992 
1993     if (result.Succeeded()) {
1994       if (valid_bp_ids.GetSize() == 0) {
1995         result.SetError("No breakpoints specified, cannot delete names.");
1996         result.SetStatus(eReturnStatusFailed);
1997         return false;
1998       }
1999       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
2000       size_t num_valid_ids = valid_bp_ids.GetSize();
2001       for (size_t index = 0; index < num_valid_ids; index++) {
2002         lldb::break_id_t bp_id =
2003             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2004         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2005         target->RemoveNameFromBreakpoint(bp_sp, bp_name);
2006       }
2007     }
2008 
2009     return true;
2010   }
2011 
2012 private:
2013   BreakpointNameOptionGroup m_name_options;
2014   OptionGroupOptions m_option_group;
2015 };
2016 
2017 class CommandObjectBreakpointNameList : public CommandObjectParsed {
2018 public:
2019   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2020       : CommandObjectParsed(interpreter, "list",
2021                             "List either the names for a breakpoint or info "
2022                             "about a given name.  With no arguments, lists all "
2023                             "names",
2024                             "breakpoint name list <command-options>"),
2025         m_name_options(), m_option_group() {
2026     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
2027     m_option_group.Finalize();
2028   }
2029 
2030   ~CommandObjectBreakpointNameList() override = default;
2031 
2032   Options *GetOptions() override { return &m_option_group; }
2033 
2034 protected:
2035   bool DoExecute(Args &command, CommandReturnObject &result) override {
2036     Target *target =
2037         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2038 
2039     if (target == nullptr) {
2040       result.AppendError("Invalid target. No existing target or breakpoints.");
2041       result.SetStatus(eReturnStatusFailed);
2042       return false;
2043     }
2044 
2045 
2046     std::vector<std::string> name_list;
2047     if (command.empty()) {
2048       target->GetBreakpointNames(name_list);
2049     } else {
2050       for (const Args::ArgEntry &arg : command)
2051       {
2052         name_list.push_back(arg.c_str());
2053       }
2054     }
2055 
2056     if (name_list.empty()) {
2057       result.AppendMessage("No breakpoint names found.");
2058     } else {
2059       for (const std::string &name_str : name_list) {
2060         const char *name = name_str.c_str();
2061         // First print out the options for the name:
2062         Status error;
2063         BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2064                                                              false,
2065                                                              error);
2066         if (bp_name)
2067         {
2068           StreamString s;
2069           result.AppendMessageWithFormat("Name: %s\n", name);
2070           if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2071           {
2072             result.AppendMessage(s.GetString());
2073           }
2074 
2075           std::unique_lock<std::recursive_mutex> lock;
2076           target->GetBreakpointList().GetListMutex(lock);
2077 
2078           BreakpointList &breakpoints = target->GetBreakpointList();
2079           bool any_set = false;
2080           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2081             if (bp_sp->MatchesName(name)) {
2082               StreamString s;
2083               any_set = true;
2084               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2085               s.EOL();
2086               result.AppendMessage(s.GetString());
2087             }
2088           }
2089           if (!any_set)
2090             result.AppendMessage("No breakpoints using this name.");
2091         } else {
2092           result.AppendMessageWithFormat("Name: %s not found.\n", name);
2093         }
2094       }
2095     }
2096     return true;
2097   }
2098 
2099 private:
2100   BreakpointNameOptionGroup m_name_options;
2101   OptionGroupOptions m_option_group;
2102 };
2103 
2104 // CommandObjectBreakpointName
2105 class CommandObjectBreakpointName : public CommandObjectMultiword {
2106 public:
2107   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2108       : CommandObjectMultiword(
2109             interpreter, "name", "Commands to manage name tags for breakpoints",
2110             "breakpoint name <subcommand> [<command-options>]") {
2111     CommandObjectSP add_command_object(
2112         new CommandObjectBreakpointNameAdd(interpreter));
2113     CommandObjectSP delete_command_object(
2114         new CommandObjectBreakpointNameDelete(interpreter));
2115     CommandObjectSP list_command_object(
2116         new CommandObjectBreakpointNameList(interpreter));
2117     CommandObjectSP configure_command_object(
2118         new CommandObjectBreakpointNameConfigure(interpreter));
2119 
2120     LoadSubCommand("add", add_command_object);
2121     LoadSubCommand("delete", delete_command_object);
2122     LoadSubCommand("list", list_command_object);
2123     LoadSubCommand("configure", configure_command_object);
2124   }
2125 
2126   ~CommandObjectBreakpointName() override = default;
2127 };
2128 
2129 // CommandObjectBreakpointRead
2130 #pragma mark Read::CommandOptions
2131 #define LLDB_OPTIONS_breakpoint_read
2132 #include "CommandOptions.inc"
2133 
2134 #pragma mark Read
2135 
2136 class CommandObjectBreakpointRead : public CommandObjectParsed {
2137 public:
2138   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2139       : CommandObjectParsed(interpreter, "breakpoint read",
2140                             "Read and set the breakpoints previously saved to "
2141                             "a file with \"breakpoint write\".  ",
2142                             nullptr),
2143         m_options() {
2144     CommandArgumentEntry arg;
2145     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2146                                       eArgTypeBreakpointIDRange);
2147     // Add the entry for the first argument for this command to the object's
2148     // arguments vector.
2149     m_arguments.push_back(arg);
2150   }
2151 
2152   ~CommandObjectBreakpointRead() override = default;
2153 
2154   Options *GetOptions() override { return &m_options; }
2155 
2156   class CommandOptions : public Options {
2157   public:
2158     CommandOptions() : Options() {}
2159 
2160     ~CommandOptions() override = default;
2161 
2162     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2163                           ExecutionContext *execution_context) override {
2164       Status error;
2165       const int short_option = m_getopt_table[option_idx].val;
2166 
2167       switch (short_option) {
2168       case 'f':
2169         m_filename.assign(option_arg);
2170         break;
2171       case 'N': {
2172         Status name_error;
2173         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2174                                                   name_error)) {
2175           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2176                                          name_error.AsCString());
2177         }
2178         m_names.push_back(option_arg);
2179         break;
2180       }
2181       default:
2182         error.SetErrorStringWithFormat("unrecognized option '%c'",
2183                                        short_option);
2184         break;
2185       }
2186 
2187       return error;
2188     }
2189 
2190     void OptionParsingStarting(ExecutionContext *execution_context) override {
2191       m_filename.clear();
2192       m_names.clear();
2193     }
2194 
2195     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2196       return llvm::makeArrayRef(g_breakpoint_read_options);
2197     }
2198 
2199     // Instance variables to hold the values for command options.
2200 
2201     std::string m_filename;
2202     std::vector<std::string> m_names;
2203   };
2204 
2205 protected:
2206   bool DoExecute(Args &command, CommandReturnObject &result) override {
2207     Target *target = GetSelectedOrDummyTarget();
2208     if (target == nullptr) {
2209       result.AppendError("Invalid target.  No existing target or breakpoints.");
2210       result.SetStatus(eReturnStatusFailed);
2211       return false;
2212     }
2213 
2214     std::unique_lock<std::recursive_mutex> lock;
2215     target->GetBreakpointList().GetListMutex(lock);
2216 
2217     FileSpec input_spec(m_options.m_filename);
2218     FileSystem::Instance().Resolve(input_spec);
2219     BreakpointIDList new_bps;
2220     Status error = target->CreateBreakpointsFromFile(
2221         input_spec, m_options.m_names, new_bps);
2222 
2223     if (!error.Success()) {
2224       result.AppendError(error.AsCString());
2225       result.SetStatus(eReturnStatusFailed);
2226       return false;
2227     }
2228 
2229     Stream &output_stream = result.GetOutputStream();
2230 
2231     size_t num_breakpoints = new_bps.GetSize();
2232     if (num_breakpoints == 0) {
2233       result.AppendMessage("No breakpoints added.");
2234     } else {
2235       // No breakpoint selected; show info about all currently set breakpoints.
2236       result.AppendMessage("New breakpoints:");
2237       for (size_t i = 0; i < num_breakpoints; ++i) {
2238         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2239         Breakpoint *bp = target->GetBreakpointList()
2240                              .FindBreakpointByID(bp_id.GetBreakpointID())
2241                              .get();
2242         if (bp)
2243           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2244                              false);
2245       }
2246     }
2247     return result.Succeeded();
2248   }
2249 
2250 private:
2251   CommandOptions m_options;
2252 };
2253 
2254 // CommandObjectBreakpointWrite
2255 #pragma mark Write::CommandOptions
2256 #define LLDB_OPTIONS_breakpoint_write
2257 #include "CommandOptions.inc"
2258 
2259 #pragma mark Write
2260 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2261 public:
2262   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2263       : CommandObjectParsed(interpreter, "breakpoint write",
2264                             "Write the breakpoints listed to a file that can "
2265                             "be read in with \"breakpoint read\".  "
2266                             "If given no arguments, writes all breakpoints.",
2267                             nullptr),
2268         m_options() {
2269     CommandArgumentEntry arg;
2270     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2271                                       eArgTypeBreakpointIDRange);
2272     // Add the entry for the first argument for this command to the object's
2273     // arguments vector.
2274     m_arguments.push_back(arg);
2275   }
2276 
2277   ~CommandObjectBreakpointWrite() override = default;
2278 
2279   Options *GetOptions() override { return &m_options; }
2280 
2281   class CommandOptions : public Options {
2282   public:
2283     CommandOptions() : Options() {}
2284 
2285     ~CommandOptions() override = default;
2286 
2287     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2288                           ExecutionContext *execution_context) override {
2289       Status error;
2290       const int short_option = m_getopt_table[option_idx].val;
2291 
2292       switch (short_option) {
2293       case 'f':
2294         m_filename.assign(option_arg);
2295         break;
2296       case 'a':
2297         m_append = true;
2298         break;
2299       default:
2300         error.SetErrorStringWithFormat("unrecognized option '%c'",
2301                                        short_option);
2302         break;
2303       }
2304 
2305       return error;
2306     }
2307 
2308     void OptionParsingStarting(ExecutionContext *execution_context) override {
2309       m_filename.clear();
2310       m_append = false;
2311     }
2312 
2313     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2314       return llvm::makeArrayRef(g_breakpoint_write_options);
2315     }
2316 
2317     // Instance variables to hold the values for command options.
2318 
2319     std::string m_filename;
2320     bool m_append = false;
2321   };
2322 
2323 protected:
2324   bool DoExecute(Args &command, CommandReturnObject &result) override {
2325     Target *target = GetSelectedOrDummyTarget();
2326     if (target == nullptr) {
2327       result.AppendError("Invalid target.  No existing target or breakpoints.");
2328       result.SetStatus(eReturnStatusFailed);
2329       return false;
2330     }
2331 
2332     std::unique_lock<std::recursive_mutex> lock;
2333     target->GetBreakpointList().GetListMutex(lock);
2334 
2335     BreakpointIDList valid_bp_ids;
2336     if (!command.empty()) {
2337       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2338           command, target, result, &valid_bp_ids,
2339           BreakpointName::Permissions::PermissionKinds::listPerm);
2340 
2341       if (!result.Succeeded()) {
2342         result.SetStatus(eReturnStatusFailed);
2343         return false;
2344       }
2345     }
2346     FileSpec file_spec(m_options.m_filename);
2347     FileSystem::Instance().Resolve(file_spec);
2348     Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2349                                                       m_options.m_append);
2350     if (!error.Success()) {
2351       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2352                                    error.AsCString());
2353       result.SetStatus(eReturnStatusFailed);
2354     }
2355     return result.Succeeded();
2356   }
2357 
2358 private:
2359   CommandOptions m_options;
2360 };
2361 
2362 // CommandObjectMultiwordBreakpoint
2363 #pragma mark MultiwordBreakpoint
2364 
2365 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2366     CommandInterpreter &interpreter)
2367     : CommandObjectMultiword(
2368           interpreter, "breakpoint",
2369           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2370           "breakpoint <subcommand> [<command-options>]") {
2371   CommandObjectSP list_command_object(
2372       new CommandObjectBreakpointList(interpreter));
2373   CommandObjectSP enable_command_object(
2374       new CommandObjectBreakpointEnable(interpreter));
2375   CommandObjectSP disable_command_object(
2376       new CommandObjectBreakpointDisable(interpreter));
2377   CommandObjectSP clear_command_object(
2378       new CommandObjectBreakpointClear(interpreter));
2379   CommandObjectSP delete_command_object(
2380       new CommandObjectBreakpointDelete(interpreter));
2381   CommandObjectSP set_command_object(
2382       new CommandObjectBreakpointSet(interpreter));
2383   CommandObjectSP command_command_object(
2384       new CommandObjectBreakpointCommand(interpreter));
2385   CommandObjectSP modify_command_object(
2386       new CommandObjectBreakpointModify(interpreter));
2387   CommandObjectSP name_command_object(
2388       new CommandObjectBreakpointName(interpreter));
2389   CommandObjectSP write_command_object(
2390       new CommandObjectBreakpointWrite(interpreter));
2391   CommandObjectSP read_command_object(
2392       new CommandObjectBreakpointRead(interpreter));
2393 
2394   list_command_object->SetCommandName("breakpoint list");
2395   enable_command_object->SetCommandName("breakpoint enable");
2396   disable_command_object->SetCommandName("breakpoint disable");
2397   clear_command_object->SetCommandName("breakpoint clear");
2398   delete_command_object->SetCommandName("breakpoint delete");
2399   set_command_object->SetCommandName("breakpoint set");
2400   command_command_object->SetCommandName("breakpoint command");
2401   modify_command_object->SetCommandName("breakpoint modify");
2402   name_command_object->SetCommandName("breakpoint name");
2403   write_command_object->SetCommandName("breakpoint write");
2404   read_command_object->SetCommandName("breakpoint read");
2405 
2406   LoadSubCommand("list", list_command_object);
2407   LoadSubCommand("enable", enable_command_object);
2408   LoadSubCommand("disable", disable_command_object);
2409   LoadSubCommand("clear", clear_command_object);
2410   LoadSubCommand("delete", delete_command_object);
2411   LoadSubCommand("set", set_command_object);
2412   LoadSubCommand("command", command_command_object);
2413   LoadSubCommand("modify", modify_command_object);
2414   LoadSubCommand("name", name_command_object);
2415   LoadSubCommand("write", write_command_object);
2416   LoadSubCommand("read", read_command_object);
2417 }
2418 
2419 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2420 
2421 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2422                                                  bool allow_locations,
2423                                                  CommandReturnObject &result,
2424                                                  BreakpointIDList *valid_ids,
2425                                                  BreakpointName::Permissions
2426                                                      ::PermissionKinds
2427                                                      purpose) {
2428   // args can be strings representing 1). integers (for breakpoint ids)
2429   //                                  2). the full breakpoint & location
2430   //                                  canonical representation
2431   //                                  3). the word "to" or a hyphen,
2432   //                                  representing a range (in which case there
2433   //                                      had *better* be an entry both before &
2434   //                                      after of one of the first two types.
2435   //                                  4). A breakpoint name
2436   // If args is empty, we will use the last created breakpoint (if there is
2437   // one.)
2438 
2439   Args temp_args;
2440 
2441   if (args.empty()) {
2442     if (target->GetLastCreatedBreakpoint()) {
2443       valid_ids->AddBreakpointID(BreakpointID(
2444           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2445       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2446     } else {
2447       result.AppendError(
2448           "No breakpoint specified and no last created breakpoint.");
2449       result.SetStatus(eReturnStatusFailed);
2450     }
2451     return;
2452   }
2453 
2454   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2455   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
2456   // id range strings over; instead generate a list of strings for all the
2457   // breakpoint ids in the range, and shove all of those breakpoint id strings
2458   // into TEMP_ARGS.
2459 
2460   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2461                                            purpose, result, temp_args);
2462 
2463   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2464   // BreakpointIDList:
2465 
2466   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2467 
2468   // At this point,  all of the breakpoint ids that the user passed in have
2469   // been converted to breakpoint IDs and put into valid_ids.
2470 
2471   if (result.Succeeded()) {
2472     // Now that we've converted everything from args into a list of breakpoint
2473     // ids, go through our tentative list of breakpoint id's and verify that
2474     // they correspond to valid/currently set breakpoints.
2475 
2476     const size_t count = valid_ids->GetSize();
2477     for (size_t i = 0; i < count; ++i) {
2478       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2479       Breakpoint *breakpoint =
2480           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2481       if (breakpoint != nullptr) {
2482         const size_t num_locations = breakpoint->GetNumLocations();
2483         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2484           StreamString id_str;
2485           BreakpointID::GetCanonicalReference(
2486               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2487           i = valid_ids->GetSize() + 1;
2488           result.AppendErrorWithFormat(
2489               "'%s' is not a currently valid breakpoint/location id.\n",
2490               id_str.GetData());
2491           result.SetStatus(eReturnStatusFailed);
2492         }
2493       } else {
2494         i = valid_ids->GetSize() + 1;
2495         result.AppendErrorWithFormat(
2496             "'%d' is not a currently valid breakpoint ID.\n",
2497             cur_bp_id.GetBreakpointID());
2498         result.SetStatus(eReturnStatusFailed);
2499       }
2500     }
2501   }
2502 }
2503