1254721Semaste//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9309124Sdim#include "CommandObjectBreakpoint.h"
10309124Sdim#include "CommandObjectBreakpointCommand.h"
11254721Semaste#include "lldb/Breakpoint/Breakpoint.h"
12254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h"
13254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h"
14321369Sdim#include "lldb/Host/OptionParser.h"
15314564Sdim#include "lldb/Interpreter/CommandInterpreter.h"
16314564Sdim#include "lldb/Interpreter/CommandReturnObject.h"
17341825Sdim#include "lldb/Interpreter/OptionArgParser.h"
18360784Sdim#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
19288943Sdim#include "lldb/Interpreter/OptionValueBoolean.h"
20280031Sdim#include "lldb/Interpreter/OptionValueString.h"
21280031Sdim#include "lldb/Interpreter/OptionValueUInt64.h"
22314564Sdim#include "lldb/Interpreter/Options.h"
23296417Sdim#include "lldb/Target/Language.h"
24314564Sdim#include "lldb/Target/StackFrame.h"
25254721Semaste#include "lldb/Target/Target.h"
26254721Semaste#include "lldb/Target/ThreadSpec.h"
27321369Sdim#include "lldb/Utility/RegularExpression.h"
28321369Sdim#include "lldb/Utility/StreamString.h"
29254721Semaste
30353358Sdim#include <memory>
31353358Sdim#include <vector>
32353358Sdim
33254721Semasteusing namespace lldb;
34254721Semasteusing namespace lldb_private;
35254721Semaste
36314564Sdimstatic void AddBreakpointDescription(Stream *s, Breakpoint *bp,
37314564Sdim                                     lldb::DescriptionLevel level) {
38314564Sdim  s->IndentMore();
39314564Sdim  bp->GetDescription(s, level, true);
40314564Sdim  s->IndentLess();
41314564Sdim  s->EOL();
42254721Semaste}
43254721Semaste
44327952Sdim// Modifiable Breakpoint Options
45327952Sdim#pragma mark Modify::CommandOptions
46360784Sdim#define LLDB_OPTIONS_breakpoint_modify
47360784Sdim#include "CommandOptions.inc"
48360784Sdim
49360784Sdimclass lldb_private::BreakpointOptionGroup : public OptionGroup {
50327952Sdimpublic:
51360784Sdim  BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
52360784Sdim
53327952Sdim  ~BreakpointOptionGroup() override = default;
54327952Sdim
55327952Sdim  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
56327952Sdim    return llvm::makeArrayRef(g_breakpoint_modify_options);
57327952Sdim  }
58327952Sdim
59327952Sdim  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
60360784Sdim                        ExecutionContext *execution_context) override {
61327952Sdim    Status error;
62360784Sdim    const int short_option =
63360784Sdim        g_breakpoint_modify_options[option_idx].short_option;
64327952Sdim
65327952Sdim    switch (short_option) {
66327952Sdim    case 'c':
67341825Sdim      // Normally an empty breakpoint condition marks is as unset. But we need
68341825Sdim      // to say it was passed in.
69327952Sdim      m_bp_opts.SetCondition(option_arg.str().c_str());
70327952Sdim      m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
71327952Sdim      break;
72327952Sdim    case 'C':
73327952Sdim      m_commands.push_back(option_arg);
74327952Sdim      break;
75327952Sdim    case 'd':
76327952Sdim      m_bp_opts.SetEnabled(false);
77327952Sdim      break;
78327952Sdim    case 'e':
79327952Sdim      m_bp_opts.SetEnabled(true);
80327952Sdim      break;
81327952Sdim    case 'G': {
82327952Sdim      bool value, success;
83341825Sdim      value = OptionArgParser::ToBoolean(option_arg, false, &success);
84327952Sdim      if (success) {
85327952Sdim        m_bp_opts.SetAutoContinue(value);
86327952Sdim      } else
87327952Sdim        error.SetErrorStringWithFormat(
88327952Sdim            "invalid boolean value '%s' passed for -G option",
89327952Sdim            option_arg.str().c_str());
90360784Sdim    } break;
91360784Sdim    case 'i': {
92327952Sdim      uint32_t ignore_count;
93327952Sdim      if (option_arg.getAsInteger(0, ignore_count))
94327952Sdim        error.SetErrorStringWithFormat("invalid ignore count '%s'",
95327952Sdim                                       option_arg.str().c_str());
96327952Sdim      else
97327952Sdim        m_bp_opts.SetIgnoreCount(ignore_count);
98360784Sdim    } break;
99327952Sdim    case 'o': {
100327952Sdim      bool value, success;
101341825Sdim      value = OptionArgParser::ToBoolean(option_arg, false, &success);
102327952Sdim      if (success) {
103327952Sdim        m_bp_opts.SetOneShot(value);
104327952Sdim      } else
105327952Sdim        error.SetErrorStringWithFormat(
106327952Sdim            "invalid boolean value '%s' passed for -o option",
107327952Sdim            option_arg.str().c_str());
108327952Sdim    } break;
109360784Sdim    case 't': {
110327952Sdim      lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
111327952Sdim      if (option_arg[0] != '\0') {
112327952Sdim        if (option_arg.getAsInteger(0, thread_id))
113327952Sdim          error.SetErrorStringWithFormat("invalid thread id string '%s'",
114327952Sdim                                         option_arg.str().c_str());
115327952Sdim      }
116327952Sdim      m_bp_opts.SetThreadID(thread_id);
117360784Sdim    } break;
118327952Sdim    case 'T':
119327952Sdim      m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
120327952Sdim      break;
121327952Sdim    case 'q':
122327952Sdim      m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
123327952Sdim      break;
124360784Sdim    case 'x': {
125327952Sdim      uint32_t thread_index = UINT32_MAX;
126327952Sdim      if (option_arg[0] != '\n') {
127327952Sdim        if (option_arg.getAsInteger(0, thread_index))
128327952Sdim          error.SetErrorStringWithFormat("invalid thread index string '%s'",
129327952Sdim                                         option_arg.str().c_str());
130327952Sdim      }
131327952Sdim      m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
132360784Sdim    } break;
133327952Sdim    default:
134360784Sdim      llvm_unreachable("Unimplemented option");
135327952Sdim    }
136327952Sdim
137327952Sdim    return error;
138327952Sdim  }
139327952Sdim
140327952Sdim  void OptionParsingStarting(ExecutionContext *execution_context) override {
141327952Sdim    m_bp_opts.Clear();
142327952Sdim    m_commands.clear();
143327952Sdim  }
144360784Sdim
145327952Sdim  Status OptionParsingFinished(ExecutionContext *execution_context) override {
146360784Sdim    if (!m_commands.empty()) {
147360784Sdim      auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
148327952Sdim
149360784Sdim      for (std::string &str : m_commands)
150360784Sdim        cmd_data->user_source.AppendString(str);
151360784Sdim
152360784Sdim      cmd_data->stop_on_error = true;
153360784Sdim      m_bp_opts.SetCommandDataCallback(cmd_data);
154327952Sdim    }
155327952Sdim    return Status();
156327952Sdim  }
157327952Sdim
158360784Sdim  const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
159360784Sdim
160327952Sdim  std::vector<std::string> m_commands;
161327952Sdim  BreakpointOptions m_bp_opts;
162327952Sdim};
163327952Sdim
164360784Sdim#define LLDB_OPTIONS_breakpoint_dummy
165360784Sdim#include "CommandOptions.inc"
166360784Sdim
167360784Sdimclass BreakpointDummyOptionGroup : public OptionGroup {
168327952Sdimpublic:
169360784Sdim  BreakpointDummyOptionGroup() : OptionGroup() {}
170360784Sdim
171327952Sdim  ~BreakpointDummyOptionGroup() override = default;
172327952Sdim
173327952Sdim  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
174327952Sdim    return llvm::makeArrayRef(g_breakpoint_dummy_options);
175327952Sdim  }
176327952Sdim
177327952Sdim  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
178360784Sdim                        ExecutionContext *execution_context) override {
179327952Sdim    Status error;
180360784Sdim    const int short_option =
181360784Sdim        g_breakpoint_dummy_options[option_idx].short_option;
182327952Sdim
183327952Sdim    switch (short_option) {
184360784Sdim    case 'D':
185360784Sdim      m_use_dummy = true;
186360784Sdim      break;
187327952Sdim    default:
188360784Sdim      llvm_unreachable("Unimplemented option");
189327952Sdim    }
190327952Sdim
191327952Sdim    return error;
192327952Sdim  }
193327952Sdim
194327952Sdim  void OptionParsingStarting(ExecutionContext *execution_context) override {
195327952Sdim    m_use_dummy = false;
196327952Sdim  }
197327952Sdim
198327952Sdim  bool m_use_dummy;
199327952Sdim};
200327952Sdim
201360784Sdim#define LLDB_OPTIONS_breakpoint_set
202360784Sdim#include "CommandOptions.inc"
203314564Sdim
204254721Semaste// CommandObjectBreakpointSet
205254721Semaste
206314564Sdimclass CommandObjectBreakpointSet : public CommandObjectParsed {
207254721Semastepublic:
208353358Sdim  enum BreakpointSetType {
209314564Sdim    eSetTypeInvalid,
210314564Sdim    eSetTypeFileAndLine,
211314564Sdim    eSetTypeAddress,
212314564Sdim    eSetTypeFunctionName,
213314564Sdim    eSetTypeFunctionRegexp,
214314564Sdim    eSetTypeSourceRegexp,
215344779Sdim    eSetTypeException,
216344779Sdim    eSetTypeScripted,
217353358Sdim  };
218254721Semaste
219314564Sdim  CommandObjectBreakpointSet(CommandInterpreter &interpreter)
220314564Sdim      : CommandObjectParsed(
221314564Sdim            interpreter, "breakpoint set",
222314564Sdim            "Sets a breakpoint or set of breakpoints in the executable.",
223314564Sdim            "breakpoint set <cmd-options>"),
224360784Sdim        m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
225360784Sdim        m_options() {
226360784Sdim    // We're picking up all the normal options, commands and disable.
227360784Sdim    m_all_options.Append(&m_python_class_options,
228360784Sdim                         LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
229360784Sdim    m_all_options.Append(&m_bp_opts,
230360784Sdim                         LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
231360784Sdim                         LLDB_OPT_SET_ALL);
232360784Sdim    m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
233360784Sdim    m_all_options.Append(&m_options);
234360784Sdim    m_all_options.Finalize();
235360784Sdim  }
236254721Semaste
237314564Sdim  ~CommandObjectBreakpointSet() override = default;
238254721Semaste
239327952Sdim  Options *GetOptions() override { return &m_all_options; }
240254721Semaste
241327952Sdim  class CommandOptions : public OptionGroup {
242314564Sdim  public:
243314564Sdim    CommandOptions()
244360784Sdim        : OptionGroup(), m_condition(), m_filenames(), m_line_num(0),
245360784Sdim          m_column(0), m_func_names(),
246360784Sdim          m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(),
247360784Sdim          m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false),
248360784Sdim          m_throw_bp(true), m_hardware(false),
249314564Sdim          m_exception_language(eLanguageTypeUnknown),
250314564Sdim          m_language(lldb::eLanguageTypeUnknown),
251360784Sdim          m_skip_prologue(eLazyBoolCalculate), m_all_files(false),
252360784Sdim          m_move_to_nearest_code(eLazyBoolCalculate) {}
253254721Semaste
254314564Sdim    ~CommandOptions() override = default;
255254721Semaste
256321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
257321369Sdim                          ExecutionContext *execution_context) override {
258321369Sdim      Status error;
259360784Sdim      const int short_option =
260360784Sdim          g_breakpoint_set_options[option_idx].short_option;
261254721Semaste
262314564Sdim      switch (short_option) {
263314564Sdim      case 'a': {
264341825Sdim        m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
265341825Sdim                                                 LLDB_INVALID_ADDRESS, &error);
266314564Sdim      } break;
267254721Semaste
268314564Sdim      case 'A':
269314564Sdim        m_all_files = true;
270314564Sdim        break;
271288943Sdim
272314564Sdim      case 'b':
273314564Sdim        m_func_names.push_back(option_arg);
274314564Sdim        m_func_name_type_mask |= eFunctionNameTypeBase;
275314564Sdim        break;
276254721Semaste
277314564Sdim      case 'C':
278314564Sdim        if (option_arg.getAsInteger(0, m_column))
279314564Sdim          error.SetErrorStringWithFormat("invalid column number: %s",
280314564Sdim                                         option_arg.str().c_str());
281314564Sdim        break;
282309124Sdim
283314564Sdim      case 'E': {
284314564Sdim        LanguageType language = Language::GetLanguageTypeFromString(option_arg);
285254721Semaste
286314564Sdim        switch (language) {
287314564Sdim        case eLanguageTypeC89:
288314564Sdim        case eLanguageTypeC:
289314564Sdim        case eLanguageTypeC99:
290314564Sdim        case eLanguageTypeC11:
291314564Sdim          m_exception_language = eLanguageTypeC;
292314564Sdim          break;
293314564Sdim        case eLanguageTypeC_plus_plus:
294314564Sdim        case eLanguageTypeC_plus_plus_03:
295314564Sdim        case eLanguageTypeC_plus_plus_11:
296314564Sdim        case eLanguageTypeC_plus_plus_14:
297314564Sdim          m_exception_language = eLanguageTypeC_plus_plus;
298314564Sdim          break;
299314564Sdim        case eLanguageTypeObjC:
300314564Sdim          m_exception_language = eLanguageTypeObjC;
301314564Sdim          break;
302314564Sdim        case eLanguageTypeObjC_plus_plus:
303314564Sdim          error.SetErrorStringWithFormat(
304314564Sdim              "Set exception breakpoints separately for c++ and objective-c");
305314564Sdim          break;
306314564Sdim        case eLanguageTypeUnknown:
307314564Sdim          error.SetErrorStringWithFormat(
308314564Sdim              "Unknown language type: '%s' for exception breakpoint",
309314564Sdim              option_arg.str().c_str());
310314564Sdim          break;
311314564Sdim        default:
312314564Sdim          error.SetErrorStringWithFormat(
313314564Sdim              "Unsupported language type: '%s' for exception breakpoint",
314314564Sdim              option_arg.str().c_str());
315314564Sdim        }
316314564Sdim      } break;
317254721Semaste
318314564Sdim      case 'f':
319344779Sdim        m_filenames.AppendIfUnique(FileSpec(option_arg));
320314564Sdim        break;
321254721Semaste
322314564Sdim      case 'F':
323314564Sdim        m_func_names.push_back(option_arg);
324314564Sdim        m_func_name_type_mask |= eFunctionNameTypeFull;
325314564Sdim        break;
326360784Sdim
327314564Sdim      case 'h': {
328314564Sdim        bool success;
329341825Sdim        m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
330314564Sdim        if (!success)
331314564Sdim          error.SetErrorStringWithFormat(
332314564Sdim              "Invalid boolean value for on-catch option: '%s'",
333314564Sdim              option_arg.str().c_str());
334314564Sdim      } break;
335258054Semaste
336314564Sdim      case 'H':
337314564Sdim        m_hardware = true;
338314564Sdim        break;
339360784Sdim
340314564Sdim      case 'K': {
341314564Sdim        bool success;
342314564Sdim        bool value;
343341825Sdim        value = OptionArgParser::ToBoolean(option_arg, true, &success);
344314564Sdim        if (value)
345314564Sdim          m_skip_prologue = eLazyBoolYes;
346314564Sdim        else
347314564Sdim          m_skip_prologue = eLazyBoolNo;
348254721Semaste
349314564Sdim        if (!success)
350314564Sdim          error.SetErrorStringWithFormat(
351314564Sdim              "Invalid boolean value for skip prologue option: '%s'",
352314564Sdim              option_arg.str().c_str());
353314564Sdim      } break;
354254721Semaste
355314564Sdim      case 'l':
356314564Sdim        if (option_arg.getAsInteger(0, m_line_num))
357314564Sdim          error.SetErrorStringWithFormat("invalid line number: %s.",
358314564Sdim                                         option_arg.str().c_str());
359314564Sdim        break;
360296417Sdim
361314564Sdim      case 'L':
362314564Sdim        m_language = Language::GetLanguageTypeFromString(option_arg);
363314564Sdim        if (m_language == eLanguageTypeUnknown)
364314564Sdim          error.SetErrorStringWithFormat(
365314564Sdim              "Unknown language type: '%s' for breakpoint",
366314564Sdim              option_arg.str().c_str());
367314564Sdim        break;
368288943Sdim
369314564Sdim      case 'm': {
370314564Sdim        bool success;
371314564Sdim        bool value;
372341825Sdim        value = OptionArgParser::ToBoolean(option_arg, true, &success);
373314564Sdim        if (value)
374314564Sdim          m_move_to_nearest_code = eLazyBoolYes;
375314564Sdim        else
376314564Sdim          m_move_to_nearest_code = eLazyBoolNo;
377254721Semaste
378314564Sdim        if (!success)
379314564Sdim          error.SetErrorStringWithFormat(
380314564Sdim              "Invalid boolean value for move-to-nearest-code option: '%s'",
381314564Sdim              option_arg.str().c_str());
382314564Sdim        break;
383314564Sdim      }
384254721Semaste
385314564Sdim      case 'M':
386314564Sdim        m_func_names.push_back(option_arg);
387314564Sdim        m_func_name_type_mask |= eFunctionNameTypeMethod;
388314564Sdim        break;
389280031Sdim
390314564Sdim      case 'n':
391314564Sdim        m_func_names.push_back(option_arg);
392314564Sdim        m_func_name_type_mask |= eFunctionNameTypeAuto;
393314564Sdim        break;
394309124Sdim
395314564Sdim      case 'N': {
396314564Sdim        if (BreakpointID::StringIsBreakpointName(option_arg, error))
397314564Sdim          m_breakpoint_names.push_back(option_arg);
398314564Sdim        else
399314564Sdim          error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
400314564Sdim                                         option_arg.str().c_str());
401314564Sdim        break;
402314564Sdim      }
403254721Semaste
404314564Sdim      case 'R': {
405314564Sdim        lldb::addr_t tmp_offset_addr;
406341825Sdim        tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
407341825Sdim                                                     option_arg, 0, &error);
408314564Sdim        if (error.Success())
409314564Sdim          m_offset_addr = tmp_offset_addr;
410314564Sdim      } break;
411288943Sdim
412314564Sdim      case 'O':
413314564Sdim        m_exception_extra_args.AppendArgument("-O");
414314564Sdim        m_exception_extra_args.AppendArgument(option_arg);
415314564Sdim        break;
416254721Semaste
417314564Sdim      case 'p':
418314564Sdim        m_source_text_regexp.assign(option_arg);
419314564Sdim        break;
420254721Semaste
421314564Sdim      case 'r':
422314564Sdim        m_func_regexp.assign(option_arg);
423314564Sdim        break;
424254721Semaste
425314564Sdim      case 's':
426344779Sdim        m_modules.AppendIfUnique(FileSpec(option_arg));
427314564Sdim        break;
428254721Semaste
429314564Sdim      case 'S':
430314564Sdim        m_func_names.push_back(option_arg);
431314564Sdim        m_func_name_type_mask |= eFunctionNameTypeSelector;
432314564Sdim        break;
433309124Sdim
434314564Sdim      case 'w': {
435314564Sdim        bool success;
436341825Sdim        m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
437314564Sdim        if (!success)
438314564Sdim          error.SetErrorStringWithFormat(
439314564Sdim              "Invalid boolean value for on-throw option: '%s'",
440314564Sdim              option_arg.str().c_str());
441314564Sdim      } break;
442254721Semaste
443314564Sdim      case 'X':
444314564Sdim        m_source_regex_func_names.insert(option_arg);
445314564Sdim        break;
446254721Semaste
447314564Sdim      default:
448360784Sdim        llvm_unreachable("Unimplemented option");
449314564Sdim      }
450254721Semaste
451314564Sdim      return error;
452314564Sdim    }
453254721Semaste
454314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
455314564Sdim      m_filenames.Clear();
456314564Sdim      m_line_num = 0;
457314564Sdim      m_column = 0;
458314564Sdim      m_func_names.clear();
459314564Sdim      m_func_name_type_mask = eFunctionNameTypeNone;
460314564Sdim      m_func_regexp.clear();
461314564Sdim      m_source_text_regexp.clear();
462314564Sdim      m_modules.Clear();
463314564Sdim      m_load_addr = LLDB_INVALID_ADDRESS;
464314564Sdim      m_offset_addr = 0;
465314564Sdim      m_catch_bp = false;
466314564Sdim      m_throw_bp = true;
467314564Sdim      m_hardware = false;
468314564Sdim      m_exception_language = eLanguageTypeUnknown;
469314564Sdim      m_language = lldb::eLanguageTypeUnknown;
470314564Sdim      m_skip_prologue = eLazyBoolCalculate;
471314564Sdim      m_breakpoint_names.clear();
472314564Sdim      m_all_files = false;
473314564Sdim      m_exception_extra_args.Clear();
474314564Sdim      m_move_to_nearest_code = eLazyBoolCalculate;
475314564Sdim      m_source_regex_func_names.clear();
476344779Sdim      m_current_key.clear();
477314564Sdim    }
478280031Sdim
479314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
480314564Sdim      return llvm::makeArrayRef(g_breakpoint_set_options);
481314564Sdim    }
482254721Semaste
483314564Sdim    // Instance variables to hold the values for command options.
484254721Semaste
485314564Sdim    std::string m_condition;
486314564Sdim    FileSpecList m_filenames;
487314564Sdim    uint32_t m_line_num;
488314564Sdim    uint32_t m_column;
489314564Sdim    std::vector<std::string> m_func_names;
490314564Sdim    std::vector<std::string> m_breakpoint_names;
491344779Sdim    lldb::FunctionNameType m_func_name_type_mask;
492314564Sdim    std::string m_func_regexp;
493314564Sdim    std::string m_source_text_regexp;
494314564Sdim    FileSpecList m_modules;
495314564Sdim    lldb::addr_t m_load_addr;
496314564Sdim    lldb::addr_t m_offset_addr;
497314564Sdim    bool m_catch_bp;
498314564Sdim    bool m_throw_bp;
499314564Sdim    bool m_hardware; // Request to use hardware breakpoints
500314564Sdim    lldb::LanguageType m_exception_language;
501314564Sdim    lldb::LanguageType m_language;
502314564Sdim    LazyBool m_skip_prologue;
503314564Sdim    bool m_all_files;
504314564Sdim    Args m_exception_extra_args;
505314564Sdim    LazyBool m_move_to_nearest_code;
506314564Sdim    std::unordered_set<std::string> m_source_regex_func_names;
507344779Sdim    std::string m_current_key;
508314564Sdim  };
509254721Semaste
510314564Sdimprotected:
511314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
512360784Sdim    Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
513254721Semaste
514314564Sdim    // The following are the various types of breakpoints that could be set:
515314564Sdim    //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
516314564Sdim    //   2).  -a  [-s -g]         (setting breakpoint by address)
517314564Sdim    //   3).  -n  [-s -g]         (setting breakpoint by function name)
518314564Sdim    //   4).  -r  [-s -g]         (setting breakpoint by function name regular
519314564Sdim    //   expression)
520314564Sdim    //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
521314564Sdim    //   to source text)
522314564Sdim    //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
523314564Sdim    //   given language.)
524254721Semaste
525314564Sdim    BreakpointSetType break_type = eSetTypeInvalid;
526254721Semaste
527360784Sdim    if (!m_python_class_options.GetName().empty())
528344779Sdim      break_type = eSetTypeScripted;
529344779Sdim    else if (m_options.m_line_num != 0)
530314564Sdim      break_type = eSetTypeFileAndLine;
531314564Sdim    else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
532314564Sdim      break_type = eSetTypeAddress;
533314564Sdim    else if (!m_options.m_func_names.empty())
534314564Sdim      break_type = eSetTypeFunctionName;
535314564Sdim    else if (!m_options.m_func_regexp.empty())
536314564Sdim      break_type = eSetTypeFunctionRegexp;
537314564Sdim    else if (!m_options.m_source_text_regexp.empty())
538314564Sdim      break_type = eSetTypeSourceRegexp;
539314564Sdim    else if (m_options.m_exception_language != eLanguageTypeUnknown)
540314564Sdim      break_type = eSetTypeException;
541254721Semaste
542327952Sdim    BreakpointSP bp_sp = nullptr;
543314564Sdim    FileSpec module_spec;
544314564Sdim    const bool internal = false;
545254721Semaste
546314564Sdim    // If the user didn't specify skip-prologue, having an offset should turn
547314564Sdim    // that off.
548314564Sdim    if (m_options.m_offset_addr != 0 &&
549314564Sdim        m_options.m_skip_prologue == eLazyBoolCalculate)
550314564Sdim      m_options.m_skip_prologue = eLazyBoolNo;
551280031Sdim
552314564Sdim    switch (break_type) {
553314564Sdim    case eSetTypeFileAndLine: // Breakpoint by source position
554314564Sdim    {
555314564Sdim      FileSpec file;
556314564Sdim      const size_t num_files = m_options.m_filenames.GetSize();
557314564Sdim      if (num_files == 0) {
558314564Sdim        if (!GetDefaultFile(target, file, result)) {
559314564Sdim          result.AppendError("No file supplied and no default file available.");
560314564Sdim          result.SetStatus(eReturnStatusFailed);
561314564Sdim          return false;
562254721Semaste        }
563314564Sdim      } else if (num_files > 1) {
564314564Sdim        result.AppendError("Only one file at a time is allowed for file and "
565314564Sdim                           "line breakpoints.");
566314564Sdim        result.SetStatus(eReturnStatusFailed);
567314564Sdim        return false;
568314564Sdim      } else
569314564Sdim        file = m_options.m_filenames.GetFileSpecAtIndex(0);
570254721Semaste
571314564Sdim      // Only check for inline functions if
572314564Sdim      LazyBool check_inlines = eLazyBoolCalculate;
573254721Semaste
574360784Sdim      bp_sp = target.CreateBreakpoint(
575360784Sdim          &(m_options.m_modules), file, m_options.m_line_num,
576360784Sdim          m_options.m_column, m_options.m_offset_addr, check_inlines,
577360784Sdim          m_options.m_skip_prologue, internal, m_options.m_hardware,
578360784Sdim          m_options.m_move_to_nearest_code);
579314564Sdim    } break;
580314564Sdim
581314564Sdim    case eSetTypeAddress: // Breakpoint by address
582254721Semaste    {
583314564Sdim      // If a shared library has been specified, make an lldb_private::Address
584327952Sdim      // with the library, and use that.  That way the address breakpoint
585327952Sdim      //  will track the load location of the library.
586314564Sdim      size_t num_modules_specified = m_options.m_modules.GetSize();
587314564Sdim      if (num_modules_specified == 1) {
588314564Sdim        const FileSpec *file_spec =
589314564Sdim            m_options.m_modules.GetFileSpecPointerAtIndex(0);
590360784Sdim        bp_sp = target.CreateAddressInModuleBreakpoint(
591360784Sdim            m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
592314564Sdim      } else if (num_modules_specified == 0) {
593360784Sdim        bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
594360784Sdim                                        m_options.m_hardware);
595314564Sdim      } else {
596314564Sdim        result.AppendError("Only one shared library can be specified for "
597314564Sdim                           "address breakpoints.");
598314564Sdim        result.SetStatus(eReturnStatusFailed);
599314564Sdim        return false;
600314564Sdim      }
601314564Sdim      break;
602254721Semaste    }
603314564Sdim    case eSetTypeFunctionName: // Breakpoint by function name
604314564Sdim    {
605344779Sdim      FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
606309124Sdim
607314564Sdim      if (name_type_mask == 0)
608314564Sdim        name_type_mask = eFunctionNameTypeAuto;
609254721Semaste
610360784Sdim      bp_sp = target.CreateBreakpoint(
611360784Sdim          &(m_options.m_modules), &(m_options.m_filenames),
612360784Sdim          m_options.m_func_names, name_type_mask, m_options.m_language,
613360784Sdim          m_options.m_offset_addr, m_options.m_skip_prologue, internal,
614360784Sdim          m_options.m_hardware);
615314564Sdim    } break;
616254721Semaste
617314564Sdim    case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
618314564Sdim                                 // name
619360784Sdim    {
620360784Sdim      RegularExpression regexp(m_options.m_func_regexp);
621360784Sdim      if (llvm::Error err = regexp.GetError()) {
622360784Sdim        result.AppendErrorWithFormat(
623360784Sdim            "Function name regular expression could not be compiled: \"%s\"",
624360784Sdim            llvm::toString(std::move(err)).c_str());
625360784Sdim        result.SetStatus(eReturnStatusFailed);
626360784Sdim        return false;
627360784Sdim      }
628254721Semaste
629360784Sdim      bp_sp = target.CreateFuncRegexBreakpoint(
630360784Sdim          &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
631360784Sdim          m_options.m_language, m_options.m_skip_prologue, internal,
632360784Sdim          m_options.m_hardware);
633360784Sdim    } break;
634314564Sdim    case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
635314564Sdim    {
636314564Sdim      const size_t num_files = m_options.m_filenames.GetSize();
637254721Semaste
638314564Sdim      if (num_files == 0 && !m_options.m_all_files) {
639314564Sdim        FileSpec file;
640314564Sdim        if (!GetDefaultFile(target, file, result)) {
641314564Sdim          result.AppendError(
642314564Sdim              "No files provided and could not find default file.");
643314564Sdim          result.SetStatus(eReturnStatusFailed);
644314564Sdim          return false;
645314564Sdim        } else {
646314564Sdim          m_options.m_filenames.Append(file);
647314564Sdim        }
648314564Sdim      }
649254721Semaste
650314564Sdim      RegularExpression regexp(m_options.m_source_text_regexp);
651360784Sdim      if (llvm::Error err = regexp.GetError()) {
652314564Sdim        result.AppendErrorWithFormat(
653314564Sdim            "Source text regular expression could not be compiled: \"%s\"",
654360784Sdim            llvm::toString(std::move(err)).c_str());
655314564Sdim        result.SetStatus(eReturnStatusFailed);
656314564Sdim        return false;
657314564Sdim      }
658360784Sdim      bp_sp = target.CreateSourceRegexBreakpoint(
659360784Sdim          &(m_options.m_modules), &(m_options.m_filenames),
660360784Sdim          m_options.m_source_regex_func_names, std::move(regexp), internal,
661360784Sdim          m_options.m_hardware, m_options.m_move_to_nearest_code);
662314564Sdim    } break;
663314564Sdim    case eSetTypeException: {
664321369Sdim      Status precond_error;
665360784Sdim      bp_sp = target.CreateExceptionBreakpoint(
666360784Sdim          m_options.m_exception_language, m_options.m_catch_bp,
667360784Sdim          m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
668360784Sdim          &precond_error);
669314564Sdim      if (precond_error.Fail()) {
670314564Sdim        result.AppendErrorWithFormat(
671314564Sdim            "Error setting extra exception arguments: %s",
672314564Sdim            precond_error.AsCString());
673360784Sdim        target.RemoveBreakpointByID(bp_sp->GetID());
674314564Sdim        result.SetStatus(eReturnStatusFailed);
675314564Sdim        return false;
676314564Sdim      }
677314564Sdim    } break;
678344779Sdim    case eSetTypeScripted: {
679344779Sdim
680344779Sdim      Status error;
681360784Sdim      bp_sp = target.CreateScriptedBreakpoint(
682360784Sdim          m_python_class_options.GetName().c_str(), &(m_options.m_modules),
683360784Sdim          &(m_options.m_filenames), false, m_options.m_hardware,
684360784Sdim          m_python_class_options.GetStructuredData(), &error);
685344779Sdim      if (error.Fail()) {
686344779Sdim        result.AppendErrorWithFormat(
687360784Sdim            "Error setting extra exception arguments: %s", error.AsCString());
688360784Sdim        target.RemoveBreakpointByID(bp_sp->GetID());
689344779Sdim        result.SetStatus(eReturnStatusFailed);
690344779Sdim        return false;
691344779Sdim      }
692344779Sdim    } break;
693314564Sdim    default:
694314564Sdim      break;
695314564Sdim    }
696254721Semaste
697314564Sdim    // Now set the various options that were passed in:
698327952Sdim    if (bp_sp) {
699327952Sdim      bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
700254721Semaste
701314564Sdim      if (!m_options.m_breakpoint_names.empty()) {
702321369Sdim        Status name_error;
703314564Sdim        for (auto name : m_options.m_breakpoint_names) {
704360784Sdim          target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
705314564Sdim          if (name_error.Fail()) {
706314564Sdim            result.AppendErrorWithFormat("Invalid breakpoint name: %s",
707314564Sdim                                         name.c_str());
708360784Sdim            target.RemoveBreakpointByID(bp_sp->GetID());
709314564Sdim            result.SetStatus(eReturnStatusFailed);
710314564Sdim            return false;
711314564Sdim          }
712314564Sdim        }
713314564Sdim      }
714314564Sdim    }
715360784Sdim
716327952Sdim    if (bp_sp) {
717314564Sdim      Stream &output_stream = result.GetOutputStream();
718314564Sdim      const bool show_locations = false;
719327952Sdim      bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
720360784Sdim                            show_locations);
721360784Sdim      if (&target == &GetDummyTarget())
722314564Sdim        output_stream.Printf("Breakpoint set in dummy target, will get copied "
723314564Sdim                             "into future targets.\n");
724314564Sdim      else {
725341825Sdim        // Don't print out this warning for exception breakpoints.  They can
726341825Sdim        // get set before the target is set, but we won't know how to actually
727341825Sdim        // set the breakpoint till we run.
728327952Sdim        if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
729314564Sdim          output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
730314564Sdim                               "actual locations.\n");
731314564Sdim        }
732314564Sdim      }
733314564Sdim      result.SetStatus(eReturnStatusSuccessFinishResult);
734327952Sdim    } else if (!bp_sp) {
735314564Sdim      result.AppendError("Breakpoint creation failed: No breakpoint created.");
736314564Sdim      result.SetStatus(eReturnStatusFailed);
737314564Sdim    }
738254721Semaste
739314564Sdim    return result.Succeeded();
740314564Sdim  }
741309124Sdim
742314564Sdimprivate:
743360784Sdim  bool GetDefaultFile(Target &target, FileSpec &file,
744314564Sdim                      CommandReturnObject &result) {
745314564Sdim    uint32_t default_line;
746341825Sdim    // First use the Source Manager's default file. Then use the current stack
747341825Sdim    // frame's file.
748360784Sdim    if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
749314564Sdim      StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
750314564Sdim      if (cur_frame == nullptr) {
751314564Sdim        result.AppendError(
752314564Sdim            "No selected frame to use to find the default file.");
753314564Sdim        result.SetStatus(eReturnStatusFailed);
754314564Sdim        return false;
755314564Sdim      } else if (!cur_frame->HasDebugInformation()) {
756314564Sdim        result.AppendError("Cannot use the selected frame to find the default "
757314564Sdim                           "file, it has no debug info.");
758314564Sdim        result.SetStatus(eReturnStatusFailed);
759314564Sdim        return false;
760314564Sdim      } else {
761314564Sdim        const SymbolContext &sc =
762314564Sdim            cur_frame->GetSymbolContext(eSymbolContextLineEntry);
763314564Sdim        if (sc.line_entry.file) {
764314564Sdim          file = sc.line_entry.file;
765314564Sdim        } else {
766314564Sdim          result.AppendError("Can't find the file for the selected frame to "
767314564Sdim                             "use as the default file.");
768314564Sdim          result.SetStatus(eReturnStatusFailed);
769314564Sdim          return false;
770314564Sdim        }
771314564Sdim      }
772314564Sdim    }
773314564Sdim    return true;
774314564Sdim  }
775254721Semaste
776327952Sdim  BreakpointOptionGroup m_bp_opts;
777327952Sdim  BreakpointDummyOptionGroup m_dummy_options;
778360784Sdim  OptionGroupPythonClassWithDict m_python_class_options;
779314564Sdim  CommandOptions m_options;
780327952Sdim  OptionGroupOptions m_all_options;
781314564Sdim};
782254721Semaste
783314564Sdim// CommandObjectBreakpointModify
784314564Sdim#pragma mark Modify
785254721Semaste
786314564Sdimclass CommandObjectBreakpointModify : public CommandObjectParsed {
787314564Sdimpublic:
788314564Sdim  CommandObjectBreakpointModify(CommandInterpreter &interpreter)
789314564Sdim      : CommandObjectParsed(interpreter, "breakpoint modify",
790314564Sdim                            "Modify the options on a breakpoint or set of "
791314564Sdim                            "breakpoints in the executable.  "
792314564Sdim                            "If no breakpoint is specified, acts on the last "
793314564Sdim                            "created breakpoint.  "
794314564Sdim                            "With the exception of -e, -d and -i, passing an "
795314564Sdim                            "empty argument clears the modification.",
796314564Sdim                            nullptr),
797314564Sdim        m_options() {
798314564Sdim    CommandArgumentEntry arg;
799314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
800314564Sdim                                      eArgTypeBreakpointIDRange);
801314564Sdim    // Add the entry for the first argument for this command to the object's
802314564Sdim    // arguments vector.
803314564Sdim    m_arguments.push_back(arg);
804360784Sdim
805360784Sdim    m_options.Append(&m_bp_opts,
806360784Sdim                     LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
807327952Sdim                     LLDB_OPT_SET_ALL);
808327952Sdim    m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
809327952Sdim    m_options.Finalize();
810314564Sdim  }
811254721Semaste
812314564Sdim  ~CommandObjectBreakpointModify() override = default;
813288943Sdim
814314564Sdim  Options *GetOptions() override { return &m_options; }
815254721Semaste
816314564Sdimprotected:
817314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
818360784Sdim    Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
819254721Semaste
820314564Sdim    std::unique_lock<std::recursive_mutex> lock;
821360784Sdim    target.GetBreakpointList().GetListMutex(lock);
822254721Semaste
823314564Sdim    BreakpointIDList valid_bp_ids;
824254721Semaste
825314564Sdim    CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
826360784Sdim        command, &target, result, &valid_bp_ids,
827327952Sdim        BreakpointName::Permissions::PermissionKinds::disablePerm);
828254721Semaste
829314564Sdim    if (result.Succeeded()) {
830314564Sdim      const size_t count = valid_bp_ids.GetSize();
831314564Sdim      for (size_t i = 0; i < count; ++i) {
832314564Sdim        BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
833254721Semaste
834314564Sdim        if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
835314564Sdim          Breakpoint *bp =
836360784Sdim              target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
837314564Sdim          if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
838314564Sdim            BreakpointLocation *location =
839314564Sdim                bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
840327952Sdim            if (location)
841360784Sdim              location->GetLocationOptions()->CopyOverSetOptions(
842360784Sdim                  m_bp_opts.GetBreakpointOptions());
843314564Sdim          } else {
844360784Sdim            bp->GetOptions()->CopyOverSetOptions(
845360784Sdim                m_bp_opts.GetBreakpointOptions());
846314564Sdim          }
847254721Semaste        }
848314564Sdim      }
849254721Semaste    }
850254721Semaste
851314564Sdim    return result.Succeeded();
852314564Sdim  }
853314564Sdim
854254721Semasteprivate:
855327952Sdim  BreakpointOptionGroup m_bp_opts;
856327952Sdim  BreakpointDummyOptionGroup m_dummy_opts;
857327952Sdim  OptionGroupOptions m_options;
858254721Semaste};
859254721Semaste
860254721Semaste// CommandObjectBreakpointEnable
861254721Semaste#pragma mark Enable
862254721Semaste
863314564Sdimclass CommandObjectBreakpointEnable : public CommandObjectParsed {
864254721Semastepublic:
865314564Sdim  CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
866314564Sdim      : CommandObjectParsed(interpreter, "enable",
867314564Sdim                            "Enable the specified disabled breakpoint(s). If "
868314564Sdim                            "no breakpoints are specified, enable all of them.",
869314564Sdim                            nullptr) {
870314564Sdim    CommandArgumentEntry arg;
871314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
872314564Sdim                                      eArgTypeBreakpointIDRange);
873314564Sdim    // Add the entry for the first argument for this command to the object's
874314564Sdim    // arguments vector.
875314564Sdim    m_arguments.push_back(arg);
876314564Sdim  }
877254721Semaste
878314564Sdim  ~CommandObjectBreakpointEnable() override = default;
879254721Semaste
880254721Semasteprotected:
881314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
882360784Sdim    Target &target = GetSelectedOrDummyTarget();
883254721Semaste
884314564Sdim    std::unique_lock<std::recursive_mutex> lock;
885360784Sdim    target.GetBreakpointList().GetListMutex(lock);
886254721Semaste
887360784Sdim    const BreakpointList &breakpoints = target.GetBreakpointList();
888254721Semaste
889314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
890254721Semaste
891314564Sdim    if (num_breakpoints == 0) {
892314564Sdim      result.AppendError("No breakpoints exist to be enabled.");
893314564Sdim      result.SetStatus(eReturnStatusFailed);
894314564Sdim      return false;
895314564Sdim    }
896254721Semaste
897314564Sdim    if (command.empty()) {
898314564Sdim      // No breakpoint selected; enable all currently set breakpoints.
899360784Sdim      target.EnableAllowedBreakpoints();
900314564Sdim      result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
901314564Sdim                                     " breakpoints)\n",
902314564Sdim                                     (uint64_t)num_breakpoints);
903314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
904314564Sdim    } else {
905314564Sdim      // Particular breakpoint selected; enable that breakpoint.
906314564Sdim      BreakpointIDList valid_bp_ids;
907314564Sdim      CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
908360784Sdim          command, &target, result, &valid_bp_ids,
909327952Sdim          BreakpointName::Permissions::PermissionKinds::disablePerm);
910254721Semaste
911314564Sdim      if (result.Succeeded()) {
912314564Sdim        int enable_count = 0;
913314564Sdim        int loc_count = 0;
914314564Sdim        const size_t count = valid_bp_ids.GetSize();
915314564Sdim        for (size_t i = 0; i < count; ++i) {
916314564Sdim          BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
917254721Semaste
918314564Sdim          if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
919314564Sdim            Breakpoint *breakpoint =
920360784Sdim                target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
921314564Sdim            if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
922314564Sdim              BreakpointLocation *location =
923314564Sdim                  breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
924314564Sdim              if (location) {
925314564Sdim                location->SetEnabled(true);
926314564Sdim                ++loc_count;
927314564Sdim              }
928314564Sdim            } else {
929314564Sdim              breakpoint->SetEnabled(true);
930314564Sdim              ++enable_count;
931254721Semaste            }
932314564Sdim          }
933254721Semaste        }
934314564Sdim        result.AppendMessageWithFormat("%d breakpoints enabled.\n",
935314564Sdim                                       enable_count + loc_count);
936314564Sdim        result.SetStatus(eReturnStatusSuccessFinishNoResult);
937314564Sdim      }
938314564Sdim    }
939254721Semaste
940314564Sdim    return result.Succeeded();
941314564Sdim  }
942254721Semaste};
943254721Semaste
944254721Semaste// CommandObjectBreakpointDisable
945254721Semaste#pragma mark Disable
946254721Semaste
947314564Sdimclass CommandObjectBreakpointDisable : public CommandObjectParsed {
948254721Semastepublic:
949314564Sdim  CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
950314564Sdim      : CommandObjectParsed(
951314564Sdim            interpreter, "breakpoint disable",
952314564Sdim            "Disable the specified breakpoint(s) without deleting "
953314564Sdim            "them.  If none are specified, disable all "
954314564Sdim            "breakpoints.",
955314564Sdim            nullptr) {
956314564Sdim    SetHelpLong(
957314564Sdim        "Disable the specified breakpoint(s) without deleting them.  \
958309124SdimIf none are specified, disable all breakpoints."
959314564Sdim        R"(
960288943Sdim
961309124Sdim)"
962314564Sdim        "Note: disabling a breakpoint will cause none of its locations to be hit \
963309124Sdimregardless of whether individual locations are enabled or disabled.  After the sequence:"
964314564Sdim        R"(
965288943Sdim
966288943Sdim    (lldb) break disable 1
967288943Sdim    (lldb) break enable 1.1
968288943Sdim
969288943Sdimexecution will NOT stop at location 1.1.  To achieve that, type:
970288943Sdim
971288943Sdim    (lldb) break disable 1.*
972288943Sdim    (lldb) break enable 1.1
973288943Sdim
974309124Sdim)"
975314564Sdim        "The first command disables all locations for breakpoint 1, \
976309124Sdimthe second re-enables the first location.");
977309124Sdim
978314564Sdim    CommandArgumentEntry arg;
979314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
980314564Sdim                                      eArgTypeBreakpointIDRange);
981314564Sdim    // Add the entry for the first argument for this command to the object's
982314564Sdim    // arguments vector.
983314564Sdim    m_arguments.push_back(arg);
984314564Sdim  }
985254721Semaste
986314564Sdim  ~CommandObjectBreakpointDisable() override = default;
987254721Semaste
988254721Semasteprotected:
989314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
990360784Sdim    Target &target = GetSelectedOrDummyTarget();
991314564Sdim    std::unique_lock<std::recursive_mutex> lock;
992360784Sdim    target.GetBreakpointList().GetListMutex(lock);
993254721Semaste
994360784Sdim    const BreakpointList &breakpoints = target.GetBreakpointList();
995314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
996254721Semaste
997314564Sdim    if (num_breakpoints == 0) {
998314564Sdim      result.AppendError("No breakpoints exist to be disabled.");
999314564Sdim      result.SetStatus(eReturnStatusFailed);
1000314564Sdim      return false;
1001314564Sdim    }
1002254721Semaste
1003314564Sdim    if (command.empty()) {
1004314564Sdim      // No breakpoint selected; disable all currently set breakpoints.
1005360784Sdim      target.DisableAllowedBreakpoints();
1006314564Sdim      result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1007314564Sdim                                     " breakpoints)\n",
1008314564Sdim                                     (uint64_t)num_breakpoints);
1009314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1010314564Sdim    } else {
1011314564Sdim      // Particular breakpoint selected; disable that breakpoint.
1012314564Sdim      BreakpointIDList valid_bp_ids;
1013254721Semaste
1014314564Sdim      CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1015360784Sdim          command, &target, result, &valid_bp_ids,
1016327952Sdim          BreakpointName::Permissions::PermissionKinds::disablePerm);
1017254721Semaste
1018314564Sdim      if (result.Succeeded()) {
1019314564Sdim        int disable_count = 0;
1020314564Sdim        int loc_count = 0;
1021314564Sdim        const size_t count = valid_bp_ids.GetSize();
1022314564Sdim        for (size_t i = 0; i < count; ++i) {
1023314564Sdim          BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1024254721Semaste
1025314564Sdim          if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1026314564Sdim            Breakpoint *breakpoint =
1027360784Sdim                target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1028314564Sdim            if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1029314564Sdim              BreakpointLocation *location =
1030314564Sdim                  breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1031314564Sdim              if (location) {
1032314564Sdim                location->SetEnabled(false);
1033314564Sdim                ++loc_count;
1034314564Sdim              }
1035314564Sdim            } else {
1036314564Sdim              breakpoint->SetEnabled(false);
1037314564Sdim              ++disable_count;
1038254721Semaste            }
1039314564Sdim          }
1040254721Semaste        }
1041314564Sdim        result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1042314564Sdim                                       disable_count + loc_count);
1043314564Sdim        result.SetStatus(eReturnStatusSuccessFinishNoResult);
1044314564Sdim      }
1045314564Sdim    }
1046254721Semaste
1047314564Sdim    return result.Succeeded();
1048314564Sdim  }
1049254721Semaste};
1050254721Semaste
1051254721Semaste// CommandObjectBreakpointList
1052314564Sdim
1053314564Sdim#pragma mark List::CommandOptions
1054353358Sdim#define LLDB_OPTIONS_breakpoint_list
1055353358Sdim#include "CommandOptions.inc"
1056314564Sdim
1057254721Semaste#pragma mark List
1058254721Semaste
1059314564Sdimclass CommandObjectBreakpointList : public CommandObjectParsed {
1060254721Semastepublic:
1061314564Sdim  CommandObjectBreakpointList(CommandInterpreter &interpreter)
1062314564Sdim      : CommandObjectParsed(
1063314564Sdim            interpreter, "breakpoint list",
1064314564Sdim            "List some or all breakpoints at configurable levels of detail.",
1065314564Sdim            nullptr),
1066314564Sdim        m_options() {
1067314564Sdim    CommandArgumentEntry arg;
1068314564Sdim    CommandArgumentData bp_id_arg;
1069254721Semaste
1070314564Sdim    // Define the first (and only) variant of this arg.
1071314564Sdim    bp_id_arg.arg_type = eArgTypeBreakpointID;
1072314564Sdim    bp_id_arg.arg_repetition = eArgRepeatOptional;
1073254721Semaste
1074314564Sdim    // There is only one variant this argument could be; put it into the
1075314564Sdim    // argument entry.
1076314564Sdim    arg.push_back(bp_id_arg);
1077254721Semaste
1078314564Sdim    // Push the data for the first argument into the m_arguments vector.
1079314564Sdim    m_arguments.push_back(arg);
1080314564Sdim  }
1081254721Semaste
1082314564Sdim  ~CommandObjectBreakpointList() override = default;
1083254721Semaste
1084314564Sdim  Options *GetOptions() override { return &m_options; }
1085314564Sdim
1086314564Sdim  class CommandOptions : public Options {
1087314564Sdim  public:
1088314564Sdim    CommandOptions()
1089314564Sdim        : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1090254721Semaste    }
1091254721Semaste
1092314564Sdim    ~CommandOptions() override = default;
1093254721Semaste
1094321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1095321369Sdim                          ExecutionContext *execution_context) override {
1096321369Sdim      Status error;
1097314564Sdim      const int short_option = m_getopt_table[option_idx].val;
1098254721Semaste
1099314564Sdim      switch (short_option) {
1100314564Sdim      case 'b':
1101314564Sdim        m_level = lldb::eDescriptionLevelBrief;
1102314564Sdim        break;
1103314564Sdim      case 'D':
1104314564Sdim        m_use_dummy = true;
1105314564Sdim        break;
1106314564Sdim      case 'f':
1107314564Sdim        m_level = lldb::eDescriptionLevelFull;
1108314564Sdim        break;
1109314564Sdim      case 'v':
1110314564Sdim        m_level = lldb::eDescriptionLevelVerbose;
1111314564Sdim        break;
1112314564Sdim      case 'i':
1113314564Sdim        m_internal = true;
1114314564Sdim        break;
1115314564Sdim      default:
1116360784Sdim        llvm_unreachable("Unimplemented option");
1117314564Sdim      }
1118254721Semaste
1119314564Sdim      return error;
1120314564Sdim    }
1121254721Semaste
1122314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
1123314564Sdim      m_level = lldb::eDescriptionLevelFull;
1124314564Sdim      m_internal = false;
1125314564Sdim      m_use_dummy = false;
1126314564Sdim    }
1127254721Semaste
1128314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1129314564Sdim      return llvm::makeArrayRef(g_breakpoint_list_options);
1130314564Sdim    }
1131254721Semaste
1132314564Sdim    // Instance variables to hold the values for command options.
1133254721Semaste
1134314564Sdim    lldb::DescriptionLevel m_level;
1135254721Semaste
1136314564Sdim    bool m_internal;
1137314564Sdim    bool m_use_dummy;
1138314564Sdim  };
1139254721Semaste
1140254721Semasteprotected:
1141314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1142360784Sdim    Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1143280031Sdim
1144314564Sdim    const BreakpointList &breakpoints =
1145360784Sdim        target.GetBreakpointList(m_options.m_internal);
1146314564Sdim    std::unique_lock<std::recursive_mutex> lock;
1147360784Sdim    target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1148254721Semaste
1149314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
1150254721Semaste
1151314564Sdim    if (num_breakpoints == 0) {
1152314564Sdim      result.AppendMessage("No breakpoints currently set.");
1153314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1154314564Sdim      return true;
1155314564Sdim    }
1156254721Semaste
1157314564Sdim    Stream &output_stream = result.GetOutputStream();
1158254721Semaste
1159314564Sdim    if (command.empty()) {
1160314564Sdim      // No breakpoint selected; show info about all currently set breakpoints.
1161314564Sdim      result.AppendMessage("Current breakpoints:");
1162314564Sdim      for (size_t i = 0; i < num_breakpoints; ++i) {
1163314564Sdim        Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1164327952Sdim        if (breakpoint->AllowList())
1165360784Sdim          AddBreakpointDescription(&output_stream, breakpoint,
1166327952Sdim                                   m_options.m_level);
1167314564Sdim      }
1168314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1169314564Sdim    } else {
1170314564Sdim      // Particular breakpoints selected; show info about that breakpoint.
1171314564Sdim      BreakpointIDList valid_bp_ids;
1172314564Sdim      CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1173360784Sdim          command, &target, result, &valid_bp_ids,
1174327952Sdim          BreakpointName::Permissions::PermissionKinds::listPerm);
1175254721Semaste
1176314564Sdim      if (result.Succeeded()) {
1177314564Sdim        for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1178314564Sdim          BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1179314564Sdim          Breakpoint *breakpoint =
1180360784Sdim              target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1181314564Sdim          AddBreakpointDescription(&output_stream, breakpoint,
1182314564Sdim                                   m_options.m_level);
1183254721Semaste        }
1184314564Sdim        result.SetStatus(eReturnStatusSuccessFinishNoResult);
1185314564Sdim      } else {
1186314564Sdim        result.AppendError("Invalid breakpoint ID.");
1187314564Sdim        result.SetStatus(eReturnStatusFailed);
1188314564Sdim      }
1189254721Semaste    }
1190254721Semaste
1191314564Sdim    return result.Succeeded();
1192314564Sdim  }
1193314564Sdim
1194254721Semasteprivate:
1195314564Sdim  CommandOptions m_options;
1196254721Semaste};
1197254721Semaste
1198314564Sdim// CommandObjectBreakpointClear
1199314564Sdim#pragma mark Clear::CommandOptions
1200254721Semaste
1201360784Sdim#define LLDB_OPTIONS_breakpoint_clear
1202360784Sdim#include "CommandOptions.inc"
1203254721Semaste
1204254721Semaste#pragma mark Clear
1205254721Semaste
1206314564Sdimclass CommandObjectBreakpointClear : public CommandObjectParsed {
1207254721Semastepublic:
1208353358Sdim  enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1209254721Semaste
1210314564Sdim  CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1211314564Sdim      : CommandObjectParsed(interpreter, "breakpoint clear",
1212314564Sdim                            "Delete or disable breakpoints matching the "
1213314564Sdim                            "specified source file and line.",
1214314564Sdim                            "breakpoint clear <cmd-options>"),
1215314564Sdim        m_options() {}
1216254721Semaste
1217314564Sdim  ~CommandObjectBreakpointClear() override = default;
1218254721Semaste
1219314564Sdim  Options *GetOptions() override { return &m_options; }
1220254721Semaste
1221314564Sdim  class CommandOptions : public Options {
1222314564Sdim  public:
1223314564Sdim    CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1224254721Semaste
1225314564Sdim    ~CommandOptions() override = default;
1226254721Semaste
1227321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1228321369Sdim                          ExecutionContext *execution_context) override {
1229321369Sdim      Status error;
1230314564Sdim      const int short_option = m_getopt_table[option_idx].val;
1231254721Semaste
1232314564Sdim      switch (short_option) {
1233314564Sdim      case 'f':
1234314564Sdim        m_filename.assign(option_arg);
1235314564Sdim        break;
1236254721Semaste
1237314564Sdim      case 'l':
1238314564Sdim        option_arg.getAsInteger(0, m_line_num);
1239314564Sdim        break;
1240254721Semaste
1241314564Sdim      default:
1242360784Sdim        llvm_unreachable("Unimplemented option");
1243314564Sdim      }
1244254721Semaste
1245314564Sdim      return error;
1246314564Sdim    }
1247254721Semaste
1248314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
1249314564Sdim      m_filename.clear();
1250314564Sdim      m_line_num = 0;
1251314564Sdim    }
1252254721Semaste
1253314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1254314564Sdim      return llvm::makeArrayRef(g_breakpoint_clear_options);
1255314564Sdim    }
1256254721Semaste
1257314564Sdim    // Instance variables to hold the values for command options.
1258254721Semaste
1259314564Sdim    std::string m_filename;
1260314564Sdim    uint32_t m_line_num;
1261314564Sdim  };
1262254721Semaste
1263254721Semasteprotected:
1264314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1265360784Sdim    Target &target = GetSelectedOrDummyTarget();
1266254721Semaste
1267341825Sdim    // The following are the various types of breakpoints that could be
1268341825Sdim    // cleared:
1269314564Sdim    //   1). -f -l (clearing breakpoint by source location)
1270254721Semaste
1271314564Sdim    BreakpointClearType break_type = eClearTypeInvalid;
1272254721Semaste
1273314564Sdim    if (m_options.m_line_num != 0)
1274314564Sdim      break_type = eClearTypeFileAndLine;
1275254721Semaste
1276314564Sdim    std::unique_lock<std::recursive_mutex> lock;
1277360784Sdim    target.GetBreakpointList().GetListMutex(lock);
1278254721Semaste
1279360784Sdim    BreakpointList &breakpoints = target.GetBreakpointList();
1280314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
1281254721Semaste
1282314564Sdim    // Early return if there's no breakpoint at all.
1283314564Sdim    if (num_breakpoints == 0) {
1284314564Sdim      result.AppendError("Breakpoint clear: No breakpoint cleared.");
1285314564Sdim      result.SetStatus(eReturnStatusFailed);
1286314564Sdim      return result.Succeeded();
1287314564Sdim    }
1288254721Semaste
1289314564Sdim    // Find matching breakpoints and delete them.
1290254721Semaste
1291314564Sdim    // First create a copy of all the IDs.
1292314564Sdim    std::vector<break_id_t> BreakIDs;
1293314564Sdim    for (size_t i = 0; i < num_breakpoints; ++i)
1294314564Sdim      BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1295254721Semaste
1296314564Sdim    int num_cleared = 0;
1297314564Sdim    StreamString ss;
1298314564Sdim    switch (break_type) {
1299314564Sdim    case eClearTypeFileAndLine: // Breakpoint by source position
1300314564Sdim    {
1301314564Sdim      const ConstString filename(m_options.m_filename.c_str());
1302314564Sdim      BreakpointLocationCollection loc_coll;
1303254721Semaste
1304314564Sdim      for (size_t i = 0; i < num_breakpoints; ++i) {
1305314564Sdim        Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1306254721Semaste
1307314564Sdim        if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1308314564Sdim          // If the collection size is 0, it's a full match and we can just
1309314564Sdim          // remove the breakpoint.
1310314564Sdim          if (loc_coll.GetSize() == 0) {
1311314564Sdim            bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1312314564Sdim            ss.EOL();
1313360784Sdim            target.RemoveBreakpointByID(bp->GetID());
1314314564Sdim            ++num_cleared;
1315314564Sdim          }
1316254721Semaste        }
1317314564Sdim      }
1318314564Sdim    } break;
1319254721Semaste
1320314564Sdim    default:
1321314564Sdim      break;
1322314564Sdim    }
1323254721Semaste
1324314564Sdim    if (num_cleared > 0) {
1325314564Sdim      Stream &output_stream = result.GetOutputStream();
1326314564Sdim      output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1327314564Sdim      output_stream << ss.GetString();
1328314564Sdim      output_stream.EOL();
1329314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1330314564Sdim    } else {
1331314564Sdim      result.AppendError("Breakpoint clear: No breakpoint cleared.");
1332314564Sdim      result.SetStatus(eReturnStatusFailed);
1333254721Semaste    }
1334254721Semaste
1335314564Sdim    return result.Succeeded();
1336314564Sdim  }
1337314564Sdim
1338254721Semasteprivate:
1339314564Sdim  CommandOptions m_options;
1340254721Semaste};
1341254721Semaste
1342254721Semaste// CommandObjectBreakpointDelete
1343360784Sdim#define LLDB_OPTIONS_breakpoint_delete
1344360784Sdim#include "CommandOptions.inc"
1345314564Sdim
1346254721Semaste#pragma mark Delete
1347254721Semaste
1348314564Sdimclass CommandObjectBreakpointDelete : public CommandObjectParsed {
1349254721Semastepublic:
1350314564Sdim  CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1351314564Sdim      : CommandObjectParsed(interpreter, "breakpoint delete",
1352314564Sdim                            "Delete the specified breakpoint(s).  If no "
1353314564Sdim                            "breakpoints are specified, delete them all.",
1354309124Sdim                            nullptr),
1355314564Sdim        m_options() {
1356314564Sdim    CommandArgumentEntry arg;
1357314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1358314564Sdim                                      eArgTypeBreakpointIDRange);
1359314564Sdim    // Add the entry for the first argument for this command to the object's
1360314564Sdim    // arguments vector.
1361314564Sdim    m_arguments.push_back(arg);
1362314564Sdim  }
1363254721Semaste
1364314564Sdim  ~CommandObjectBreakpointDelete() override = default;
1365254721Semaste
1366314564Sdim  Options *GetOptions() override { return &m_options; }
1367280031Sdim
1368314564Sdim  class CommandOptions : public Options {
1369314564Sdim  public:
1370314564Sdim    CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1371280031Sdim
1372314564Sdim    ~CommandOptions() override = default;
1373280031Sdim
1374321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1375321369Sdim                          ExecutionContext *execution_context) override {
1376321369Sdim      Status error;
1377314564Sdim      const int short_option = m_getopt_table[option_idx].val;
1378280031Sdim
1379314564Sdim      switch (short_option) {
1380314564Sdim      case 'f':
1381314564Sdim        m_force = true;
1382314564Sdim        break;
1383280031Sdim
1384314564Sdim      case 'D':
1385314564Sdim        m_use_dummy = true;
1386314564Sdim        break;
1387280031Sdim
1388314564Sdim      default:
1389360784Sdim        llvm_unreachable("Unimplemented option");
1390314564Sdim      }
1391280031Sdim
1392314564Sdim      return error;
1393314564Sdim    }
1394280031Sdim
1395314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
1396314564Sdim      m_use_dummy = false;
1397314564Sdim      m_force = false;
1398314564Sdim    }
1399280031Sdim
1400314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1401314564Sdim      return llvm::makeArrayRef(g_breakpoint_delete_options);
1402314564Sdim    }
1403280031Sdim
1404314564Sdim    // Instance variables to hold the values for command options.
1405314564Sdim    bool m_use_dummy;
1406314564Sdim    bool m_force;
1407314564Sdim  };
1408280031Sdim
1409254721Semasteprotected:
1410314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1411360784Sdim    Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1412280031Sdim
1413314564Sdim    std::unique_lock<std::recursive_mutex> lock;
1414360784Sdim    target.GetBreakpointList().GetListMutex(lock);
1415309124Sdim
1416360784Sdim    const BreakpointList &breakpoints = target.GetBreakpointList();
1417254721Semaste
1418314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
1419254721Semaste
1420314564Sdim    if (num_breakpoints == 0) {
1421314564Sdim      result.AppendError("No breakpoints exist to be deleted.");
1422314564Sdim      result.SetStatus(eReturnStatusFailed);
1423314564Sdim      return false;
1424314564Sdim    }
1425254721Semaste
1426314564Sdim    if (command.empty()) {
1427314564Sdim      if (!m_options.m_force &&
1428314564Sdim          !m_interpreter.Confirm(
1429314564Sdim              "About to delete all breakpoints, do you want to do that?",
1430314564Sdim              true)) {
1431314564Sdim        result.AppendMessage("Operation cancelled...");
1432314564Sdim      } else {
1433360784Sdim        target.RemoveAllowedBreakpoints();
1434314564Sdim        result.AppendMessageWithFormat(
1435314564Sdim            "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1436314564Sdim            (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1437314564Sdim      }
1438314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1439314564Sdim    } else {
1440314564Sdim      // Particular breakpoint selected; disable that breakpoint.
1441314564Sdim      BreakpointIDList valid_bp_ids;
1442314564Sdim      CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1443360784Sdim          command, &target, result, &valid_bp_ids,
1444327952Sdim          BreakpointName::Permissions::PermissionKinds::deletePerm);
1445254721Semaste
1446314564Sdim      if (result.Succeeded()) {
1447314564Sdim        int delete_count = 0;
1448314564Sdim        int disable_count = 0;
1449314564Sdim        const size_t count = valid_bp_ids.GetSize();
1450314564Sdim        for (size_t i = 0; i < count; ++i) {
1451314564Sdim          BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1452254721Semaste
1453314564Sdim          if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1454314564Sdim            if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1455314564Sdim              Breakpoint *breakpoint =
1456360784Sdim                  target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1457314564Sdim              BreakpointLocation *location =
1458314564Sdim                  breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1459314564Sdim              // It makes no sense to try to delete individual locations, so we
1460314564Sdim              // disable them instead.
1461314564Sdim              if (location) {
1462314564Sdim                location->SetEnabled(false);
1463314564Sdim                ++disable_count;
1464314564Sdim              }
1465314564Sdim            } else {
1466360784Sdim              target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1467314564Sdim              ++delete_count;
1468254721Semaste            }
1469314564Sdim          }
1470254721Semaste        }
1471314564Sdim        result.AppendMessageWithFormat(
1472314564Sdim            "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1473314564Sdim            delete_count, disable_count);
1474314564Sdim        result.SetStatus(eReturnStatusSuccessFinishNoResult);
1475314564Sdim      }
1476254721Semaste    }
1477314564Sdim    return result.Succeeded();
1478314564Sdim  }
1479309124Sdim
1480280031Sdimprivate:
1481314564Sdim  CommandOptions m_options;
1482254721Semaste};
1483254721Semaste
1484280031Sdim// CommandObjectBreakpointName
1485360784Sdim#define LLDB_OPTIONS_breakpoint_name
1486360784Sdim#include "CommandOptions.inc"
1487280031Sdim
1488314564Sdimclass BreakpointNameOptionGroup : public OptionGroup {
1489280031Sdimpublic:
1490314564Sdim  BreakpointNameOptionGroup()
1491314564Sdim      : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1492314564Sdim  }
1493280031Sdim
1494314564Sdim  ~BreakpointNameOptionGroup() override = default;
1495309124Sdim
1496314564Sdim  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1497314564Sdim    return llvm::makeArrayRef(g_breakpoint_name_options);
1498314564Sdim  }
1499280031Sdim
1500321369Sdim  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1501321369Sdim                        ExecutionContext *execution_context) override {
1502321369Sdim    Status error;
1503314564Sdim    const int short_option = g_breakpoint_name_options[option_idx].short_option;
1504280031Sdim
1505314564Sdim    switch (short_option) {
1506314564Sdim    case 'N':
1507314564Sdim      if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1508314564Sdim          error.Success())
1509314564Sdim        m_name.SetValueFromString(option_arg);
1510314564Sdim      break;
1511314564Sdim    case 'B':
1512314564Sdim      if (m_breakpoint.SetValueFromString(option_arg).Fail())
1513314564Sdim        error.SetErrorStringWithFormat(
1514314564Sdim            "unrecognized value \"%s\" for breakpoint",
1515314564Sdim            option_arg.str().c_str());
1516314564Sdim      break;
1517314564Sdim    case 'D':
1518314564Sdim      if (m_use_dummy.SetValueFromString(option_arg).Fail())
1519314564Sdim        error.SetErrorStringWithFormat(
1520314564Sdim            "unrecognized value \"%s\" for use-dummy",
1521314564Sdim            option_arg.str().c_str());
1522314564Sdim      break;
1523327952Sdim    case 'H':
1524327952Sdim      m_help_string.SetValueFromString(option_arg);
1525327952Sdim      break;
1526280031Sdim
1527314564Sdim    default:
1528360784Sdim      llvm_unreachable("Unimplemented option");
1529280031Sdim    }
1530314564Sdim    return error;
1531314564Sdim  }
1532280031Sdim
1533314564Sdim  void OptionParsingStarting(ExecutionContext *execution_context) override {
1534314564Sdim    m_name.Clear();
1535314564Sdim    m_breakpoint.Clear();
1536314564Sdim    m_use_dummy.Clear();
1537314564Sdim    m_use_dummy.SetDefaultValue(false);
1538327952Sdim    m_help_string.Clear();
1539314564Sdim  }
1540314564Sdim
1541314564Sdim  OptionValueString m_name;
1542314564Sdim  OptionValueUInt64 m_breakpoint;
1543314564Sdim  OptionValueBoolean m_use_dummy;
1544327952Sdim  OptionValueString m_help_string;
1545280031Sdim};
1546280031Sdim
1547360784Sdim#define LLDB_OPTIONS_breakpoint_access
1548360784Sdim#include "CommandOptions.inc"
1549327952Sdim
1550344779Sdimclass BreakpointAccessOptionGroup : public OptionGroup {
1551327952Sdimpublic:
1552344779Sdim  BreakpointAccessOptionGroup() : OptionGroup() {}
1553344779Sdim
1554327952Sdim  ~BreakpointAccessOptionGroup() override = default;
1555344779Sdim
1556327952Sdim  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1557327952Sdim    return llvm::makeArrayRef(g_breakpoint_access_options);
1558327952Sdim  }
1559327952Sdim  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1560327952Sdim                        ExecutionContext *execution_context) override {
1561327952Sdim    Status error;
1562360784Sdim    const int short_option =
1563360784Sdim        g_breakpoint_access_options[option_idx].short_option;
1564327952Sdim
1565327952Sdim    switch (short_option) {
1566360784Sdim    case 'L': {
1567360784Sdim      bool value, success;
1568360784Sdim      value = OptionArgParser::ToBoolean(option_arg, false, &success);
1569360784Sdim      if (success) {
1570360784Sdim        m_permissions.SetAllowList(value);
1571360784Sdim      } else
1572360784Sdim        error.SetErrorStringWithFormat(
1573360784Sdim            "invalid boolean value '%s' passed for -L option",
1574360784Sdim            option_arg.str().c_str());
1575360784Sdim    } break;
1576360784Sdim    case 'A': {
1577360784Sdim      bool value, success;
1578360784Sdim      value = OptionArgParser::ToBoolean(option_arg, false, &success);
1579360784Sdim      if (success) {
1580360784Sdim        m_permissions.SetAllowDisable(value);
1581360784Sdim      } else
1582360784Sdim        error.SetErrorStringWithFormat(
1583360784Sdim            "invalid boolean value '%s' passed for -L option",
1584360784Sdim            option_arg.str().c_str());
1585360784Sdim    } break;
1586360784Sdim    case 'D': {
1587360784Sdim      bool value, success;
1588360784Sdim      value = OptionArgParser::ToBoolean(option_arg, false, &success);
1589360784Sdim      if (success) {
1590360784Sdim        m_permissions.SetAllowDelete(value);
1591360784Sdim      } else
1592360784Sdim        error.SetErrorStringWithFormat(
1593360784Sdim            "invalid boolean value '%s' passed for -L option",
1594360784Sdim            option_arg.str().c_str());
1595360784Sdim    } break;
1596360784Sdim    default:
1597360784Sdim      llvm_unreachable("Unimplemented option");
1598360784Sdim    }
1599327952Sdim
1600327952Sdim    return error;
1601327952Sdim  }
1602360784Sdim
1603360784Sdim  void OptionParsingStarting(ExecutionContext *execution_context) override {}
1604360784Sdim
1605360784Sdim  const BreakpointName::Permissions &GetPermissions() const {
1606327952Sdim    return m_permissions;
1607327952Sdim  }
1608360784Sdim  BreakpointName::Permissions m_permissions;
1609327952Sdim};
1610327952Sdim
1611327952Sdimclass CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1612327952Sdimpublic:
1613327952Sdim  CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1614327952Sdim      : CommandObjectParsed(
1615360784Sdim            interpreter, "configure",
1616360784Sdim            "Configure the options for the breakpoint"
1617327952Sdim            " name provided.  "
1618327952Sdim            "If you provide a breakpoint id, the options will be copied from "
1619327952Sdim            "the breakpoint, otherwise only the options specified will be set "
1620327952Sdim            "on the name.",
1621327952Sdim            "breakpoint name configure <command-options> "
1622327952Sdim            "<breakpoint-name-list>"),
1623327952Sdim        m_bp_opts(), m_option_group() {
1624327952Sdim    // Create the first variant for the first (and only) argument for this
1625327952Sdim    // command.
1626327952Sdim    CommandArgumentEntry arg1;
1627327952Sdim    CommandArgumentData id_arg;
1628327952Sdim    id_arg.arg_type = eArgTypeBreakpointName;
1629327952Sdim    id_arg.arg_repetition = eArgRepeatOptional;
1630327952Sdim    arg1.push_back(id_arg);
1631327952Sdim    m_arguments.push_back(arg1);
1632327952Sdim
1633360784Sdim    m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1634360784Sdim    m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1635327952Sdim                          LLDB_OPT_SET_ALL);
1636360784Sdim    m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1637327952Sdim                          LLDB_OPT_SET_ALL);
1638327952Sdim    m_option_group.Finalize();
1639327952Sdim  }
1640327952Sdim
1641327952Sdim  ~CommandObjectBreakpointNameConfigure() override = default;
1642327952Sdim
1643327952Sdim  Options *GetOptions() override { return &m_option_group; }
1644327952Sdim
1645327952Sdimprotected:
1646327952Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1647327952Sdim
1648327952Sdim    const size_t argc = command.GetArgumentCount();
1649327952Sdim    if (argc == 0) {
1650327952Sdim      result.AppendError("No names provided.");
1651327952Sdim      result.SetStatus(eReturnStatusFailed);
1652327952Sdim      return false;
1653327952Sdim    }
1654327952Sdim
1655360784Sdim    Target &target = GetSelectedOrDummyTarget(false);
1656327952Sdim
1657327952Sdim    std::unique_lock<std::recursive_mutex> lock;
1658360784Sdim    target.GetBreakpointList().GetListMutex(lock);
1659327952Sdim
1660327952Sdim    // Make a pass through first to see that all the names are legal.
1661327952Sdim    for (auto &entry : command.entries()) {
1662327952Sdim      Status error;
1663360784Sdim      if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1664327952Sdim        result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1665327952Sdim                                     entry.c_str(), error.AsCString());
1666327952Sdim        result.SetStatus(eReturnStatusFailed);
1667327952Sdim        return false;
1668327952Sdim      }
1669327952Sdim    }
1670341825Sdim    // Now configure them, we already pre-checked the names so we don't need to
1671341825Sdim    // check the error:
1672327952Sdim    BreakpointSP bp_sp;
1673360784Sdim    if (m_bp_id.m_breakpoint.OptionWasSet()) {
1674327952Sdim      lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1675360784Sdim      bp_sp = target.GetBreakpointByID(bp_id);
1676360784Sdim      if (!bp_sp) {
1677327952Sdim        result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1678360784Sdim                                      bp_id);
1679327952Sdim        result.SetStatus(eReturnStatusFailed);
1680327952Sdim        return false;
1681327952Sdim      }
1682327952Sdim    }
1683327952Sdim
1684327952Sdim    Status error;
1685327952Sdim    for (auto &entry : command.entries()) {
1686327952Sdim      ConstString name(entry.c_str());
1687360784Sdim      BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1688327952Sdim      if (!bp_name)
1689327952Sdim        continue;
1690327952Sdim      if (m_bp_id.m_help_string.OptionWasSet())
1691327952Sdim        bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1692360784Sdim
1693327952Sdim      if (bp_sp)
1694360784Sdim        target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1695327952Sdim                                       m_access_options.GetPermissions());
1696327952Sdim      else
1697360784Sdim        target.ConfigureBreakpointName(*bp_name,
1698327952Sdim                                       m_bp_opts.GetBreakpointOptions(),
1699327952Sdim                                       m_access_options.GetPermissions());
1700327952Sdim    }
1701327952Sdim    return true;
1702327952Sdim  }
1703327952Sdim
1704327952Sdimprivate:
1705327952Sdim  BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1706327952Sdim  BreakpointOptionGroup m_bp_opts;
1707327952Sdim  BreakpointAccessOptionGroup m_access_options;
1708327952Sdim  OptionGroupOptions m_option_group;
1709327952Sdim};
1710327952Sdim
1711314564Sdimclass CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1712280031Sdimpublic:
1713314564Sdim  CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1714314564Sdim      : CommandObjectParsed(
1715314564Sdim            interpreter, "add", "Add a name to the breakpoints provided.",
1716314564Sdim            "breakpoint name add <command-options> <breakpoint-id-list>"),
1717314564Sdim        m_name_options(), m_option_group() {
1718314564Sdim    // Create the first variant for the first (and only) argument for this
1719314564Sdim    // command.
1720314564Sdim    CommandArgumentEntry arg1;
1721314564Sdim    CommandArgumentData id_arg;
1722314564Sdim    id_arg.arg_type = eArgTypeBreakpointID;
1723314564Sdim    id_arg.arg_repetition = eArgRepeatOptional;
1724314564Sdim    arg1.push_back(id_arg);
1725314564Sdim    m_arguments.push_back(arg1);
1726280031Sdim
1727314564Sdim    m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1728314564Sdim    m_option_group.Finalize();
1729314564Sdim  }
1730280031Sdim
1731314564Sdim  ~CommandObjectBreakpointNameAdd() override = default;
1732280031Sdim
1733314564Sdim  Options *GetOptions() override { return &m_option_group; }
1734309124Sdim
1735280031Sdimprotected:
1736314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1737314564Sdim    if (!m_name_options.m_name.OptionWasSet()) {
1738314564Sdim      result.SetError("No name option provided.");
1739314564Sdim      return false;
1740314564Sdim    }
1741280031Sdim
1742360784Sdim    Target &target =
1743314564Sdim        GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1744280031Sdim
1745314564Sdim    std::unique_lock<std::recursive_mutex> lock;
1746360784Sdim    target.GetBreakpointList().GetListMutex(lock);
1747309124Sdim
1748360784Sdim    const BreakpointList &breakpoints = target.GetBreakpointList();
1749280031Sdim
1750314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
1751314564Sdim    if (num_breakpoints == 0) {
1752314564Sdim      result.SetError("No breakpoints, cannot add names.");
1753314564Sdim      result.SetStatus(eReturnStatusFailed);
1754314564Sdim      return false;
1755314564Sdim    }
1756280031Sdim
1757314564Sdim    // Particular breakpoint selected; disable that breakpoint.
1758314564Sdim    BreakpointIDList valid_bp_ids;
1759314564Sdim    CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1760360784Sdim        command, &target, result, &valid_bp_ids,
1761327952Sdim        BreakpointName::Permissions::PermissionKinds::listPerm);
1762280031Sdim
1763314564Sdim    if (result.Succeeded()) {
1764314564Sdim      if (valid_bp_ids.GetSize() == 0) {
1765314564Sdim        result.SetError("No breakpoints specified, cannot add names.");
1766314564Sdim        result.SetStatus(eReturnStatusFailed);
1767314564Sdim        return false;
1768314564Sdim      }
1769314564Sdim      size_t num_valid_ids = valid_bp_ids.GetSize();
1770327952Sdim      const char *bp_name = m_name_options.m_name.GetCurrentValue();
1771360784Sdim      Status error; // This error reports illegal names, but we've already
1772327952Sdim                    // checked that, so we don't need to check it again here.
1773314564Sdim      for (size_t index = 0; index < num_valid_ids; index++) {
1774314564Sdim        lldb::break_id_t bp_id =
1775314564Sdim            valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1776314564Sdim        BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1777360784Sdim        target.AddNameToBreakpoint(bp_sp, bp_name, error);
1778314564Sdim      }
1779280031Sdim    }
1780280031Sdim
1781314564Sdim    return true;
1782314564Sdim  }
1783314564Sdim
1784280031Sdimprivate:
1785314564Sdim  BreakpointNameOptionGroup m_name_options;
1786314564Sdim  OptionGroupOptions m_option_group;
1787280031Sdim};
1788280031Sdim
1789314564Sdimclass CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1790280031Sdimpublic:
1791314564Sdim  CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1792314564Sdim      : CommandObjectParsed(
1793314564Sdim            interpreter, "delete",
1794314564Sdim            "Delete a name from the breakpoints provided.",
1795314564Sdim            "breakpoint name delete <command-options> <breakpoint-id-list>"),
1796314564Sdim        m_name_options(), m_option_group() {
1797314564Sdim    // Create the first variant for the first (and only) argument for this
1798314564Sdim    // command.
1799314564Sdim    CommandArgumentEntry arg1;
1800314564Sdim    CommandArgumentData id_arg;
1801314564Sdim    id_arg.arg_type = eArgTypeBreakpointID;
1802314564Sdim    id_arg.arg_repetition = eArgRepeatOptional;
1803314564Sdim    arg1.push_back(id_arg);
1804314564Sdim    m_arguments.push_back(arg1);
1805280031Sdim
1806314564Sdim    m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1807314564Sdim    m_option_group.Finalize();
1808314564Sdim  }
1809314564Sdim
1810314564Sdim  ~CommandObjectBreakpointNameDelete() override = default;
1811314564Sdim
1812314564Sdim  Options *GetOptions() override { return &m_option_group; }
1813314564Sdim
1814314564Sdimprotected:
1815314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1816314564Sdim    if (!m_name_options.m_name.OptionWasSet()) {
1817314564Sdim      result.SetError("No name option provided.");
1818314564Sdim      return false;
1819280031Sdim    }
1820280031Sdim
1821360784Sdim    Target &target =
1822314564Sdim        GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1823280031Sdim
1824314564Sdim    std::unique_lock<std::recursive_mutex> lock;
1825360784Sdim    target.GetBreakpointList().GetListMutex(lock);
1826280031Sdim
1827360784Sdim    const BreakpointList &breakpoints = target.GetBreakpointList();
1828280031Sdim
1829314564Sdim    size_t num_breakpoints = breakpoints.GetSize();
1830314564Sdim    if (num_breakpoints == 0) {
1831314564Sdim      result.SetError("No breakpoints, cannot delete names.");
1832314564Sdim      result.SetStatus(eReturnStatusFailed);
1833314564Sdim      return false;
1834314564Sdim    }
1835280031Sdim
1836314564Sdim    // Particular breakpoint selected; disable that breakpoint.
1837314564Sdim    BreakpointIDList valid_bp_ids;
1838314564Sdim    CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1839360784Sdim        command, &target, result, &valid_bp_ids,
1840327952Sdim        BreakpointName::Permissions::PermissionKinds::deletePerm);
1841309124Sdim
1842314564Sdim    if (result.Succeeded()) {
1843314564Sdim      if (valid_bp_ids.GetSize() == 0) {
1844314564Sdim        result.SetError("No breakpoints specified, cannot delete names.");
1845314564Sdim        result.SetStatus(eReturnStatusFailed);
1846314564Sdim        return false;
1847314564Sdim      }
1848327952Sdim      ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1849314564Sdim      size_t num_valid_ids = valid_bp_ids.GetSize();
1850314564Sdim      for (size_t index = 0; index < num_valid_ids; index++) {
1851314564Sdim        lldb::break_id_t bp_id =
1852314564Sdim            valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1853314564Sdim        BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1854360784Sdim        target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1855314564Sdim      }
1856314564Sdim    }
1857280031Sdim
1858314564Sdim    return true;
1859314564Sdim  }
1860280031Sdim
1861314564Sdimprivate:
1862314564Sdim  BreakpointNameOptionGroup m_name_options;
1863314564Sdim  OptionGroupOptions m_option_group;
1864314564Sdim};
1865280031Sdim
1866314564Sdimclass CommandObjectBreakpointNameList : public CommandObjectParsed {
1867314564Sdimpublic:
1868314564Sdim  CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1869314564Sdim      : CommandObjectParsed(interpreter, "list",
1870327952Sdim                            "List either the names for a breakpoint or info "
1871327952Sdim                            "about a given name.  With no arguments, lists all "
1872327952Sdim                            "names",
1873314564Sdim                            "breakpoint name list <command-options>"),
1874314564Sdim        m_name_options(), m_option_group() {
1875327952Sdim    m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1876314564Sdim    m_option_group.Finalize();
1877314564Sdim  }
1878314564Sdim
1879314564Sdim  ~CommandObjectBreakpointNameList() override = default;
1880314564Sdim
1881314564Sdim  Options *GetOptions() override { return &m_option_group; }
1882314564Sdim
1883314564Sdimprotected:
1884314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
1885360784Sdim    Target &target =
1886314564Sdim        GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1887314564Sdim
1888327952Sdim    std::vector<std::string> name_list;
1889327952Sdim    if (command.empty()) {
1890360784Sdim      target.GetBreakpointNames(name_list);
1891327952Sdim    } else {
1892360784Sdim      for (const Args::ArgEntry &arg : command) {
1893327952Sdim        name_list.push_back(arg.c_str());
1894327952Sdim      }
1895327952Sdim    }
1896360784Sdim
1897327952Sdim    if (name_list.empty()) {
1898327952Sdim      result.AppendMessage("No breakpoint names found.");
1899327952Sdim    } else {
1900327952Sdim      for (const std::string &name_str : name_list) {
1901327952Sdim        const char *name = name_str.c_str();
1902327952Sdim        // First print out the options for the name:
1903327952Sdim        Status error;
1904360784Sdim        BreakpointName *bp_name =
1905360784Sdim            target.FindBreakpointName(ConstString(name), false, error);
1906360784Sdim        if (bp_name) {
1907327952Sdim          StreamString s;
1908327952Sdim          result.AppendMessageWithFormat("Name: %s\n", name);
1909360784Sdim          if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1910327952Sdim            result.AppendMessage(s.GetString());
1911327952Sdim          }
1912360784Sdim
1913327952Sdim          std::unique_lock<std::recursive_mutex> lock;
1914360784Sdim          target.GetBreakpointList().GetListMutex(lock);
1915314564Sdim
1916360784Sdim          BreakpointList &breakpoints = target.GetBreakpointList();
1917327952Sdim          bool any_set = false;
1918327952Sdim          for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1919327952Sdim            if (bp_sp->MatchesName(name)) {
1920327952Sdim              StreamString s;
1921327952Sdim              any_set = true;
1922327952Sdim              bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1923327952Sdim              s.EOL();
1924327952Sdim              result.AppendMessage(s.GetString());
1925327952Sdim            }
1926327952Sdim          }
1927327952Sdim          if (!any_set)
1928327952Sdim            result.AppendMessage("No breakpoints using this name.");
1929327952Sdim        } else {
1930327952Sdim          result.AppendMessageWithFormat("Name: %s not found.\n", name);
1931280031Sdim        }
1932314564Sdim      }
1933280031Sdim    }
1934314564Sdim    return true;
1935314564Sdim  }
1936280031Sdim
1937280031Sdimprivate:
1938314564Sdim  BreakpointNameOptionGroup m_name_options;
1939314564Sdim  OptionGroupOptions m_option_group;
1940280031Sdim};
1941280031Sdim
1942314564Sdim// CommandObjectBreakpointName
1943314564Sdimclass CommandObjectBreakpointName : public CommandObjectMultiword {
1944280031Sdimpublic:
1945314564Sdim  CommandObjectBreakpointName(CommandInterpreter &interpreter)
1946314564Sdim      : CommandObjectMultiword(
1947314564Sdim            interpreter, "name", "Commands to manage name tags for breakpoints",
1948314564Sdim            "breakpoint name <subcommand> [<command-options>]") {
1949314564Sdim    CommandObjectSP add_command_object(
1950314564Sdim        new CommandObjectBreakpointNameAdd(interpreter));
1951314564Sdim    CommandObjectSP delete_command_object(
1952314564Sdim        new CommandObjectBreakpointNameDelete(interpreter));
1953314564Sdim    CommandObjectSP list_command_object(
1954314564Sdim        new CommandObjectBreakpointNameList(interpreter));
1955327952Sdim    CommandObjectSP configure_command_object(
1956327952Sdim        new CommandObjectBreakpointNameConfigure(interpreter));
1957314564Sdim
1958314564Sdim    LoadSubCommand("add", add_command_object);
1959314564Sdim    LoadSubCommand("delete", delete_command_object);
1960314564Sdim    LoadSubCommand("list", list_command_object);
1961327952Sdim    LoadSubCommand("configure", configure_command_object);
1962314564Sdim  }
1963314564Sdim
1964314564Sdim  ~CommandObjectBreakpointName() override = default;
1965314564Sdim};
1966314564Sdim
1967314564Sdim// CommandObjectBreakpointRead
1968314564Sdim#pragma mark Read::CommandOptions
1969360784Sdim#define LLDB_OPTIONS_breakpoint_read
1970360784Sdim#include "CommandOptions.inc"
1971314564Sdim
1972314564Sdim#pragma mark Read
1973314564Sdim
1974314564Sdimclass CommandObjectBreakpointRead : public CommandObjectParsed {
1975314564Sdimpublic:
1976314564Sdim  CommandObjectBreakpointRead(CommandInterpreter &interpreter)
1977314564Sdim      : CommandObjectParsed(interpreter, "breakpoint read",
1978314564Sdim                            "Read and set the breakpoints previously saved to "
1979314564Sdim                            "a file with \"breakpoint write\".  ",
1980314564Sdim                            nullptr),
1981314564Sdim        m_options() {
1982314564Sdim    CommandArgumentEntry arg;
1983314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1984314564Sdim                                      eArgTypeBreakpointIDRange);
1985314564Sdim    // Add the entry for the first argument for this command to the object's
1986314564Sdim    // arguments vector.
1987314564Sdim    m_arguments.push_back(arg);
1988314564Sdim  }
1989314564Sdim
1990314564Sdim  ~CommandObjectBreakpointRead() override = default;
1991314564Sdim
1992314564Sdim  Options *GetOptions() override { return &m_options; }
1993314564Sdim
1994314564Sdim  class CommandOptions : public Options {
1995314564Sdim  public:
1996314564Sdim    CommandOptions() : Options() {}
1997314564Sdim
1998314564Sdim    ~CommandOptions() override = default;
1999314564Sdim
2000321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2001321369Sdim                          ExecutionContext *execution_context) override {
2002321369Sdim      Status error;
2003314564Sdim      const int short_option = m_getopt_table[option_idx].val;
2004314564Sdim
2005314564Sdim      switch (short_option) {
2006314564Sdim      case 'f':
2007314564Sdim        m_filename.assign(option_arg);
2008314564Sdim        break;
2009314564Sdim      case 'N': {
2010321369Sdim        Status name_error;
2011314564Sdim        if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2012314564Sdim                                                  name_error)) {
2013314564Sdim          error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2014314564Sdim                                         name_error.AsCString());
2015314564Sdim        }
2016314564Sdim        m_names.push_back(option_arg);
2017314564Sdim        break;
2018314564Sdim      }
2019314564Sdim      default:
2020360784Sdim        llvm_unreachable("Unimplemented option");
2021314564Sdim      }
2022314564Sdim
2023314564Sdim      return error;
2024280031Sdim    }
2025280031Sdim
2026314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
2027314564Sdim      m_filename.clear();
2028314564Sdim      m_names.clear();
2029314564Sdim    }
2030280031Sdim
2031314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2032314564Sdim      return llvm::makeArrayRef(g_breakpoint_read_options);
2033309124Sdim    }
2034309124Sdim
2035314564Sdim    // Instance variables to hold the values for command options.
2036314564Sdim
2037314564Sdim    std::string m_filename;
2038314564Sdim    std::vector<std::string> m_names;
2039314564Sdim  };
2040314564Sdim
2041280031Sdimprotected:
2042314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
2043360784Sdim    Target &target = GetSelectedOrDummyTarget();
2044280031Sdim
2045314564Sdim    std::unique_lock<std::recursive_mutex> lock;
2046360784Sdim    target.GetBreakpointList().GetListMutex(lock);
2047280031Sdim
2048344779Sdim    FileSpec input_spec(m_options.m_filename);
2049344779Sdim    FileSystem::Instance().Resolve(input_spec);
2050314564Sdim    BreakpointIDList new_bps;
2051360784Sdim    Status error = target.CreateBreakpointsFromFile(input_spec,
2052360784Sdim                                                    m_options.m_names, new_bps);
2053309124Sdim
2054314564Sdim    if (!error.Success()) {
2055314564Sdim      result.AppendError(error.AsCString());
2056314564Sdim      result.SetStatus(eReturnStatusFailed);
2057314564Sdim      return false;
2058314564Sdim    }
2059280031Sdim
2060314564Sdim    Stream &output_stream = result.GetOutputStream();
2061314564Sdim
2062314564Sdim    size_t num_breakpoints = new_bps.GetSize();
2063314564Sdim    if (num_breakpoints == 0) {
2064314564Sdim      result.AppendMessage("No breakpoints added.");
2065314564Sdim    } else {
2066314564Sdim      // No breakpoint selected; show info about all currently set breakpoints.
2067314564Sdim      result.AppendMessage("New breakpoints:");
2068314564Sdim      for (size_t i = 0; i < num_breakpoints; ++i) {
2069314564Sdim        BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2070360784Sdim        Breakpoint *bp = target.GetBreakpointList()
2071314564Sdim                             .FindBreakpointByID(bp_id.GetBreakpointID())
2072314564Sdim                             .get();
2073314564Sdim        if (bp)
2074314564Sdim          bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2075314564Sdim                             false);
2076314564Sdim      }
2077280031Sdim    }
2078314564Sdim    return result.Succeeded();
2079314564Sdim  }
2080280031Sdim
2081280031Sdimprivate:
2082314564Sdim  CommandOptions m_options;
2083280031Sdim};
2084280031Sdim
2085314564Sdim// CommandObjectBreakpointWrite
2086314564Sdim#pragma mark Write::CommandOptions
2087360784Sdim#define LLDB_OPTIONS_breakpoint_write
2088360784Sdim#include "CommandOptions.inc"
2089314564Sdim
2090314564Sdim#pragma mark Write
2091314564Sdimclass CommandObjectBreakpointWrite : public CommandObjectParsed {
2092280031Sdimpublic:
2093314564Sdim  CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2094314564Sdim      : CommandObjectParsed(interpreter, "breakpoint write",
2095314564Sdim                            "Write the breakpoints listed to a file that can "
2096314564Sdim                            "be read in with \"breakpoint read\".  "
2097314564Sdim                            "If given no arguments, writes all breakpoints.",
2098314564Sdim                            nullptr),
2099314564Sdim        m_options() {
2100314564Sdim    CommandArgumentEntry arg;
2101314564Sdim    CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2102314564Sdim                                      eArgTypeBreakpointIDRange);
2103314564Sdim    // Add the entry for the first argument for this command to the object's
2104314564Sdim    // arguments vector.
2105314564Sdim    m_arguments.push_back(arg);
2106314564Sdim  }
2107280031Sdim
2108314564Sdim  ~CommandObjectBreakpointWrite() override = default;
2109314564Sdim
2110314564Sdim  Options *GetOptions() override { return &m_options; }
2111314564Sdim
2112314564Sdim  class CommandOptions : public Options {
2113314564Sdim  public:
2114314564Sdim    CommandOptions() : Options() {}
2115314564Sdim
2116314564Sdim    ~CommandOptions() override = default;
2117314564Sdim
2118321369Sdim    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2119321369Sdim                          ExecutionContext *execution_context) override {
2120321369Sdim      Status error;
2121314564Sdim      const int short_option = m_getopt_table[option_idx].val;
2122314564Sdim
2123314564Sdim      switch (short_option) {
2124314564Sdim      case 'f':
2125314564Sdim        m_filename.assign(option_arg);
2126314564Sdim        break;
2127314564Sdim      case 'a':
2128314564Sdim        m_append = true;
2129314564Sdim        break;
2130314564Sdim      default:
2131360784Sdim        llvm_unreachable("Unimplemented option");
2132314564Sdim      }
2133314564Sdim
2134314564Sdim      return error;
2135280031Sdim    }
2136280031Sdim
2137314564Sdim    void OptionParsingStarting(ExecutionContext *execution_context) override {
2138314564Sdim      m_filename.clear();
2139314564Sdim      m_append = false;
2140314564Sdim    }
2141314564Sdim
2142314564Sdim    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2143314564Sdim      return llvm::makeArrayRef(g_breakpoint_write_options);
2144314564Sdim    }
2145314564Sdim
2146314564Sdim    // Instance variables to hold the values for command options.
2147314564Sdim
2148314564Sdim    std::string m_filename;
2149314564Sdim    bool m_append = false;
2150314564Sdim  };
2151314564Sdim
2152314564Sdimprotected:
2153314564Sdim  bool DoExecute(Args &command, CommandReturnObject &result) override {
2154360784Sdim    Target &target = GetSelectedOrDummyTarget();
2155314564Sdim
2156314564Sdim    std::unique_lock<std::recursive_mutex> lock;
2157360784Sdim    target.GetBreakpointList().GetListMutex(lock);
2158314564Sdim
2159314564Sdim    BreakpointIDList valid_bp_ids;
2160314564Sdim    if (!command.empty()) {
2161314564Sdim      CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2162360784Sdim          command, &target, result, &valid_bp_ids,
2163327952Sdim          BreakpointName::Permissions::PermissionKinds::listPerm);
2164314564Sdim
2165314564Sdim      if (!result.Succeeded()) {
2166314564Sdim        result.SetStatus(eReturnStatusFailed);
2167314564Sdim        return false;
2168314564Sdim      }
2169314564Sdim    }
2170344779Sdim    FileSpec file_spec(m_options.m_filename);
2171344779Sdim    FileSystem::Instance().Resolve(file_spec);
2172360784Sdim    Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2173360784Sdim                                                     m_options.m_append);
2174314564Sdim    if (!error.Success()) {
2175314564Sdim      result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2176314564Sdim                                   error.AsCString());
2177314564Sdim      result.SetStatus(eReturnStatusFailed);
2178314564Sdim    }
2179314564Sdim    return result.Succeeded();
2180314564Sdim  }
2181314564Sdim
2182314564Sdimprivate:
2183314564Sdim  CommandOptions m_options;
2184280031Sdim};
2185280031Sdim
2186280031Sdim// CommandObjectMultiwordBreakpoint
2187254721Semaste#pragma mark MultiwordBreakpoint
2188254721Semaste
2189314564SdimCommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2190314564Sdim    CommandInterpreter &interpreter)
2191314564Sdim    : CommandObjectMultiword(
2192314564Sdim          interpreter, "breakpoint",
2193314564Sdim          "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2194314564Sdim          "breakpoint <subcommand> [<command-options>]") {
2195314564Sdim  CommandObjectSP list_command_object(
2196314564Sdim      new CommandObjectBreakpointList(interpreter));
2197314564Sdim  CommandObjectSP enable_command_object(
2198314564Sdim      new CommandObjectBreakpointEnable(interpreter));
2199314564Sdim  CommandObjectSP disable_command_object(
2200314564Sdim      new CommandObjectBreakpointDisable(interpreter));
2201314564Sdim  CommandObjectSP clear_command_object(
2202314564Sdim      new CommandObjectBreakpointClear(interpreter));
2203314564Sdim  CommandObjectSP delete_command_object(
2204314564Sdim      new CommandObjectBreakpointDelete(interpreter));
2205314564Sdim  CommandObjectSP set_command_object(
2206314564Sdim      new CommandObjectBreakpointSet(interpreter));
2207314564Sdim  CommandObjectSP command_command_object(
2208314564Sdim      new CommandObjectBreakpointCommand(interpreter));
2209314564Sdim  CommandObjectSP modify_command_object(
2210314564Sdim      new CommandObjectBreakpointModify(interpreter));
2211314564Sdim  CommandObjectSP name_command_object(
2212314564Sdim      new CommandObjectBreakpointName(interpreter));
2213314564Sdim  CommandObjectSP write_command_object(
2214314564Sdim      new CommandObjectBreakpointWrite(interpreter));
2215314564Sdim  CommandObjectSP read_command_object(
2216314564Sdim      new CommandObjectBreakpointRead(interpreter));
2217254721Semaste
2218314564Sdim  list_command_object->SetCommandName("breakpoint list");
2219314564Sdim  enable_command_object->SetCommandName("breakpoint enable");
2220314564Sdim  disable_command_object->SetCommandName("breakpoint disable");
2221314564Sdim  clear_command_object->SetCommandName("breakpoint clear");
2222314564Sdim  delete_command_object->SetCommandName("breakpoint delete");
2223314564Sdim  set_command_object->SetCommandName("breakpoint set");
2224314564Sdim  command_command_object->SetCommandName("breakpoint command");
2225314564Sdim  modify_command_object->SetCommandName("breakpoint modify");
2226314564Sdim  name_command_object->SetCommandName("breakpoint name");
2227314564Sdim  write_command_object->SetCommandName("breakpoint write");
2228314564Sdim  read_command_object->SetCommandName("breakpoint read");
2229254721Semaste
2230314564Sdim  LoadSubCommand("list", list_command_object);
2231314564Sdim  LoadSubCommand("enable", enable_command_object);
2232314564Sdim  LoadSubCommand("disable", disable_command_object);
2233314564Sdim  LoadSubCommand("clear", clear_command_object);
2234314564Sdim  LoadSubCommand("delete", delete_command_object);
2235314564Sdim  LoadSubCommand("set", set_command_object);
2236314564Sdim  LoadSubCommand("command", command_command_object);
2237314564Sdim  LoadSubCommand("modify", modify_command_object);
2238314564Sdim  LoadSubCommand("name", name_command_object);
2239314564Sdim  LoadSubCommand("write", write_command_object);
2240314564Sdim  LoadSubCommand("read", read_command_object);
2241254721Semaste}
2242254721Semaste
2243309124SdimCommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2244254721Semaste
2245360784Sdimvoid CommandObjectMultiwordBreakpoint::VerifyIDs(
2246360784Sdim    Args &args, Target *target, bool allow_locations,
2247360784Sdim    CommandReturnObject &result, BreakpointIDList *valid_ids,
2248360784Sdim    BreakpointName::Permissions ::PermissionKinds purpose) {
2249314564Sdim  // args can be strings representing 1). integers (for breakpoint ids)
2250314564Sdim  //                                  2). the full breakpoint & location
2251314564Sdim  //                                  canonical representation
2252314564Sdim  //                                  3). the word "to" or a hyphen,
2253314564Sdim  //                                  representing a range (in which case there
2254314564Sdim  //                                      had *better* be an entry both before &
2255314564Sdim  //                                      after of one of the first two types.
2256314564Sdim  //                                  4). A breakpoint name
2257314564Sdim  // If args is empty, we will use the last created breakpoint (if there is
2258314564Sdim  // one.)
2259254721Semaste
2260314564Sdim  Args temp_args;
2261254721Semaste
2262314564Sdim  if (args.empty()) {
2263314564Sdim    if (target->GetLastCreatedBreakpoint()) {
2264314564Sdim      valid_ids->AddBreakpointID(BreakpointID(
2265314564Sdim          target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2266314564Sdim      result.SetStatus(eReturnStatusSuccessFinishNoResult);
2267314564Sdim    } else {
2268314564Sdim      result.AppendError(
2269314564Sdim          "No breakpoint specified and no last created breakpoint.");
2270314564Sdim      result.SetStatus(eReturnStatusFailed);
2271254721Semaste    }
2272314564Sdim    return;
2273314564Sdim  }
2274254721Semaste
2275314564Sdim  // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2276341825Sdim  // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
2277341825Sdim  // id range strings over; instead generate a list of strings for all the
2278341825Sdim  // breakpoint ids in the range, and shove all of those breakpoint id strings
2279341825Sdim  // into TEMP_ARGS.
2280254721Semaste
2281360784Sdim  BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2282327952Sdim                                           purpose, result, temp_args);
2283254721Semaste
2284314564Sdim  // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2285314564Sdim  // BreakpointIDList:
2286254721Semaste
2287341825Sdim  valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2288254721Semaste
2289341825Sdim  // At this point,  all of the breakpoint ids that the user passed in have
2290341825Sdim  // been converted to breakpoint IDs and put into valid_ids.
2291254721Semaste
2292314564Sdim  if (result.Succeeded()) {
2293314564Sdim    // Now that we've converted everything from args into a list of breakpoint
2294341825Sdim    // ids, go through our tentative list of breakpoint id's and verify that
2295341825Sdim    // they correspond to valid/currently set breakpoints.
2296314564Sdim
2297314564Sdim    const size_t count = valid_ids->GetSize();
2298314564Sdim    for (size_t i = 0; i < count; ++i) {
2299314564Sdim      BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2300314564Sdim      Breakpoint *breakpoint =
2301314564Sdim          target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2302314564Sdim      if (breakpoint != nullptr) {
2303314564Sdim        const size_t num_locations = breakpoint->GetNumLocations();
2304314564Sdim        if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2305314564Sdim          StreamString id_str;
2306314564Sdim          BreakpointID::GetCanonicalReference(
2307314564Sdim              &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2308314564Sdim          i = valid_ids->GetSize() + 1;
2309314564Sdim          result.AppendErrorWithFormat(
2310314564Sdim              "'%s' is not a currently valid breakpoint/location id.\n",
2311314564Sdim              id_str.GetData());
2312314564Sdim          result.SetStatus(eReturnStatusFailed);
2313254721Semaste        }
2314314564Sdim      } else {
2315314564Sdim        i = valid_ids->GetSize() + 1;
2316314564Sdim        result.AppendErrorWithFormat(
2317314564Sdim            "'%d' is not a currently valid breakpoint ID.\n",
2318314564Sdim            cur_bp_id.GetBreakpointID());
2319314564Sdim        result.SetStatus(eReturnStatusFailed);
2320314564Sdim      }
2321254721Semaste    }
2322314564Sdim  }
2323254721Semaste}
2324