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