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