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