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