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