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