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