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