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