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