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