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