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