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