15ffd83dbSDimitry Andric //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "CommandObjectBreakpoint.h"
100b57cec5SDimitry Andric #include "CommandObjectBreakpointCommand.h"
110b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
120b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h"
130b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
140b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
150b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
160b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
170b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
189dba64beSDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h"
20af732203SDimitry Andric #include "lldb/Interpreter/OptionValueFileColonLine.h"
210b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueString.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueUInt64.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
240b57cec5SDimitry Andric #include "lldb/Target/Language.h"
250b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
260b57cec5SDimitry Andric #include "lldb/Target/Target.h"
270b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h"
280b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
290b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #include <memory>
320b57cec5SDimitry Andric #include <vector>
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace lldb;
350b57cec5SDimitry Andric using namespace lldb_private;
360b57cec5SDimitry Andric 
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)370b57cec5SDimitry Andric static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
380b57cec5SDimitry Andric                                      lldb::DescriptionLevel level) {
390b57cec5SDimitry Andric   s->IndentMore();
400b57cec5SDimitry Andric   bp->GetDescription(s, level, true);
410b57cec5SDimitry Andric   s->IndentLess();
420b57cec5SDimitry Andric   s->EOL();
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Modifiable Breakpoint Options
460b57cec5SDimitry Andric #pragma mark Modify::CommandOptions
479dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_modify
489dba64beSDimitry Andric #include "CommandOptions.inc"
499dba64beSDimitry Andric 
50480093f4SDimitry Andric class lldb_private::BreakpointOptionGroup : public OptionGroup {
510b57cec5SDimitry Andric public:
BreakpointOptionGroup()52480093f4SDimitry Andric   BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   ~BreakpointOptionGroup() override = default;
550b57cec5SDimitry Andric 
GetDefinitions()560b57cec5SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
570b57cec5SDimitry Andric     return llvm::makeArrayRef(g_breakpoint_modify_options);
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)600b57cec5SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
610b57cec5SDimitry Andric                         ExecutionContext *execution_context) override {
620b57cec5SDimitry Andric     Status error;
63480093f4SDimitry Andric     const int short_option =
64480093f4SDimitry Andric         g_breakpoint_modify_options[option_idx].short_option;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     switch (short_option) {
670b57cec5SDimitry Andric     case 'c':
680b57cec5SDimitry Andric       // Normally an empty breakpoint condition marks is as unset. But we need
690b57cec5SDimitry Andric       // to say it was passed in.
700b57cec5SDimitry Andric       m_bp_opts.SetCondition(option_arg.str().c_str());
710b57cec5SDimitry Andric       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
720b57cec5SDimitry Andric       break;
730b57cec5SDimitry Andric     case 'C':
745ffd83dbSDimitry Andric       m_commands.push_back(std::string(option_arg));
750b57cec5SDimitry Andric       break;
760b57cec5SDimitry Andric     case 'd':
770b57cec5SDimitry Andric       m_bp_opts.SetEnabled(false);
780b57cec5SDimitry Andric       break;
790b57cec5SDimitry Andric     case 'e':
800b57cec5SDimitry Andric       m_bp_opts.SetEnabled(true);
810b57cec5SDimitry Andric       break;
820b57cec5SDimitry Andric     case 'G': {
830b57cec5SDimitry Andric       bool value, success;
840b57cec5SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
850b57cec5SDimitry Andric       if (success) {
860b57cec5SDimitry Andric         m_bp_opts.SetAutoContinue(value);
870b57cec5SDimitry Andric       } else
880b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
890b57cec5SDimitry Andric             "invalid boolean value '%s' passed for -G option",
900b57cec5SDimitry Andric             option_arg.str().c_str());
91480093f4SDimitry Andric     } break;
92480093f4SDimitry Andric     case 'i': {
930b57cec5SDimitry Andric       uint32_t ignore_count;
940b57cec5SDimitry Andric       if (option_arg.getAsInteger(0, ignore_count))
950b57cec5SDimitry Andric         error.SetErrorStringWithFormat("invalid ignore count '%s'",
960b57cec5SDimitry Andric                                        option_arg.str().c_str());
970b57cec5SDimitry Andric       else
980b57cec5SDimitry Andric         m_bp_opts.SetIgnoreCount(ignore_count);
99480093f4SDimitry Andric     } break;
1000b57cec5SDimitry Andric     case 'o': {
1010b57cec5SDimitry Andric       bool value, success;
1020b57cec5SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1030b57cec5SDimitry Andric       if (success) {
1040b57cec5SDimitry Andric         m_bp_opts.SetOneShot(value);
1050b57cec5SDimitry Andric       } else
1060b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
1070b57cec5SDimitry Andric             "invalid boolean value '%s' passed for -o option",
1080b57cec5SDimitry Andric             option_arg.str().c_str());
1090b57cec5SDimitry Andric     } break;
110480093f4SDimitry Andric     case 't': {
1110b57cec5SDimitry Andric       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
1120b57cec5SDimitry Andric       if (option_arg[0] != '\0') {
1130b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, thread_id))
1140b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid thread id string '%s'",
1150b57cec5SDimitry Andric                                          option_arg.str().c_str());
1160b57cec5SDimitry Andric       }
1170b57cec5SDimitry Andric       m_bp_opts.SetThreadID(thread_id);
118480093f4SDimitry Andric     } break;
1190b57cec5SDimitry Andric     case 'T':
1200b57cec5SDimitry Andric       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
1210b57cec5SDimitry Andric       break;
1220b57cec5SDimitry Andric     case 'q':
1230b57cec5SDimitry Andric       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
1240b57cec5SDimitry Andric       break;
125480093f4SDimitry Andric     case 'x': {
1260b57cec5SDimitry Andric       uint32_t thread_index = UINT32_MAX;
1270b57cec5SDimitry Andric       if (option_arg[0] != '\n') {
1280b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, thread_index))
1290b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid thread index string '%s'",
1300b57cec5SDimitry Andric                                          option_arg.str().c_str());
1310b57cec5SDimitry Andric       }
1320b57cec5SDimitry Andric       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
133480093f4SDimitry Andric     } break;
1340b57cec5SDimitry Andric     default:
1359dba64beSDimitry Andric       llvm_unreachable("Unimplemented option");
1360b57cec5SDimitry Andric     }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     return error;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1410b57cec5SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
1420b57cec5SDimitry Andric     m_bp_opts.Clear();
1430b57cec5SDimitry Andric     m_commands.clear();
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric 
OptionParsingFinished(ExecutionContext * execution_context)1460b57cec5SDimitry Andric   Status OptionParsingFinished(ExecutionContext *execution_context) override {
147480093f4SDimitry Andric     if (!m_commands.empty()) {
1489dba64beSDimitry Andric       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric       for (std::string &str : m_commands)
1510b57cec5SDimitry Andric         cmd_data->user_source.AppendString(str);
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric       cmd_data->stop_on_error = true;
1540b57cec5SDimitry Andric       m_bp_opts.SetCommandDataCallback(cmd_data);
1550b57cec5SDimitry Andric     }
1560b57cec5SDimitry Andric     return Status();
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
GetBreakpointOptions()159480093f4SDimitry Andric   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   std::vector<std::string> m_commands;
1620b57cec5SDimitry Andric   BreakpointOptions m_bp_opts;
1630b57cec5SDimitry Andric };
1649dba64beSDimitry Andric 
1659dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_dummy
1669dba64beSDimitry Andric #include "CommandOptions.inc"
1670b57cec5SDimitry Andric 
168480093f4SDimitry Andric class BreakpointDummyOptionGroup : public OptionGroup {
1690b57cec5SDimitry Andric public:
BreakpointDummyOptionGroup()170480093f4SDimitry Andric   BreakpointDummyOptionGroup() : OptionGroup() {}
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   ~BreakpointDummyOptionGroup() override = default;
1730b57cec5SDimitry Andric 
GetDefinitions()1740b57cec5SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1750b57cec5SDimitry Andric     return llvm::makeArrayRef(g_breakpoint_dummy_options);
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1780b57cec5SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1790b57cec5SDimitry Andric                         ExecutionContext *execution_context) override {
1800b57cec5SDimitry Andric     Status error;
181480093f4SDimitry Andric     const int short_option =
182480093f4SDimitry Andric         g_breakpoint_dummy_options[option_idx].short_option;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric     switch (short_option) {
1850b57cec5SDimitry Andric     case 'D':
1860b57cec5SDimitry Andric       m_use_dummy = true;
1870b57cec5SDimitry Andric       break;
1880b57cec5SDimitry Andric     default:
1899dba64beSDimitry Andric       llvm_unreachable("Unimplemented option");
1900b57cec5SDimitry Andric     }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     return error;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1950b57cec5SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
1960b57cec5SDimitry Andric     m_use_dummy = false;
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   bool m_use_dummy;
2000b57cec5SDimitry Andric };
2010b57cec5SDimitry Andric 
2029dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_set
2039dba64beSDimitry Andric #include "CommandOptions.inc"
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric // CommandObjectBreakpointSet
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric class CommandObjectBreakpointSet : public CommandObjectParsed {
2080b57cec5SDimitry Andric public:
2090b57cec5SDimitry Andric   enum BreakpointSetType {
2100b57cec5SDimitry Andric     eSetTypeInvalid,
2110b57cec5SDimitry Andric     eSetTypeFileAndLine,
2120b57cec5SDimitry Andric     eSetTypeAddress,
2130b57cec5SDimitry Andric     eSetTypeFunctionName,
2140b57cec5SDimitry Andric     eSetTypeFunctionRegexp,
2150b57cec5SDimitry Andric     eSetTypeSourceRegexp,
2160b57cec5SDimitry Andric     eSetTypeException,
2170b57cec5SDimitry Andric     eSetTypeScripted,
2180b57cec5SDimitry Andric   };
2190b57cec5SDimitry Andric 
CommandObjectBreakpointSet(CommandInterpreter & interpreter)2200b57cec5SDimitry Andric   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
2210b57cec5SDimitry Andric       : CommandObjectParsed(
2220b57cec5SDimitry Andric             interpreter, "breakpoint set",
2230b57cec5SDimitry Andric             "Sets a breakpoint or set of breakpoints in the executable.",
2240b57cec5SDimitry Andric             "breakpoint set <cmd-options>"),
225480093f4SDimitry Andric         m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
2269dba64beSDimitry Andric         m_options() {
2270b57cec5SDimitry Andric     // We're picking up all the normal options, commands and disable.
228480093f4SDimitry Andric     m_all_options.Append(&m_python_class_options,
229480093f4SDimitry Andric                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
2300b57cec5SDimitry Andric     m_all_options.Append(&m_bp_opts,
2310b57cec5SDimitry Andric                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
2320b57cec5SDimitry Andric                          LLDB_OPT_SET_ALL);
2330b57cec5SDimitry Andric     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2340b57cec5SDimitry Andric     m_all_options.Append(&m_options);
2350b57cec5SDimitry Andric     m_all_options.Finalize();
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   ~CommandObjectBreakpointSet() override = default;
2390b57cec5SDimitry Andric 
GetOptions()2400b57cec5SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   class CommandOptions : public OptionGroup {
2430b57cec5SDimitry Andric   public:
CommandOptions()2440b57cec5SDimitry Andric     CommandOptions()
245*5f7ddb14SDimitry Andric         : OptionGroup(), m_condition(), m_filenames(), m_func_names(),
246*5f7ddb14SDimitry Andric           m_func_regexp(), m_source_text_regexp(), m_modules() {}
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric     ~CommandOptions() override = default;
2490b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2500b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2510b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
2520b57cec5SDimitry Andric       Status error;
253480093f4SDimitry Andric       const int short_option =
254480093f4SDimitry Andric           g_breakpoint_set_options[option_idx].short_option;
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric       switch (short_option) {
2570b57cec5SDimitry Andric       case 'a': {
2580b57cec5SDimitry Andric         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
2590b57cec5SDimitry Andric                                                  LLDB_INVALID_ADDRESS, &error);
2600b57cec5SDimitry Andric       } break;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric       case 'A':
2630b57cec5SDimitry Andric         m_all_files = true;
2640b57cec5SDimitry Andric         break;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric       case 'b':
2675ffd83dbSDimitry Andric         m_func_names.push_back(std::string(option_arg));
2680b57cec5SDimitry Andric         m_func_name_type_mask |= eFunctionNameTypeBase;
2690b57cec5SDimitry Andric         break;
2700b57cec5SDimitry Andric 
2715ffd83dbSDimitry Andric       case 'u':
2720b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_column))
2730b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid column number: %s",
2740b57cec5SDimitry Andric                                          option_arg.str().c_str());
2750b57cec5SDimitry Andric         break;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       case 'E': {
2780b57cec5SDimitry Andric         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric         switch (language) {
2810b57cec5SDimitry Andric         case eLanguageTypeC89:
2820b57cec5SDimitry Andric         case eLanguageTypeC:
2830b57cec5SDimitry Andric         case eLanguageTypeC99:
2840b57cec5SDimitry Andric         case eLanguageTypeC11:
2850b57cec5SDimitry Andric           m_exception_language = eLanguageTypeC;
2860b57cec5SDimitry Andric           break;
2870b57cec5SDimitry Andric         case eLanguageTypeC_plus_plus:
2880b57cec5SDimitry Andric         case eLanguageTypeC_plus_plus_03:
2890b57cec5SDimitry Andric         case eLanguageTypeC_plus_plus_11:
2900b57cec5SDimitry Andric         case eLanguageTypeC_plus_plus_14:
2910b57cec5SDimitry Andric           m_exception_language = eLanguageTypeC_plus_plus;
2920b57cec5SDimitry Andric           break;
2930b57cec5SDimitry Andric         case eLanguageTypeObjC:
2940b57cec5SDimitry Andric           m_exception_language = eLanguageTypeObjC;
2950b57cec5SDimitry Andric           break;
2960b57cec5SDimitry Andric         case eLanguageTypeObjC_plus_plus:
2970b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
2980b57cec5SDimitry Andric               "Set exception breakpoints separately for c++ and objective-c");
2990b57cec5SDimitry Andric           break;
3000b57cec5SDimitry Andric         case eLanguageTypeUnknown:
3010b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3020b57cec5SDimitry Andric               "Unknown language type: '%s' for exception breakpoint",
3030b57cec5SDimitry Andric               option_arg.str().c_str());
3040b57cec5SDimitry Andric           break;
3050b57cec5SDimitry Andric         default:
3060b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3070b57cec5SDimitry Andric               "Unsupported language type: '%s' for exception breakpoint",
3080b57cec5SDimitry Andric               option_arg.str().c_str());
3090b57cec5SDimitry Andric         }
3100b57cec5SDimitry Andric       } break;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric       case 'f':
3130b57cec5SDimitry Andric         m_filenames.AppendIfUnique(FileSpec(option_arg));
3140b57cec5SDimitry Andric         break;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric       case 'F':
3175ffd83dbSDimitry Andric         m_func_names.push_back(std::string(option_arg));
3180b57cec5SDimitry Andric         m_func_name_type_mask |= eFunctionNameTypeFull;
3190b57cec5SDimitry Andric         break;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric       case 'h': {
3220b57cec5SDimitry Andric         bool success;
3230b57cec5SDimitry Andric         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
3240b57cec5SDimitry Andric         if (!success)
3250b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3260b57cec5SDimitry Andric               "Invalid boolean value for on-catch option: '%s'",
3270b57cec5SDimitry Andric               option_arg.str().c_str());
3280b57cec5SDimitry Andric       } break;
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric       case 'H':
3310b57cec5SDimitry Andric         m_hardware = true;
3320b57cec5SDimitry Andric         break;
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric       case 'K': {
3350b57cec5SDimitry Andric         bool success;
3360b57cec5SDimitry Andric         bool value;
3370b57cec5SDimitry Andric         value = OptionArgParser::ToBoolean(option_arg, true, &success);
3380b57cec5SDimitry Andric         if (value)
3390b57cec5SDimitry Andric           m_skip_prologue = eLazyBoolYes;
3400b57cec5SDimitry Andric         else
3410b57cec5SDimitry Andric           m_skip_prologue = eLazyBoolNo;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric         if (!success)
3440b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3450b57cec5SDimitry Andric               "Invalid boolean value for skip prologue option: '%s'",
3460b57cec5SDimitry Andric               option_arg.str().c_str());
3470b57cec5SDimitry Andric       } break;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric       case 'l':
3500b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_line_num))
3510b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid line number: %s.",
3520b57cec5SDimitry Andric                                          option_arg.str().c_str());
3530b57cec5SDimitry Andric         break;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric       case 'L':
3560b57cec5SDimitry Andric         m_language = Language::GetLanguageTypeFromString(option_arg);
3570b57cec5SDimitry Andric         if (m_language == eLanguageTypeUnknown)
3580b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3590b57cec5SDimitry Andric               "Unknown language type: '%s' for breakpoint",
3600b57cec5SDimitry Andric               option_arg.str().c_str());
3610b57cec5SDimitry Andric         break;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric       case 'm': {
3640b57cec5SDimitry Andric         bool success;
3650b57cec5SDimitry Andric         bool value;
3660b57cec5SDimitry Andric         value = OptionArgParser::ToBoolean(option_arg, true, &success);
3670b57cec5SDimitry Andric         if (value)
3680b57cec5SDimitry Andric           m_move_to_nearest_code = eLazyBoolYes;
3690b57cec5SDimitry Andric         else
3700b57cec5SDimitry Andric           m_move_to_nearest_code = eLazyBoolNo;
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric         if (!success)
3730b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
3740b57cec5SDimitry Andric               "Invalid boolean value for move-to-nearest-code option: '%s'",
3750b57cec5SDimitry Andric               option_arg.str().c_str());
3760b57cec5SDimitry Andric         break;
3770b57cec5SDimitry Andric       }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric       case 'M':
3805ffd83dbSDimitry Andric         m_func_names.push_back(std::string(option_arg));
3810b57cec5SDimitry Andric         m_func_name_type_mask |= eFunctionNameTypeMethod;
3820b57cec5SDimitry Andric         break;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric       case 'n':
3855ffd83dbSDimitry Andric         m_func_names.push_back(std::string(option_arg));
3860b57cec5SDimitry Andric         m_func_name_type_mask |= eFunctionNameTypeAuto;
3870b57cec5SDimitry Andric         break;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric       case 'N': {
3900b57cec5SDimitry Andric         if (BreakpointID::StringIsBreakpointName(option_arg, error))
3915ffd83dbSDimitry Andric           m_breakpoint_names.push_back(std::string(option_arg));
3920b57cec5SDimitry Andric         else
3930b57cec5SDimitry Andric           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
3940b57cec5SDimitry Andric                                          option_arg.str().c_str());
3950b57cec5SDimitry Andric         break;
3960b57cec5SDimitry Andric       }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric       case 'R': {
3990b57cec5SDimitry Andric         lldb::addr_t tmp_offset_addr;
4000b57cec5SDimitry Andric         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
4010b57cec5SDimitry Andric                                                      option_arg, 0, &error);
4020b57cec5SDimitry Andric         if (error.Success())
4030b57cec5SDimitry Andric           m_offset_addr = tmp_offset_addr;
4040b57cec5SDimitry Andric       } break;
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric       case 'O':
4070b57cec5SDimitry Andric         m_exception_extra_args.AppendArgument("-O");
4080b57cec5SDimitry Andric         m_exception_extra_args.AppendArgument(option_arg);
4090b57cec5SDimitry Andric         break;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric       case 'p':
4125ffd83dbSDimitry Andric         m_source_text_regexp.assign(std::string(option_arg));
4130b57cec5SDimitry Andric         break;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric       case 'r':
4165ffd83dbSDimitry Andric         m_func_regexp.assign(std::string(option_arg));
4170b57cec5SDimitry Andric         break;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric       case 's':
4200b57cec5SDimitry Andric         m_modules.AppendIfUnique(FileSpec(option_arg));
4210b57cec5SDimitry Andric         break;
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric       case 'S':
4245ffd83dbSDimitry Andric         m_func_names.push_back(std::string(option_arg));
4250b57cec5SDimitry Andric         m_func_name_type_mask |= eFunctionNameTypeSelector;
4260b57cec5SDimitry Andric         break;
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric       case 'w': {
4290b57cec5SDimitry Andric         bool success;
4300b57cec5SDimitry Andric         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
4310b57cec5SDimitry Andric         if (!success)
4320b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
4330b57cec5SDimitry Andric               "Invalid boolean value for on-throw option: '%s'",
4340b57cec5SDimitry Andric               option_arg.str().c_str());
4350b57cec5SDimitry Andric       } break;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric       case 'X':
4385ffd83dbSDimitry Andric         m_source_regex_func_names.insert(std::string(option_arg));
4390b57cec5SDimitry Andric         break;
4400b57cec5SDimitry Andric 
441af732203SDimitry Andric       case 'y':
442af732203SDimitry Andric       {
443af732203SDimitry Andric         OptionValueFileColonLine value;
444af732203SDimitry Andric         Status fcl_err = value.SetValueFromString(option_arg);
445af732203SDimitry Andric         if (!fcl_err.Success()) {
446af732203SDimitry Andric           error.SetErrorStringWithFormat(
447af732203SDimitry Andric               "Invalid value for file:line specifier: %s",
448af732203SDimitry Andric               fcl_err.AsCString());
449af732203SDimitry Andric         } else {
450af732203SDimitry Andric           m_filenames.AppendIfUnique(value.GetFileSpec());
451af732203SDimitry Andric           m_line_num = value.GetLineNumber();
452af732203SDimitry Andric           m_column = value.GetColumnNumber();
453af732203SDimitry Andric         }
454af732203SDimitry Andric       } break;
455af732203SDimitry Andric 
4560b57cec5SDimitry Andric       default:
4579dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
4580b57cec5SDimitry Andric       }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric       return error;
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)4630b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
4640b57cec5SDimitry Andric       m_filenames.Clear();
4650b57cec5SDimitry Andric       m_line_num = 0;
4660b57cec5SDimitry Andric       m_column = 0;
4670b57cec5SDimitry Andric       m_func_names.clear();
4680b57cec5SDimitry Andric       m_func_name_type_mask = eFunctionNameTypeNone;
4690b57cec5SDimitry Andric       m_func_regexp.clear();
4700b57cec5SDimitry Andric       m_source_text_regexp.clear();
4710b57cec5SDimitry Andric       m_modules.Clear();
4720b57cec5SDimitry Andric       m_load_addr = LLDB_INVALID_ADDRESS;
4730b57cec5SDimitry Andric       m_offset_addr = 0;
4740b57cec5SDimitry Andric       m_catch_bp = false;
4750b57cec5SDimitry Andric       m_throw_bp = true;
4760b57cec5SDimitry Andric       m_hardware = false;
4770b57cec5SDimitry Andric       m_exception_language = eLanguageTypeUnknown;
4780b57cec5SDimitry Andric       m_language = lldb::eLanguageTypeUnknown;
4790b57cec5SDimitry Andric       m_skip_prologue = eLazyBoolCalculate;
4800b57cec5SDimitry Andric       m_breakpoint_names.clear();
4810b57cec5SDimitry Andric       m_all_files = false;
4820b57cec5SDimitry Andric       m_exception_extra_args.Clear();
4830b57cec5SDimitry Andric       m_move_to_nearest_code = eLazyBoolCalculate;
4840b57cec5SDimitry Andric       m_source_regex_func_names.clear();
4850b57cec5SDimitry Andric       m_current_key.clear();
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric 
GetDefinitions()4880b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4890b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_set_options);
4900b57cec5SDimitry Andric     }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric     std::string m_condition;
4950b57cec5SDimitry Andric     FileSpecList m_filenames;
496*5f7ddb14SDimitry Andric     uint32_t m_line_num = 0;
497*5f7ddb14SDimitry Andric     uint32_t m_column = 0;
4980b57cec5SDimitry Andric     std::vector<std::string> m_func_names;
4990b57cec5SDimitry Andric     std::vector<std::string> m_breakpoint_names;
500*5f7ddb14SDimitry Andric     lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5010b57cec5SDimitry Andric     std::string m_func_regexp;
5020b57cec5SDimitry Andric     std::string m_source_text_regexp;
5030b57cec5SDimitry Andric     FileSpecList m_modules;
504*5f7ddb14SDimitry Andric     lldb::addr_t m_load_addr = 0;
5050b57cec5SDimitry Andric     lldb::addr_t m_offset_addr;
506*5f7ddb14SDimitry Andric     bool m_catch_bp = false;
507*5f7ddb14SDimitry Andric     bool m_throw_bp = true;
508*5f7ddb14SDimitry Andric     bool m_hardware = false; // Request to use hardware breakpoints
509*5f7ddb14SDimitry Andric     lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
510*5f7ddb14SDimitry Andric     lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
511*5f7ddb14SDimitry Andric     LazyBool m_skip_prologue = eLazyBoolCalculate;
512*5f7ddb14SDimitry Andric     bool m_all_files = false;
5130b57cec5SDimitry Andric     Args m_exception_extra_args;
514*5f7ddb14SDimitry Andric     LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
5150b57cec5SDimitry Andric     std::unordered_set<std::string> m_source_regex_func_names;
5160b57cec5SDimitry Andric     std::string m_current_key;
5170b57cec5SDimitry Andric   };
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)5200b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
5219dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric     // The following are the various types of breakpoints that could be set:
5240b57cec5SDimitry Andric     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
5250b57cec5SDimitry Andric     //   2).  -a  [-s -g]         (setting breakpoint by address)
5260b57cec5SDimitry Andric     //   3).  -n  [-s -g]         (setting breakpoint by function name)
5270b57cec5SDimitry Andric     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
5280b57cec5SDimitry Andric     //   expression)
5290b57cec5SDimitry Andric     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
5300b57cec5SDimitry Andric     //   to source text)
5310b57cec5SDimitry Andric     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
5320b57cec5SDimitry Andric     //   given language.)
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric     BreakpointSetType break_type = eSetTypeInvalid;
5350b57cec5SDimitry Andric 
536480093f4SDimitry Andric     if (!m_python_class_options.GetName().empty())
5370b57cec5SDimitry Andric       break_type = eSetTypeScripted;
5380b57cec5SDimitry Andric     else if (m_options.m_line_num != 0)
5390b57cec5SDimitry Andric       break_type = eSetTypeFileAndLine;
5400b57cec5SDimitry Andric     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
5410b57cec5SDimitry Andric       break_type = eSetTypeAddress;
5420b57cec5SDimitry Andric     else if (!m_options.m_func_names.empty())
5430b57cec5SDimitry Andric       break_type = eSetTypeFunctionName;
5440b57cec5SDimitry Andric     else if (!m_options.m_func_regexp.empty())
5450b57cec5SDimitry Andric       break_type = eSetTypeFunctionRegexp;
5460b57cec5SDimitry Andric     else if (!m_options.m_source_text_regexp.empty())
5470b57cec5SDimitry Andric       break_type = eSetTypeSourceRegexp;
5480b57cec5SDimitry Andric     else if (m_options.m_exception_language != eLanguageTypeUnknown)
5490b57cec5SDimitry Andric       break_type = eSetTypeException;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     BreakpointSP bp_sp = nullptr;
5520b57cec5SDimitry Andric     FileSpec module_spec;
5530b57cec5SDimitry Andric     const bool internal = false;
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric     // If the user didn't specify skip-prologue, having an offset should turn
5560b57cec5SDimitry Andric     // that off.
5570b57cec5SDimitry Andric     if (m_options.m_offset_addr != 0 &&
5580b57cec5SDimitry Andric         m_options.m_skip_prologue == eLazyBoolCalculate)
5590b57cec5SDimitry Andric       m_options.m_skip_prologue = eLazyBoolNo;
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     switch (break_type) {
5620b57cec5SDimitry Andric     case eSetTypeFileAndLine: // Breakpoint by source position
5630b57cec5SDimitry Andric     {
5640b57cec5SDimitry Andric       FileSpec file;
5650b57cec5SDimitry Andric       const size_t num_files = m_options.m_filenames.GetSize();
5660b57cec5SDimitry Andric       if (num_files == 0) {
5670b57cec5SDimitry Andric         if (!GetDefaultFile(target, file, result)) {
5680b57cec5SDimitry Andric           result.AppendError("No file supplied and no default file available.");
5690b57cec5SDimitry Andric           return false;
5700b57cec5SDimitry Andric         }
5710b57cec5SDimitry Andric       } else if (num_files > 1) {
5720b57cec5SDimitry Andric         result.AppendError("Only one file at a time is allowed for file and "
5730b57cec5SDimitry Andric                            "line breakpoints.");
5740b57cec5SDimitry Andric         return false;
5750b57cec5SDimitry Andric       } else
5760b57cec5SDimitry Andric         file = m_options.m_filenames.GetFileSpecAtIndex(0);
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric       // Only check for inline functions if
5790b57cec5SDimitry Andric       LazyBool check_inlines = eLazyBoolCalculate;
5800b57cec5SDimitry Andric 
5819dba64beSDimitry Andric       bp_sp = target.CreateBreakpoint(
5829dba64beSDimitry Andric           &(m_options.m_modules), file, m_options.m_line_num,
5839dba64beSDimitry Andric           m_options.m_column, m_options.m_offset_addr, check_inlines,
5849dba64beSDimitry Andric           m_options.m_skip_prologue, internal, m_options.m_hardware,
5850b57cec5SDimitry Andric           m_options.m_move_to_nearest_code);
5860b57cec5SDimitry Andric     } break;
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric     case eSetTypeAddress: // Breakpoint by address
5890b57cec5SDimitry Andric     {
5900b57cec5SDimitry Andric       // If a shared library has been specified, make an lldb_private::Address
5910b57cec5SDimitry Andric       // with the library, and use that.  That way the address breakpoint
5920b57cec5SDimitry Andric       //  will track the load location of the library.
5930b57cec5SDimitry Andric       size_t num_modules_specified = m_options.m_modules.GetSize();
5940b57cec5SDimitry Andric       if (num_modules_specified == 1) {
5950b57cec5SDimitry Andric         const FileSpec *file_spec =
5960b57cec5SDimitry Andric             m_options.m_modules.GetFileSpecPointerAtIndex(0);
5979dba64beSDimitry Andric         bp_sp = target.CreateAddressInModuleBreakpoint(
5989dba64beSDimitry Andric             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
5990b57cec5SDimitry Andric       } else if (num_modules_specified == 0) {
6009dba64beSDimitry Andric         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
6010b57cec5SDimitry Andric                                         m_options.m_hardware);
6020b57cec5SDimitry Andric       } else {
6030b57cec5SDimitry Andric         result.AppendError("Only one shared library can be specified for "
6040b57cec5SDimitry Andric                            "address breakpoints.");
6050b57cec5SDimitry Andric         return false;
6060b57cec5SDimitry Andric       }
6070b57cec5SDimitry Andric       break;
6080b57cec5SDimitry Andric     }
6090b57cec5SDimitry Andric     case eSetTypeFunctionName: // Breakpoint by function name
6100b57cec5SDimitry Andric     {
6110b57cec5SDimitry Andric       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric       if (name_type_mask == 0)
6140b57cec5SDimitry Andric         name_type_mask = eFunctionNameTypeAuto;
6150b57cec5SDimitry Andric 
6169dba64beSDimitry Andric       bp_sp = target.CreateBreakpoint(
6179dba64beSDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames),
6189dba64beSDimitry Andric           m_options.m_func_names, name_type_mask, m_options.m_language,
6199dba64beSDimitry Andric           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
6200b57cec5SDimitry Andric           m_options.m_hardware);
6210b57cec5SDimitry Andric     } break;
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
6240b57cec5SDimitry Andric                                  // name
6250b57cec5SDimitry Andric     {
6260b57cec5SDimitry Andric       RegularExpression regexp(m_options.m_func_regexp);
6279dba64beSDimitry Andric       if (llvm::Error err = regexp.GetError()) {
6280b57cec5SDimitry Andric         result.AppendErrorWithFormat(
6295ffd83dbSDimitry Andric             "Function name regular expression could not be compiled: %s",
6309dba64beSDimitry Andric             llvm::toString(std::move(err)).c_str());
6315ffd83dbSDimitry Andric         // Check if the incorrect regex looks like a globbing expression and
6325ffd83dbSDimitry Andric         // warn the user about it.
6335ffd83dbSDimitry Andric         if (!m_options.m_func_regexp.empty()) {
6345ffd83dbSDimitry Andric           if (m_options.m_func_regexp[0] == '*' ||
6355ffd83dbSDimitry Andric               m_options.m_func_regexp[0] == '?')
6365ffd83dbSDimitry Andric             result.AppendWarning(
6375ffd83dbSDimitry Andric                 "Function name regex does not accept glob patterns.");
6385ffd83dbSDimitry Andric         }
6390b57cec5SDimitry Andric         return false;
6400b57cec5SDimitry Andric       }
6410b57cec5SDimitry Andric 
6429dba64beSDimitry Andric       bp_sp = target.CreateFuncRegexBreakpoint(
6439dba64beSDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
6449dba64beSDimitry Andric           m_options.m_language, m_options.m_skip_prologue, internal,
6450b57cec5SDimitry Andric           m_options.m_hardware);
646480093f4SDimitry Andric     } break;
6470b57cec5SDimitry Andric     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
6480b57cec5SDimitry Andric     {
6490b57cec5SDimitry Andric       const size_t num_files = m_options.m_filenames.GetSize();
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric       if (num_files == 0 && !m_options.m_all_files) {
6520b57cec5SDimitry Andric         FileSpec file;
6530b57cec5SDimitry Andric         if (!GetDefaultFile(target, file, result)) {
6540b57cec5SDimitry Andric           result.AppendError(
6550b57cec5SDimitry Andric               "No files provided and could not find default file.");
6560b57cec5SDimitry Andric           return false;
6570b57cec5SDimitry Andric         } else {
6580b57cec5SDimitry Andric           m_options.m_filenames.Append(file);
6590b57cec5SDimitry Andric         }
6600b57cec5SDimitry Andric       }
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric       RegularExpression regexp(m_options.m_source_text_regexp);
6639dba64beSDimitry Andric       if (llvm::Error err = regexp.GetError()) {
6640b57cec5SDimitry Andric         result.AppendErrorWithFormat(
6650b57cec5SDimitry Andric             "Source text regular expression could not be compiled: \"%s\"",
6669dba64beSDimitry Andric             llvm::toString(std::move(err)).c_str());
6670b57cec5SDimitry Andric         return false;
6680b57cec5SDimitry Andric       }
6699dba64beSDimitry Andric       bp_sp = target.CreateSourceRegexBreakpoint(
6709dba64beSDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames),
6719dba64beSDimitry Andric           m_options.m_source_regex_func_names, std::move(regexp), internal,
6729dba64beSDimitry Andric           m_options.m_hardware, m_options.m_move_to_nearest_code);
6730b57cec5SDimitry Andric     } break;
6740b57cec5SDimitry Andric     case eSetTypeException: {
6750b57cec5SDimitry Andric       Status precond_error;
6769dba64beSDimitry Andric       bp_sp = target.CreateExceptionBreakpoint(
6779dba64beSDimitry Andric           m_options.m_exception_language, m_options.m_catch_bp,
6789dba64beSDimitry Andric           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
6790b57cec5SDimitry Andric           &precond_error);
6800b57cec5SDimitry Andric       if (precond_error.Fail()) {
6810b57cec5SDimitry Andric         result.AppendErrorWithFormat(
6820b57cec5SDimitry Andric             "Error setting extra exception arguments: %s",
6830b57cec5SDimitry Andric             precond_error.AsCString());
6849dba64beSDimitry Andric         target.RemoveBreakpointByID(bp_sp->GetID());
6850b57cec5SDimitry Andric         return false;
6860b57cec5SDimitry Andric       }
6870b57cec5SDimitry Andric     } break;
6880b57cec5SDimitry Andric     case eSetTypeScripted: {
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric       Status error;
6919dba64beSDimitry Andric       bp_sp = target.CreateScriptedBreakpoint(
692480093f4SDimitry Andric           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
6939dba64beSDimitry Andric           &(m_options.m_filenames), false, m_options.m_hardware,
6949dba64beSDimitry Andric           m_python_class_options.GetStructuredData(), &error);
6950b57cec5SDimitry Andric       if (error.Fail()) {
6960b57cec5SDimitry Andric         result.AppendErrorWithFormat(
697480093f4SDimitry Andric             "Error setting extra exception arguments: %s", error.AsCString());
6989dba64beSDimitry Andric         target.RemoveBreakpointByID(bp_sp->GetID());
6990b57cec5SDimitry Andric         return false;
7000b57cec5SDimitry Andric       }
7010b57cec5SDimitry Andric     } break;
7020b57cec5SDimitry Andric     default:
7030b57cec5SDimitry Andric       break;
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     // Now set the various options that were passed in:
7070b57cec5SDimitry Andric     if (bp_sp) {
708*5f7ddb14SDimitry Andric       bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric       if (!m_options.m_breakpoint_names.empty()) {
7110b57cec5SDimitry Andric         Status name_error;
7120b57cec5SDimitry Andric         for (auto name : m_options.m_breakpoint_names) {
7139dba64beSDimitry Andric           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
7140b57cec5SDimitry Andric           if (name_error.Fail()) {
7150b57cec5SDimitry Andric             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
7160b57cec5SDimitry Andric                                          name.c_str());
7179dba64beSDimitry Andric             target.RemoveBreakpointByID(bp_sp->GetID());
7180b57cec5SDimitry Andric             return false;
7190b57cec5SDimitry Andric           }
7200b57cec5SDimitry Andric         }
7210b57cec5SDimitry Andric       }
7220b57cec5SDimitry Andric     }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric     if (bp_sp) {
7250b57cec5SDimitry Andric       Stream &output_stream = result.GetOutputStream();
7260b57cec5SDimitry Andric       const bool show_locations = false;
7270b57cec5SDimitry Andric       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
7280b57cec5SDimitry Andric                             show_locations);
7299dba64beSDimitry Andric       if (&target == &GetDummyTarget())
7300b57cec5SDimitry Andric         output_stream.Printf("Breakpoint set in dummy target, will get copied "
7310b57cec5SDimitry Andric                              "into future targets.\n");
7320b57cec5SDimitry Andric       else {
7330b57cec5SDimitry Andric         // Don't print out this warning for exception breakpoints.  They can
7340b57cec5SDimitry Andric         // get set before the target is set, but we won't know how to actually
7350b57cec5SDimitry Andric         // set the breakpoint till we run.
7360b57cec5SDimitry Andric         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
7370b57cec5SDimitry Andric           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
7380b57cec5SDimitry Andric                                "actual locations.\n");
7390b57cec5SDimitry Andric         }
7400b57cec5SDimitry Andric       }
7410b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
7420b57cec5SDimitry Andric     } else if (!bp_sp) {
7430b57cec5SDimitry Andric       result.AppendError("Breakpoint creation failed: No breakpoint created.");
7440b57cec5SDimitry Andric     }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric     return result.Succeeded();
7470b57cec5SDimitry Andric   }
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)7509dba64beSDimitry Andric   bool GetDefaultFile(Target &target, FileSpec &file,
7510b57cec5SDimitry Andric                       CommandReturnObject &result) {
7520b57cec5SDimitry Andric     uint32_t default_line;
7530b57cec5SDimitry Andric     // First use the Source Manager's default file. Then use the current stack
7540b57cec5SDimitry Andric     // frame's file.
7559dba64beSDimitry Andric     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
7560b57cec5SDimitry Andric       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
7570b57cec5SDimitry Andric       if (cur_frame == nullptr) {
7580b57cec5SDimitry Andric         result.AppendError(
7590b57cec5SDimitry Andric             "No selected frame to use to find the default file.");
7600b57cec5SDimitry Andric         return false;
7610b57cec5SDimitry Andric       } else if (!cur_frame->HasDebugInformation()) {
7620b57cec5SDimitry Andric         result.AppendError("Cannot use the selected frame to find the default "
7630b57cec5SDimitry Andric                            "file, it has no debug info.");
7640b57cec5SDimitry Andric         return false;
7650b57cec5SDimitry Andric       } else {
7660b57cec5SDimitry Andric         const SymbolContext &sc =
7670b57cec5SDimitry Andric             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
7680b57cec5SDimitry Andric         if (sc.line_entry.file) {
7690b57cec5SDimitry Andric           file = sc.line_entry.file;
7700b57cec5SDimitry Andric         } else {
7710b57cec5SDimitry Andric           result.AppendError("Can't find the file for the selected frame to "
7720b57cec5SDimitry Andric                              "use as the default file.");
7730b57cec5SDimitry Andric           return false;
7740b57cec5SDimitry Andric         }
7750b57cec5SDimitry Andric       }
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric     return true;
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   BreakpointOptionGroup m_bp_opts;
7810b57cec5SDimitry Andric   BreakpointDummyOptionGroup m_dummy_options;
7829dba64beSDimitry Andric   OptionGroupPythonClassWithDict m_python_class_options;
7830b57cec5SDimitry Andric   CommandOptions m_options;
7840b57cec5SDimitry Andric   OptionGroupOptions m_all_options;
7850b57cec5SDimitry Andric };
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric // CommandObjectBreakpointModify
7880b57cec5SDimitry Andric #pragma mark Modify
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric class CommandObjectBreakpointModify : public CommandObjectParsed {
7910b57cec5SDimitry Andric public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)7920b57cec5SDimitry Andric   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
7930b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint modify",
7940b57cec5SDimitry Andric                             "Modify the options on a breakpoint or set of "
7950b57cec5SDimitry Andric                             "breakpoints in the executable.  "
7960b57cec5SDimitry Andric                             "If no breakpoint is specified, acts on the last "
7970b57cec5SDimitry Andric                             "created breakpoint.  "
7980b57cec5SDimitry Andric                             "With the exception of -e, -d and -i, passing an "
7990b57cec5SDimitry Andric                             "empty argument clears the modification.",
8000b57cec5SDimitry Andric                             nullptr),
8010b57cec5SDimitry Andric         m_options() {
8020b57cec5SDimitry Andric     CommandArgumentEntry arg;
8030b57cec5SDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
8040b57cec5SDimitry Andric                                       eArgTypeBreakpointIDRange);
8050b57cec5SDimitry Andric     // Add the entry for the first argument for this command to the object's
8060b57cec5SDimitry Andric     // arguments vector.
8070b57cec5SDimitry Andric     m_arguments.push_back(arg);
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric     m_options.Append(&m_bp_opts,
8100b57cec5SDimitry Andric                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
8110b57cec5SDimitry Andric                      LLDB_OPT_SET_ALL);
8120b57cec5SDimitry Andric     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
8130b57cec5SDimitry Andric     m_options.Finalize();
8140b57cec5SDimitry Andric   }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric   ~CommandObjectBreakpointModify() override = default;
8170b57cec5SDimitry Andric 
8185ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8195ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
8205ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
8215ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
8225ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8235ffd83dbSDimitry Andric         request, nullptr);
8245ffd83dbSDimitry Andric   }
8255ffd83dbSDimitry Andric 
GetOptions()8260b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)8290b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
8309dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
8339dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
8340b57cec5SDimitry Andric 
8350b57cec5SDimitry Andric     BreakpointIDList valid_bp_ids;
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
8389dba64beSDimitry Andric         command, &target, result, &valid_bp_ids,
8390b57cec5SDimitry Andric         BreakpointName::Permissions::PermissionKinds::disablePerm);
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric     if (result.Succeeded()) {
8420b57cec5SDimitry Andric       const size_t count = valid_bp_ids.GetSize();
8430b57cec5SDimitry Andric       for (size_t i = 0; i < count; ++i) {
8440b57cec5SDimitry Andric         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
8470b57cec5SDimitry Andric           Breakpoint *bp =
8489dba64beSDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
8490b57cec5SDimitry Andric           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
8500b57cec5SDimitry Andric             BreakpointLocation *location =
8510b57cec5SDimitry Andric                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
8520b57cec5SDimitry Andric             if (location)
853*5f7ddb14SDimitry Andric               location->GetLocationOptions().CopyOverSetOptions(
854480093f4SDimitry Andric                   m_bp_opts.GetBreakpointOptions());
8550b57cec5SDimitry Andric           } else {
856*5f7ddb14SDimitry Andric             bp->GetOptions().CopyOverSetOptions(
857480093f4SDimitry Andric                 m_bp_opts.GetBreakpointOptions());
8580b57cec5SDimitry Andric           }
8590b57cec5SDimitry Andric         }
8600b57cec5SDimitry Andric       }
8610b57cec5SDimitry Andric     }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric     return result.Succeeded();
8640b57cec5SDimitry Andric   }
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric private:
8670b57cec5SDimitry Andric   BreakpointOptionGroup m_bp_opts;
8680b57cec5SDimitry Andric   BreakpointDummyOptionGroup m_dummy_opts;
8690b57cec5SDimitry Andric   OptionGroupOptions m_options;
8700b57cec5SDimitry Andric };
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric // CommandObjectBreakpointEnable
8730b57cec5SDimitry Andric #pragma mark Enable
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric class CommandObjectBreakpointEnable : public CommandObjectParsed {
8760b57cec5SDimitry Andric public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)8770b57cec5SDimitry Andric   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
8780b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "enable",
8790b57cec5SDimitry Andric                             "Enable the specified disabled breakpoint(s). If "
8800b57cec5SDimitry Andric                             "no breakpoints are specified, enable all of them.",
8810b57cec5SDimitry Andric                             nullptr) {
8820b57cec5SDimitry Andric     CommandArgumentEntry arg;
8830b57cec5SDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
8840b57cec5SDimitry Andric                                       eArgTypeBreakpointIDRange);
8850b57cec5SDimitry Andric     // Add the entry for the first argument for this command to the object's
8860b57cec5SDimitry Andric     // arguments vector.
8870b57cec5SDimitry Andric     m_arguments.push_back(arg);
8880b57cec5SDimitry Andric   }
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   ~CommandObjectBreakpointEnable() override = default;
8910b57cec5SDimitry Andric 
8925ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8935ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
8945ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
8955ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
8965ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8975ffd83dbSDimitry Andric         request, nullptr);
8985ffd83dbSDimitry Andric   }
8995ffd83dbSDimitry Andric 
9000b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)9010b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
9029dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget();
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
9059dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
9060b57cec5SDimitry Andric 
9079dba64beSDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     if (num_breakpoints == 0) {
9120b57cec5SDimitry Andric       result.AppendError("No breakpoints exist to be enabled.");
9130b57cec5SDimitry Andric       return false;
9140b57cec5SDimitry Andric     }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric     if (command.empty()) {
9170b57cec5SDimitry Andric       // No breakpoint selected; enable all currently set breakpoints.
9189dba64beSDimitry Andric       target.EnableAllowedBreakpoints();
9190b57cec5SDimitry Andric       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
9200b57cec5SDimitry Andric                                      " breakpoints)\n",
9210b57cec5SDimitry Andric                                      (uint64_t)num_breakpoints);
9220b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
9230b57cec5SDimitry Andric     } else {
9240b57cec5SDimitry Andric       // Particular breakpoint selected; enable that breakpoint.
9250b57cec5SDimitry Andric       BreakpointIDList valid_bp_ids;
9260b57cec5SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
9279dba64beSDimitry Andric           command, &target, result, &valid_bp_ids,
9280b57cec5SDimitry Andric           BreakpointName::Permissions::PermissionKinds::disablePerm);
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric       if (result.Succeeded()) {
9310b57cec5SDimitry Andric         int enable_count = 0;
9320b57cec5SDimitry Andric         int loc_count = 0;
9330b57cec5SDimitry Andric         const size_t count = valid_bp_ids.GetSize();
9340b57cec5SDimitry Andric         for (size_t i = 0; i < count; ++i) {
9350b57cec5SDimitry Andric           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
9380b57cec5SDimitry Andric             Breakpoint *breakpoint =
9399dba64beSDimitry Andric                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
9400b57cec5SDimitry Andric             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
9410b57cec5SDimitry Andric               BreakpointLocation *location =
9420b57cec5SDimitry Andric                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
9430b57cec5SDimitry Andric               if (location) {
9440b57cec5SDimitry Andric                 location->SetEnabled(true);
9450b57cec5SDimitry Andric                 ++loc_count;
9460b57cec5SDimitry Andric               }
9470b57cec5SDimitry Andric             } else {
9480b57cec5SDimitry Andric               breakpoint->SetEnabled(true);
9490b57cec5SDimitry Andric               ++enable_count;
9500b57cec5SDimitry Andric             }
9510b57cec5SDimitry Andric           }
9520b57cec5SDimitry Andric         }
9530b57cec5SDimitry Andric         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
9540b57cec5SDimitry Andric                                        enable_count + loc_count);
9550b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9560b57cec5SDimitry Andric       }
9570b57cec5SDimitry Andric     }
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric     return result.Succeeded();
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric };
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric // CommandObjectBreakpointDisable
9640b57cec5SDimitry Andric #pragma mark Disable
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric class CommandObjectBreakpointDisable : public CommandObjectParsed {
9670b57cec5SDimitry Andric public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)9680b57cec5SDimitry Andric   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
9690b57cec5SDimitry Andric       : CommandObjectParsed(
9700b57cec5SDimitry Andric             interpreter, "breakpoint disable",
9710b57cec5SDimitry Andric             "Disable the specified breakpoint(s) without deleting "
9720b57cec5SDimitry Andric             "them.  If none are specified, disable all "
9730b57cec5SDimitry Andric             "breakpoints.",
9740b57cec5SDimitry Andric             nullptr) {
9750b57cec5SDimitry Andric     SetHelpLong(
9760b57cec5SDimitry Andric         "Disable the specified breakpoint(s) without deleting them.  \
9770b57cec5SDimitry Andric If none are specified, disable all breakpoints."
9780b57cec5SDimitry Andric         R"(
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric )"
9810b57cec5SDimitry Andric         "Note: disabling a breakpoint will cause none of its locations to be hit \
9820b57cec5SDimitry Andric regardless of whether individual locations are enabled or disabled.  After the sequence:"
9830b57cec5SDimitry Andric         R"(
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric     (lldb) break disable 1
9860b57cec5SDimitry Andric     (lldb) break enable 1.1
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric execution will NOT stop at location 1.1.  To achieve that, type:
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric     (lldb) break disable 1.*
9910b57cec5SDimitry Andric     (lldb) break enable 1.1
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric )"
9940b57cec5SDimitry Andric         "The first command disables all locations for breakpoint 1, \
9950b57cec5SDimitry Andric the second re-enables the first location.");
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric     CommandArgumentEntry arg;
9980b57cec5SDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
9990b57cec5SDimitry Andric                                       eArgTypeBreakpointIDRange);
10000b57cec5SDimitry Andric     // Add the entry for the first argument for this command to the object's
10010b57cec5SDimitry Andric     // arguments vector.
10020b57cec5SDimitry Andric     m_arguments.push_back(arg);
10030b57cec5SDimitry Andric   }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   ~CommandObjectBreakpointDisable() override = default;
10060b57cec5SDimitry Andric 
10075ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)10085ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
10095ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
10105ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
10115ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10125ffd83dbSDimitry Andric         request, nullptr);
10135ffd83dbSDimitry Andric   }
10145ffd83dbSDimitry Andric 
10150b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)10160b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
10179dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget();
10180b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
10199dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
10200b57cec5SDimitry Andric 
10219dba64beSDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
10220b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric     if (num_breakpoints == 0) {
10250b57cec5SDimitry Andric       result.AppendError("No breakpoints exist to be disabled.");
10260b57cec5SDimitry Andric       return false;
10270b57cec5SDimitry Andric     }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric     if (command.empty()) {
10300b57cec5SDimitry Andric       // No breakpoint selected; disable all currently set breakpoints.
10319dba64beSDimitry Andric       target.DisableAllowedBreakpoints();
10320b57cec5SDimitry Andric       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
10330b57cec5SDimitry Andric                                      " breakpoints)\n",
10340b57cec5SDimitry Andric                                      (uint64_t)num_breakpoints);
10350b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
10360b57cec5SDimitry Andric     } else {
10370b57cec5SDimitry Andric       // Particular breakpoint selected; disable that breakpoint.
10380b57cec5SDimitry Andric       BreakpointIDList valid_bp_ids;
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
10419dba64beSDimitry Andric           command, &target, result, &valid_bp_ids,
10420b57cec5SDimitry Andric           BreakpointName::Permissions::PermissionKinds::disablePerm);
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric       if (result.Succeeded()) {
10450b57cec5SDimitry Andric         int disable_count = 0;
10460b57cec5SDimitry Andric         int loc_count = 0;
10470b57cec5SDimitry Andric         const size_t count = valid_bp_ids.GetSize();
10480b57cec5SDimitry Andric         for (size_t i = 0; i < count; ++i) {
10490b57cec5SDimitry Andric           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
10520b57cec5SDimitry Andric             Breakpoint *breakpoint =
10539dba64beSDimitry Andric                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
10540b57cec5SDimitry Andric             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
10550b57cec5SDimitry Andric               BreakpointLocation *location =
10560b57cec5SDimitry Andric                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
10570b57cec5SDimitry Andric               if (location) {
10580b57cec5SDimitry Andric                 location->SetEnabled(false);
10590b57cec5SDimitry Andric                 ++loc_count;
10600b57cec5SDimitry Andric               }
10610b57cec5SDimitry Andric             } else {
10620b57cec5SDimitry Andric               breakpoint->SetEnabled(false);
10630b57cec5SDimitry Andric               ++disable_count;
10640b57cec5SDimitry Andric             }
10650b57cec5SDimitry Andric           }
10660b57cec5SDimitry Andric         }
10670b57cec5SDimitry Andric         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
10680b57cec5SDimitry Andric                                        disable_count + loc_count);
10690b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10700b57cec5SDimitry Andric       }
10710b57cec5SDimitry Andric     }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric     return result.Succeeded();
10740b57cec5SDimitry Andric   }
10750b57cec5SDimitry Andric };
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric // CommandObjectBreakpointList
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric #pragma mark List::CommandOptions
10800b57cec5SDimitry Andric #define LLDB_OPTIONS_breakpoint_list
10810b57cec5SDimitry Andric #include "CommandOptions.inc"
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric #pragma mark List
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric class CommandObjectBreakpointList : public CommandObjectParsed {
10860b57cec5SDimitry Andric public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)10870b57cec5SDimitry Andric   CommandObjectBreakpointList(CommandInterpreter &interpreter)
10880b57cec5SDimitry Andric       : CommandObjectParsed(
10890b57cec5SDimitry Andric             interpreter, "breakpoint list",
10900b57cec5SDimitry Andric             "List some or all breakpoints at configurable levels of detail.",
10910b57cec5SDimitry Andric             nullptr),
10920b57cec5SDimitry Andric         m_options() {
10930b57cec5SDimitry Andric     CommandArgumentEntry arg;
10940b57cec5SDimitry Andric     CommandArgumentData bp_id_arg;
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
10970b57cec5SDimitry Andric     bp_id_arg.arg_type = eArgTypeBreakpointID;
10980b57cec5SDimitry Andric     bp_id_arg.arg_repetition = eArgRepeatOptional;
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
11010b57cec5SDimitry Andric     // argument entry.
11020b57cec5SDimitry Andric     arg.push_back(bp_id_arg);
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
11050b57cec5SDimitry Andric     m_arguments.push_back(arg);
11060b57cec5SDimitry Andric   }
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric   ~CommandObjectBreakpointList() override = default;
11090b57cec5SDimitry Andric 
GetOptions()11100b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   class CommandOptions : public Options {
11130b57cec5SDimitry Andric   public:
CommandOptions()1114*5f7ddb14SDimitry Andric     CommandOptions() : Options() {}
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric     ~CommandOptions() override = default;
11170b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)11180b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
11190b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
11200b57cec5SDimitry Andric       Status error;
11210b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric       switch (short_option) {
11240b57cec5SDimitry Andric       case 'b':
11250b57cec5SDimitry Andric         m_level = lldb::eDescriptionLevelBrief;
11260b57cec5SDimitry Andric         break;
11270b57cec5SDimitry Andric       case 'D':
11280b57cec5SDimitry Andric         m_use_dummy = true;
11290b57cec5SDimitry Andric         break;
11300b57cec5SDimitry Andric       case 'f':
11310b57cec5SDimitry Andric         m_level = lldb::eDescriptionLevelFull;
11320b57cec5SDimitry Andric         break;
11330b57cec5SDimitry Andric       case 'v':
11340b57cec5SDimitry Andric         m_level = lldb::eDescriptionLevelVerbose;
11350b57cec5SDimitry Andric         break;
11360b57cec5SDimitry Andric       case 'i':
11370b57cec5SDimitry Andric         m_internal = true;
11380b57cec5SDimitry Andric         break;
11390b57cec5SDimitry Andric       default:
11409dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
11410b57cec5SDimitry Andric       }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric       return error;
11440b57cec5SDimitry Andric     }
11450b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)11460b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
11470b57cec5SDimitry Andric       m_level = lldb::eDescriptionLevelFull;
11480b57cec5SDimitry Andric       m_internal = false;
11490b57cec5SDimitry Andric       m_use_dummy = false;
11500b57cec5SDimitry Andric     }
11510b57cec5SDimitry Andric 
GetDefinitions()11520b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
11530b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_list_options);
11540b57cec5SDimitry Andric     }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
11570b57cec5SDimitry Andric 
1158*5f7ddb14SDimitry Andric     lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric     bool m_internal;
1161*5f7ddb14SDimitry Andric     bool m_use_dummy = false;
11620b57cec5SDimitry Andric   };
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)11650b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
11669dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric     const BreakpointList &breakpoints =
11699dba64beSDimitry Andric         target.GetBreakpointList(m_options.m_internal);
11700b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
11719dba64beSDimitry Andric     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric     if (num_breakpoints == 0) {
11760b57cec5SDimitry Andric       result.AppendMessage("No breakpoints currently set.");
11770b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11780b57cec5SDimitry Andric       return true;
11790b57cec5SDimitry Andric     }
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric     Stream &output_stream = result.GetOutputStream();
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric     if (command.empty()) {
11840b57cec5SDimitry Andric       // No breakpoint selected; show info about all currently set breakpoints.
11850b57cec5SDimitry Andric       result.AppendMessage("Current breakpoints:");
11860b57cec5SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
11870b57cec5SDimitry Andric         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
11880b57cec5SDimitry Andric         if (breakpoint->AllowList())
11890b57cec5SDimitry Andric           AddBreakpointDescription(&output_stream, breakpoint,
11900b57cec5SDimitry Andric                                    m_options.m_level);
11910b57cec5SDimitry Andric       }
11920b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11930b57cec5SDimitry Andric     } else {
11940b57cec5SDimitry Andric       // Particular breakpoints selected; show info about that breakpoint.
11950b57cec5SDimitry Andric       BreakpointIDList valid_bp_ids;
11960b57cec5SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
11979dba64beSDimitry Andric           command, &target, result, &valid_bp_ids,
11980b57cec5SDimitry Andric           BreakpointName::Permissions::PermissionKinds::listPerm);
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric       if (result.Succeeded()) {
12010b57cec5SDimitry Andric         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12020b57cec5SDimitry Andric           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
12030b57cec5SDimitry Andric           Breakpoint *breakpoint =
12049dba64beSDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
12050b57cec5SDimitry Andric           AddBreakpointDescription(&output_stream, breakpoint,
12060b57cec5SDimitry Andric                                    m_options.m_level);
12070b57cec5SDimitry Andric         }
12080b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
12090b57cec5SDimitry Andric       } else {
12100b57cec5SDimitry Andric         result.AppendError("Invalid breakpoint ID.");
12110b57cec5SDimitry Andric       }
12120b57cec5SDimitry Andric     }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric     return result.Succeeded();
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric private:
12180b57cec5SDimitry Andric   CommandOptions m_options;
12190b57cec5SDimitry Andric };
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric // CommandObjectBreakpointClear
12220b57cec5SDimitry Andric #pragma mark Clear::CommandOptions
12230b57cec5SDimitry Andric 
12249dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_clear
12259dba64beSDimitry Andric #include "CommandOptions.inc"
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric #pragma mark Clear
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric class CommandObjectBreakpointClear : public CommandObjectParsed {
12300b57cec5SDimitry Andric public:
12310b57cec5SDimitry Andric   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12320b57cec5SDimitry Andric 
CommandObjectBreakpointClear(CommandInterpreter & interpreter)12330b57cec5SDimitry Andric   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12340b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint clear",
12350b57cec5SDimitry Andric                             "Delete or disable breakpoints matching the "
12360b57cec5SDimitry Andric                             "specified source file and line.",
12370b57cec5SDimitry Andric                             "breakpoint clear <cmd-options>"),
12380b57cec5SDimitry Andric         m_options() {}
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric   ~CommandObjectBreakpointClear() override = default;
12410b57cec5SDimitry Andric 
GetOptions()12420b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric   class CommandOptions : public Options {
12450b57cec5SDimitry Andric   public:
CommandOptions()1246*5f7ddb14SDimitry Andric     CommandOptions() : Options(), m_filename() {}
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric     ~CommandOptions() override = default;
12490b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)12500b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
12510b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
12520b57cec5SDimitry Andric       Status error;
12530b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric       switch (short_option) {
12560b57cec5SDimitry Andric       case 'f':
12575ffd83dbSDimitry Andric         m_filename.assign(std::string(option_arg));
12580b57cec5SDimitry Andric         break;
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric       case 'l':
12610b57cec5SDimitry Andric         option_arg.getAsInteger(0, m_line_num);
12620b57cec5SDimitry Andric         break;
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric       default:
12659dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
12660b57cec5SDimitry Andric       }
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric       return error;
12690b57cec5SDimitry Andric     }
12700b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)12710b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
12720b57cec5SDimitry Andric       m_filename.clear();
12730b57cec5SDimitry Andric       m_line_num = 0;
12740b57cec5SDimitry Andric     }
12750b57cec5SDimitry Andric 
GetDefinitions()12760b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
12770b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_clear_options);
12780b57cec5SDimitry Andric     }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric     std::string m_filename;
1283*5f7ddb14SDimitry Andric     uint32_t m_line_num = 0;
12840b57cec5SDimitry Andric   };
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)12870b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12889dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget();
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric     // The following are the various types of breakpoints that could be
12910b57cec5SDimitry Andric     // cleared:
12920b57cec5SDimitry Andric     //   1). -f -l (clearing breakpoint by source location)
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric     BreakpointClearType break_type = eClearTypeInvalid;
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric     if (m_options.m_line_num != 0)
12970b57cec5SDimitry Andric       break_type = eClearTypeFileAndLine;
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
13009dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
13010b57cec5SDimitry Andric 
13029dba64beSDimitry Andric     BreakpointList &breakpoints = target.GetBreakpointList();
13030b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric     // Early return if there's no breakpoint at all.
13060b57cec5SDimitry Andric     if (num_breakpoints == 0) {
13070b57cec5SDimitry Andric       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13080b57cec5SDimitry Andric       return result.Succeeded();
13090b57cec5SDimitry Andric     }
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric     // Find matching breakpoints and delete them.
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric     // First create a copy of all the IDs.
13140b57cec5SDimitry Andric     std::vector<break_id_t> BreakIDs;
13150b57cec5SDimitry Andric     for (size_t i = 0; i < num_breakpoints; ++i)
13160b57cec5SDimitry Andric       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric     int num_cleared = 0;
13190b57cec5SDimitry Andric     StreamString ss;
13200b57cec5SDimitry Andric     switch (break_type) {
13210b57cec5SDimitry Andric     case eClearTypeFileAndLine: // Breakpoint by source position
13220b57cec5SDimitry Andric     {
13230b57cec5SDimitry Andric       const ConstString filename(m_options.m_filename.c_str());
13240b57cec5SDimitry Andric       BreakpointLocationCollection loc_coll;
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
13270b57cec5SDimitry Andric         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13280b57cec5SDimitry Andric 
13290b57cec5SDimitry Andric         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
13300b57cec5SDimitry Andric           // If the collection size is 0, it's a full match and we can just
13310b57cec5SDimitry Andric           // remove the breakpoint.
13320b57cec5SDimitry Andric           if (loc_coll.GetSize() == 0) {
13330b57cec5SDimitry Andric             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13340b57cec5SDimitry Andric             ss.EOL();
13359dba64beSDimitry Andric             target.RemoveBreakpointByID(bp->GetID());
13360b57cec5SDimitry Andric             ++num_cleared;
13370b57cec5SDimitry Andric           }
13380b57cec5SDimitry Andric         }
13390b57cec5SDimitry Andric       }
13400b57cec5SDimitry Andric     } break;
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric     default:
13430b57cec5SDimitry Andric       break;
13440b57cec5SDimitry Andric     }
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric     if (num_cleared > 0) {
13470b57cec5SDimitry Andric       Stream &output_stream = result.GetOutputStream();
13480b57cec5SDimitry Andric       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
13490b57cec5SDimitry Andric       output_stream << ss.GetString();
13500b57cec5SDimitry Andric       output_stream.EOL();
13510b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
13520b57cec5SDimitry Andric     } else {
13530b57cec5SDimitry Andric       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13540b57cec5SDimitry Andric     }
13550b57cec5SDimitry Andric 
13560b57cec5SDimitry Andric     return result.Succeeded();
13570b57cec5SDimitry Andric   }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric private:
13600b57cec5SDimitry Andric   CommandOptions m_options;
13610b57cec5SDimitry Andric };
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric // CommandObjectBreakpointDelete
13649dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_delete
13659dba64beSDimitry Andric #include "CommandOptions.inc"
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric #pragma mark Delete
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric class CommandObjectBreakpointDelete : public CommandObjectParsed {
13700b57cec5SDimitry Andric public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)13710b57cec5SDimitry Andric   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
13720b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint delete",
13730b57cec5SDimitry Andric                             "Delete the specified breakpoint(s).  If no "
13740b57cec5SDimitry Andric                             "breakpoints are specified, delete them all.",
13750b57cec5SDimitry Andric                             nullptr),
13760b57cec5SDimitry Andric         m_options() {
13770b57cec5SDimitry Andric     CommandArgumentEntry arg;
13780b57cec5SDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
13790b57cec5SDimitry Andric                                       eArgTypeBreakpointIDRange);
13800b57cec5SDimitry Andric     // Add the entry for the first argument for this command to the object's
13810b57cec5SDimitry Andric     // arguments vector.
13820b57cec5SDimitry Andric     m_arguments.push_back(arg);
13830b57cec5SDimitry Andric   }
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric   ~CommandObjectBreakpointDelete() override = default;
13860b57cec5SDimitry Andric 
13875ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)13885ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
13895ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
13905ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
13915ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
13925ffd83dbSDimitry Andric         request, nullptr);
13935ffd83dbSDimitry Andric   }
13945ffd83dbSDimitry Andric 
GetOptions()13950b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric   class CommandOptions : public Options {
13980b57cec5SDimitry Andric   public:
CommandOptions()1399*5f7ddb14SDimitry Andric     CommandOptions() : Options() {}
14000b57cec5SDimitry Andric 
14010b57cec5SDimitry Andric     ~CommandOptions() override = default;
14020b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14030b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
14040b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
14050b57cec5SDimitry Andric       Status error;
14060b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric       switch (short_option) {
14090b57cec5SDimitry Andric       case 'f':
14100b57cec5SDimitry Andric         m_force = true;
14110b57cec5SDimitry Andric         break;
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric       case 'D':
14140b57cec5SDimitry Andric         m_use_dummy = true;
14150b57cec5SDimitry Andric         break;
14160b57cec5SDimitry Andric 
1417af732203SDimitry Andric       case 'd':
1418af732203SDimitry Andric         m_delete_disabled = true;
1419af732203SDimitry Andric         break;
1420af732203SDimitry Andric 
14210b57cec5SDimitry Andric       default:
14229dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
14230b57cec5SDimitry Andric       }
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric       return error;
14260b57cec5SDimitry Andric     }
14270b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)14280b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
14290b57cec5SDimitry Andric       m_use_dummy = false;
14300b57cec5SDimitry Andric       m_force = false;
1431af732203SDimitry Andric       m_delete_disabled = false;
14320b57cec5SDimitry Andric     }
14330b57cec5SDimitry Andric 
GetDefinitions()14340b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
14350b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_delete_options);
14360b57cec5SDimitry Andric     }
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
1439*5f7ddb14SDimitry Andric     bool m_use_dummy = false;
1440*5f7ddb14SDimitry Andric     bool m_force = false;
1441*5f7ddb14SDimitry Andric     bool m_delete_disabled = false;
14420b57cec5SDimitry Andric   };
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)14450b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
14469dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1447af732203SDimitry Andric     result.Clear();
14480b57cec5SDimitry Andric 
14490b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
14509dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
14510b57cec5SDimitry Andric 
1452af732203SDimitry Andric     BreakpointList &breakpoints = target.GetBreakpointList();
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     if (num_breakpoints == 0) {
14570b57cec5SDimitry Andric       result.AppendError("No breakpoints exist to be deleted.");
14580b57cec5SDimitry Andric       return false;
14590b57cec5SDimitry Andric     }
14600b57cec5SDimitry Andric 
1461*5f7ddb14SDimitry Andric     // Handle the delete all breakpoints case:
1462af732203SDimitry Andric     if (command.empty() && !m_options.m_delete_disabled) {
14630b57cec5SDimitry Andric       if (!m_options.m_force &&
14640b57cec5SDimitry Andric           !m_interpreter.Confirm(
14650b57cec5SDimitry Andric               "About to delete all breakpoints, do you want to do that?",
14660b57cec5SDimitry Andric               true)) {
14670b57cec5SDimitry Andric         result.AppendMessage("Operation cancelled...");
14680b57cec5SDimitry Andric       } else {
14699dba64beSDimitry Andric         target.RemoveAllowedBreakpoints();
14700b57cec5SDimitry Andric         result.AppendMessageWithFormat(
14710b57cec5SDimitry Andric             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
14720b57cec5SDimitry Andric             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14730b57cec5SDimitry Andric       }
14740b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1475*5f7ddb14SDimitry Andric       return result.Succeeded();
1476*5f7ddb14SDimitry Andric     }
1477*5f7ddb14SDimitry Andric 
1478*5f7ddb14SDimitry Andric     // Either we have some kind of breakpoint specification(s),
1479*5f7ddb14SDimitry Andric     // or we are handling "break disable --deleted".  Gather the list
1480*5f7ddb14SDimitry Andric     // of breakpoints to delete here, the we'll delete them below.
14810b57cec5SDimitry Andric     BreakpointIDList valid_bp_ids;
1482af732203SDimitry Andric 
1483af732203SDimitry Andric     if (m_options.m_delete_disabled) {
1484af732203SDimitry Andric       BreakpointIDList excluded_bp_ids;
1485af732203SDimitry Andric 
1486af732203SDimitry Andric       if (!command.empty()) {
1487af732203SDimitry Andric         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1488af732203SDimitry Andric             command, &target, result, &excluded_bp_ids,
1489af732203SDimitry Andric             BreakpointName::Permissions::PermissionKinds::deletePerm);
1490*5f7ddb14SDimitry Andric         if (!result.Succeeded())
1491*5f7ddb14SDimitry Andric           return false;
1492af732203SDimitry Andric       }
1493*5f7ddb14SDimitry Andric 
1494af732203SDimitry Andric       for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1495af732203SDimitry Andric         if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1496af732203SDimitry Andric           BreakpointID bp_id(breakpoint_sp->GetID());
1497af732203SDimitry Andric           size_t pos = 0;
1498af732203SDimitry Andric           if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
1499af732203SDimitry Andric             valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
1500af732203SDimitry Andric         }
1501af732203SDimitry Andric       }
1502af732203SDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1503af732203SDimitry Andric         result.AppendError("No disabled breakpoints.");
1504af732203SDimitry Andric         return false;
1505af732203SDimitry Andric       }
1506af732203SDimitry Andric     } else {
15070b57cec5SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
15089dba64beSDimitry Andric           command, &target, result, &valid_bp_ids,
15090b57cec5SDimitry Andric           BreakpointName::Permissions::PermissionKinds::deletePerm);
1510*5f7ddb14SDimitry Andric       if (!result.Succeeded())
1511*5f7ddb14SDimitry Andric         return false;
1512af732203SDimitry Andric     }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric     int delete_count = 0;
15150b57cec5SDimitry Andric     int disable_count = 0;
15160b57cec5SDimitry Andric     const size_t count = valid_bp_ids.GetSize();
15170b57cec5SDimitry Andric     for (size_t i = 0; i < count; ++i) {
15180b57cec5SDimitry Andric       BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric       if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
15210b57cec5SDimitry Andric         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
15220b57cec5SDimitry Andric           Breakpoint *breakpoint =
15239dba64beSDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
15240b57cec5SDimitry Andric           BreakpointLocation *location =
15250b57cec5SDimitry Andric               breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
15260b57cec5SDimitry Andric           // It makes no sense to try to delete individual locations, so we
15270b57cec5SDimitry Andric           // disable them instead.
15280b57cec5SDimitry Andric           if (location) {
15290b57cec5SDimitry Andric             location->SetEnabled(false);
15300b57cec5SDimitry Andric             ++disable_count;
15310b57cec5SDimitry Andric           }
15320b57cec5SDimitry Andric         } else {
15339dba64beSDimitry Andric           target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15340b57cec5SDimitry Andric           ++delete_count;
15350b57cec5SDimitry Andric         }
15360b57cec5SDimitry Andric       }
15370b57cec5SDimitry Andric     }
15380b57cec5SDimitry Andric     result.AppendMessageWithFormat(
15390b57cec5SDimitry Andric         "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15400b57cec5SDimitry Andric         delete_count, disable_count);
15410b57cec5SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishNoResult);
15420b57cec5SDimitry Andric     return result.Succeeded();
15430b57cec5SDimitry Andric   }
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric private:
15460b57cec5SDimitry Andric   CommandOptions m_options;
15470b57cec5SDimitry Andric };
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric // CommandObjectBreakpointName
15509dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_name
15519dba64beSDimitry Andric #include "CommandOptions.inc"
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric class BreakpointNameOptionGroup : public OptionGroup {
15540b57cec5SDimitry Andric public:
BreakpointNameOptionGroup()15550b57cec5SDimitry Andric   BreakpointNameOptionGroup()
15560b57cec5SDimitry Andric       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15570b57cec5SDimitry Andric   }
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   ~BreakpointNameOptionGroup() override = default;
15600b57cec5SDimitry Andric 
GetDefinitions()15610b57cec5SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
15620b57cec5SDimitry Andric     return llvm::makeArrayRef(g_breakpoint_name_options);
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)15650b57cec5SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
15660b57cec5SDimitry Andric                         ExecutionContext *execution_context) override {
15670b57cec5SDimitry Andric     Status error;
15680b57cec5SDimitry Andric     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric     switch (short_option) {
15710b57cec5SDimitry Andric     case 'N':
15720b57cec5SDimitry Andric       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
15730b57cec5SDimitry Andric           error.Success())
15740b57cec5SDimitry Andric         m_name.SetValueFromString(option_arg);
15750b57cec5SDimitry Andric       break;
15760b57cec5SDimitry Andric     case 'B':
15770b57cec5SDimitry Andric       if (m_breakpoint.SetValueFromString(option_arg).Fail())
15780b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
15790b57cec5SDimitry Andric             "unrecognized value \"%s\" for breakpoint",
15800b57cec5SDimitry Andric             option_arg.str().c_str());
15810b57cec5SDimitry Andric       break;
15820b57cec5SDimitry Andric     case 'D':
15830b57cec5SDimitry Andric       if (m_use_dummy.SetValueFromString(option_arg).Fail())
15840b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
15850b57cec5SDimitry Andric             "unrecognized value \"%s\" for use-dummy",
15860b57cec5SDimitry Andric             option_arg.str().c_str());
15870b57cec5SDimitry Andric       break;
15880b57cec5SDimitry Andric     case 'H':
15890b57cec5SDimitry Andric       m_help_string.SetValueFromString(option_arg);
15900b57cec5SDimitry Andric       break;
15910b57cec5SDimitry Andric 
15920b57cec5SDimitry Andric     default:
15939dba64beSDimitry Andric       llvm_unreachable("Unimplemented option");
15940b57cec5SDimitry Andric     }
15950b57cec5SDimitry Andric     return error;
15960b57cec5SDimitry Andric   }
15970b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)15980b57cec5SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
15990b57cec5SDimitry Andric     m_name.Clear();
16000b57cec5SDimitry Andric     m_breakpoint.Clear();
16010b57cec5SDimitry Andric     m_use_dummy.Clear();
16020b57cec5SDimitry Andric     m_use_dummy.SetDefaultValue(false);
16030b57cec5SDimitry Andric     m_help_string.Clear();
16040b57cec5SDimitry Andric   }
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric   OptionValueString m_name;
16070b57cec5SDimitry Andric   OptionValueUInt64 m_breakpoint;
16080b57cec5SDimitry Andric   OptionValueBoolean m_use_dummy;
16090b57cec5SDimitry Andric   OptionValueString m_help_string;
16100b57cec5SDimitry Andric };
16110b57cec5SDimitry Andric 
16129dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_access
16139dba64beSDimitry Andric #include "CommandOptions.inc"
16140b57cec5SDimitry Andric 
16150b57cec5SDimitry Andric class BreakpointAccessOptionGroup : public OptionGroup {
16160b57cec5SDimitry Andric public:
BreakpointAccessOptionGroup()16170b57cec5SDimitry Andric   BreakpointAccessOptionGroup() : OptionGroup() {}
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric   ~BreakpointAccessOptionGroup() override = default;
16200b57cec5SDimitry Andric 
GetDefinitions()16210b57cec5SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
16220b57cec5SDimitry Andric     return llvm::makeArrayRef(g_breakpoint_access_options);
16230b57cec5SDimitry Andric   }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)16240b57cec5SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
16250b57cec5SDimitry Andric                         ExecutionContext *execution_context) override {
16260b57cec5SDimitry Andric     Status error;
1627480093f4SDimitry Andric     const int short_option =
1628480093f4SDimitry Andric         g_breakpoint_access_options[option_idx].short_option;
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric     switch (short_option) {
16310b57cec5SDimitry Andric     case 'L': {
16320b57cec5SDimitry Andric       bool value, success;
16330b57cec5SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
16340b57cec5SDimitry Andric       if (success) {
16350b57cec5SDimitry Andric         m_permissions.SetAllowList(value);
16360b57cec5SDimitry Andric       } else
16370b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
16380b57cec5SDimitry Andric             "invalid boolean value '%s' passed for -L option",
16390b57cec5SDimitry Andric             option_arg.str().c_str());
16400b57cec5SDimitry Andric     } break;
16410b57cec5SDimitry Andric     case 'A': {
16420b57cec5SDimitry Andric       bool value, success;
16430b57cec5SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
16440b57cec5SDimitry Andric       if (success) {
16450b57cec5SDimitry Andric         m_permissions.SetAllowDisable(value);
16460b57cec5SDimitry Andric       } else
16470b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
16480b57cec5SDimitry Andric             "invalid boolean value '%s' passed for -L option",
16490b57cec5SDimitry Andric             option_arg.str().c_str());
16500b57cec5SDimitry Andric     } break;
16510b57cec5SDimitry Andric     case 'D': {
16520b57cec5SDimitry Andric       bool value, success;
16530b57cec5SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
16540b57cec5SDimitry Andric       if (success) {
16550b57cec5SDimitry Andric         m_permissions.SetAllowDelete(value);
16560b57cec5SDimitry Andric       } else
16570b57cec5SDimitry Andric         error.SetErrorStringWithFormat(
16580b57cec5SDimitry Andric             "invalid boolean value '%s' passed for -L option",
16590b57cec5SDimitry Andric             option_arg.str().c_str());
16600b57cec5SDimitry Andric     } break;
16619dba64beSDimitry Andric     default:
16629dba64beSDimitry Andric       llvm_unreachable("Unimplemented option");
16630b57cec5SDimitry Andric     }
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric     return error;
16660b57cec5SDimitry Andric   }
16670b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1668480093f4SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {}
16690b57cec5SDimitry Andric 
GetPermissions() const1670480093f4SDimitry Andric   const BreakpointName::Permissions &GetPermissions() const {
16710b57cec5SDimitry Andric     return m_permissions;
16720b57cec5SDimitry Andric   }
16730b57cec5SDimitry Andric   BreakpointName::Permissions m_permissions;
16740b57cec5SDimitry Andric };
16750b57cec5SDimitry Andric 
16760b57cec5SDimitry Andric class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
16770b57cec5SDimitry Andric public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)16780b57cec5SDimitry Andric   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
16790b57cec5SDimitry Andric       : CommandObjectParsed(
1680480093f4SDimitry Andric             interpreter, "configure",
1681480093f4SDimitry Andric             "Configure the options for the breakpoint"
16820b57cec5SDimitry Andric             " name provided.  "
16830b57cec5SDimitry Andric             "If you provide a breakpoint id, the options will be copied from "
16840b57cec5SDimitry Andric             "the breakpoint, otherwise only the options specified will be set "
16850b57cec5SDimitry Andric             "on the name.",
16860b57cec5SDimitry Andric             "breakpoint name configure <command-options> "
16870b57cec5SDimitry Andric             "<breakpoint-name-list>"),
16880b57cec5SDimitry Andric         m_bp_opts(), m_option_group() {
16890b57cec5SDimitry Andric     // Create the first variant for the first (and only) argument for this
16900b57cec5SDimitry Andric     // command.
16910b57cec5SDimitry Andric     CommandArgumentEntry arg1;
16920b57cec5SDimitry Andric     CommandArgumentData id_arg;
16930b57cec5SDimitry Andric     id_arg.arg_type = eArgTypeBreakpointName;
16940b57cec5SDimitry Andric     id_arg.arg_repetition = eArgRepeatOptional;
16950b57cec5SDimitry Andric     arg1.push_back(id_arg);
16960b57cec5SDimitry Andric     m_arguments.push_back(arg1);
16970b57cec5SDimitry Andric 
1698480093f4SDimitry Andric     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1699480093f4SDimitry Andric     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
17000b57cec5SDimitry Andric                           LLDB_OPT_SET_ALL);
1701480093f4SDimitry Andric     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
17020b57cec5SDimitry Andric                           LLDB_OPT_SET_ALL);
17030b57cec5SDimitry Andric     m_option_group.Finalize();
17040b57cec5SDimitry Andric   }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   ~CommandObjectBreakpointNameConfigure() override = default;
17070b57cec5SDimitry Andric 
GetOptions()17080b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)17110b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric     const size_t argc = command.GetArgumentCount();
17140b57cec5SDimitry Andric     if (argc == 0) {
17150b57cec5SDimitry Andric       result.AppendError("No names provided.");
17160b57cec5SDimitry Andric       return false;
17170b57cec5SDimitry Andric     }
17180b57cec5SDimitry Andric 
17199dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget(false);
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
17229dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
17230b57cec5SDimitry Andric 
17240b57cec5SDimitry Andric     // Make a pass through first to see that all the names are legal.
17250b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
17260b57cec5SDimitry Andric       Status error;
1727480093f4SDimitry Andric       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
17280b57cec5SDimitry Andric         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
17290b57cec5SDimitry Andric                                      entry.c_str(), error.AsCString());
17300b57cec5SDimitry Andric         return false;
17310b57cec5SDimitry Andric       }
17320b57cec5SDimitry Andric     }
17330b57cec5SDimitry Andric     // Now configure them, we already pre-checked the names so we don't need to
17340b57cec5SDimitry Andric     // check the error:
17350b57cec5SDimitry Andric     BreakpointSP bp_sp;
1736480093f4SDimitry Andric     if (m_bp_id.m_breakpoint.OptionWasSet()) {
17370b57cec5SDimitry Andric       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
17389dba64beSDimitry Andric       bp_sp = target.GetBreakpointByID(bp_id);
1739480093f4SDimitry Andric       if (!bp_sp) {
17400b57cec5SDimitry Andric         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
17410b57cec5SDimitry Andric                                       bp_id);
17420b57cec5SDimitry Andric         return false;
17430b57cec5SDimitry Andric       }
17440b57cec5SDimitry Andric     }
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric     Status error;
17470b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
17480b57cec5SDimitry Andric       ConstString name(entry.c_str());
17499dba64beSDimitry Andric       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
17500b57cec5SDimitry Andric       if (!bp_name)
17510b57cec5SDimitry Andric         continue;
17520b57cec5SDimitry Andric       if (m_bp_id.m_help_string.OptionWasSet())
17530b57cec5SDimitry Andric         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric       if (bp_sp)
1756*5f7ddb14SDimitry Andric         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
17570b57cec5SDimitry Andric                                        m_access_options.GetPermissions());
17580b57cec5SDimitry Andric       else
17599dba64beSDimitry Andric         target.ConfigureBreakpointName(*bp_name,
17600b57cec5SDimitry Andric                                        m_bp_opts.GetBreakpointOptions(),
17610b57cec5SDimitry Andric                                        m_access_options.GetPermissions());
17620b57cec5SDimitry Andric     }
17630b57cec5SDimitry Andric     return true;
17640b57cec5SDimitry Andric   }
17650b57cec5SDimitry Andric 
17660b57cec5SDimitry Andric private:
17670b57cec5SDimitry Andric   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
17680b57cec5SDimitry Andric   BreakpointOptionGroup m_bp_opts;
17690b57cec5SDimitry Andric   BreakpointAccessOptionGroup m_access_options;
17700b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
17710b57cec5SDimitry Andric };
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17740b57cec5SDimitry Andric public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)17750b57cec5SDimitry Andric   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
17760b57cec5SDimitry Andric       : CommandObjectParsed(
17770b57cec5SDimitry Andric             interpreter, "add", "Add a name to the breakpoints provided.",
17780b57cec5SDimitry Andric             "breakpoint name add <command-options> <breakpoint-id-list>"),
17790b57cec5SDimitry Andric         m_name_options(), m_option_group() {
17800b57cec5SDimitry Andric     // Create the first variant for the first (and only) argument for this
17810b57cec5SDimitry Andric     // command.
17820b57cec5SDimitry Andric     CommandArgumentEntry arg1;
17830b57cec5SDimitry Andric     CommandArgumentData id_arg;
17840b57cec5SDimitry Andric     id_arg.arg_type = eArgTypeBreakpointID;
17850b57cec5SDimitry Andric     id_arg.arg_repetition = eArgRepeatOptional;
17860b57cec5SDimitry Andric     arg1.push_back(id_arg);
17870b57cec5SDimitry Andric     m_arguments.push_back(arg1);
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17900b57cec5SDimitry Andric     m_option_group.Finalize();
17910b57cec5SDimitry Andric   }
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric   ~CommandObjectBreakpointNameAdd() override = default;
17940b57cec5SDimitry Andric 
17955ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)17965ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
17975ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
17985ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
17995ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
18005ffd83dbSDimitry Andric         request, nullptr);
18015ffd83dbSDimitry Andric   }
18025ffd83dbSDimitry Andric 
GetOptions()18030b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
18040b57cec5SDimitry Andric 
18050b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)18060b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
18070b57cec5SDimitry Andric     if (!m_name_options.m_name.OptionWasSet()) {
1808*5f7ddb14SDimitry Andric       result.AppendError("No name option provided.");
18090b57cec5SDimitry Andric       return false;
18100b57cec5SDimitry Andric     }
18110b57cec5SDimitry Andric 
18129dba64beSDimitry Andric     Target &target =
18130b57cec5SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
18169dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
18170b57cec5SDimitry Andric 
18189dba64beSDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
18190b57cec5SDimitry Andric 
18200b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
18210b57cec5SDimitry Andric     if (num_breakpoints == 0) {
1822*5f7ddb14SDimitry Andric       result.AppendError("No breakpoints, cannot add names.");
18230b57cec5SDimitry Andric       return false;
18240b57cec5SDimitry Andric     }
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric     // Particular breakpoint selected; disable that breakpoint.
18270b57cec5SDimitry Andric     BreakpointIDList valid_bp_ids;
18280b57cec5SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
18299dba64beSDimitry Andric         command, &target, result, &valid_bp_ids,
18300b57cec5SDimitry Andric         BreakpointName::Permissions::PermissionKinds::listPerm);
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric     if (result.Succeeded()) {
18330b57cec5SDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1834*5f7ddb14SDimitry Andric         result.AppendError("No breakpoints specified, cannot add names.");
18350b57cec5SDimitry Andric         return false;
18360b57cec5SDimitry Andric       }
18370b57cec5SDimitry Andric       size_t num_valid_ids = valid_bp_ids.GetSize();
18380b57cec5SDimitry Andric       const char *bp_name = m_name_options.m_name.GetCurrentValue();
18390b57cec5SDimitry Andric       Status error; // This error reports illegal names, but we've already
18400b57cec5SDimitry Andric                     // checked that, so we don't need to check it again here.
18410b57cec5SDimitry Andric       for (size_t index = 0; index < num_valid_ids; index++) {
18420b57cec5SDimitry Andric         lldb::break_id_t bp_id =
18430b57cec5SDimitry Andric             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18440b57cec5SDimitry Andric         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
18459dba64beSDimitry Andric         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18460b57cec5SDimitry Andric       }
18470b57cec5SDimitry Andric     }
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric     return true;
18500b57cec5SDimitry Andric   }
18510b57cec5SDimitry Andric 
18520b57cec5SDimitry Andric private:
18530b57cec5SDimitry Andric   BreakpointNameOptionGroup m_name_options;
18540b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
18550b57cec5SDimitry Andric };
18560b57cec5SDimitry Andric 
18570b57cec5SDimitry Andric class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18580b57cec5SDimitry Andric public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)18590b57cec5SDimitry Andric   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
18600b57cec5SDimitry Andric       : CommandObjectParsed(
18610b57cec5SDimitry Andric             interpreter, "delete",
18620b57cec5SDimitry Andric             "Delete a name from the breakpoints provided.",
18630b57cec5SDimitry Andric             "breakpoint name delete <command-options> <breakpoint-id-list>"),
18640b57cec5SDimitry Andric         m_name_options(), m_option_group() {
18650b57cec5SDimitry Andric     // Create the first variant for the first (and only) argument for this
18660b57cec5SDimitry Andric     // command.
18670b57cec5SDimitry Andric     CommandArgumentEntry arg1;
18680b57cec5SDimitry Andric     CommandArgumentData id_arg;
18690b57cec5SDimitry Andric     id_arg.arg_type = eArgTypeBreakpointID;
18700b57cec5SDimitry Andric     id_arg.arg_repetition = eArgRepeatOptional;
18710b57cec5SDimitry Andric     arg1.push_back(id_arg);
18720b57cec5SDimitry Andric     m_arguments.push_back(arg1);
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18750b57cec5SDimitry Andric     m_option_group.Finalize();
18760b57cec5SDimitry Andric   }
18770b57cec5SDimitry Andric 
18780b57cec5SDimitry Andric   ~CommandObjectBreakpointNameDelete() override = default;
18790b57cec5SDimitry Andric 
18805ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)18815ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
18825ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
18835ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
18845ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
18855ffd83dbSDimitry Andric         request, nullptr);
18865ffd83dbSDimitry Andric   }
18875ffd83dbSDimitry Andric 
GetOptions()18880b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)18910b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
18920b57cec5SDimitry Andric     if (!m_name_options.m_name.OptionWasSet()) {
1893*5f7ddb14SDimitry Andric       result.AppendError("No name option provided.");
18940b57cec5SDimitry Andric       return false;
18950b57cec5SDimitry Andric     }
18960b57cec5SDimitry Andric 
18979dba64beSDimitry Andric     Target &target =
18980b57cec5SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
19019dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
19020b57cec5SDimitry Andric 
19039dba64beSDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric     size_t num_breakpoints = breakpoints.GetSize();
19060b57cec5SDimitry Andric     if (num_breakpoints == 0) {
1907*5f7ddb14SDimitry Andric       result.AppendError("No breakpoints, cannot delete names.");
19080b57cec5SDimitry Andric       return false;
19090b57cec5SDimitry Andric     }
19100b57cec5SDimitry Andric 
19110b57cec5SDimitry Andric     // Particular breakpoint selected; disable that breakpoint.
19120b57cec5SDimitry Andric     BreakpointIDList valid_bp_ids;
19130b57cec5SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
19149dba64beSDimitry Andric         command, &target, result, &valid_bp_ids,
19150b57cec5SDimitry Andric         BreakpointName::Permissions::PermissionKinds::deletePerm);
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric     if (result.Succeeded()) {
19180b57cec5SDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1919*5f7ddb14SDimitry Andric         result.AppendError("No breakpoints specified, cannot delete names.");
19200b57cec5SDimitry Andric         return false;
19210b57cec5SDimitry Andric       }
19220b57cec5SDimitry Andric       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19230b57cec5SDimitry Andric       size_t num_valid_ids = valid_bp_ids.GetSize();
19240b57cec5SDimitry Andric       for (size_t index = 0; index < num_valid_ids; index++) {
19250b57cec5SDimitry Andric         lldb::break_id_t bp_id =
19260b57cec5SDimitry Andric             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19270b57cec5SDimitry Andric         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
19289dba64beSDimitry Andric         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19290b57cec5SDimitry Andric       }
19300b57cec5SDimitry Andric     }
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric     return true;
19330b57cec5SDimitry Andric   }
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric private:
19360b57cec5SDimitry Andric   BreakpointNameOptionGroup m_name_options;
19370b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
19380b57cec5SDimitry Andric };
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric class CommandObjectBreakpointNameList : public CommandObjectParsed {
19410b57cec5SDimitry Andric public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)19420b57cec5SDimitry Andric   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
19430b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "list",
19440b57cec5SDimitry Andric                             "List either the names for a breakpoint or info "
19450b57cec5SDimitry Andric                             "about a given name.  With no arguments, lists all "
19460b57cec5SDimitry Andric                             "names",
19470b57cec5SDimitry Andric                             "breakpoint name list <command-options>"),
19480b57cec5SDimitry Andric         m_name_options(), m_option_group() {
19490b57cec5SDimitry Andric     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19500b57cec5SDimitry Andric     m_option_group.Finalize();
19510b57cec5SDimitry Andric   }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   ~CommandObjectBreakpointNameList() override = default;
19540b57cec5SDimitry Andric 
GetOptions()19550b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
19560b57cec5SDimitry Andric 
19570b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)19580b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
19599dba64beSDimitry Andric     Target &target =
19600b57cec5SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric     std::vector<std::string> name_list;
19630b57cec5SDimitry Andric     if (command.empty()) {
19649dba64beSDimitry Andric       target.GetBreakpointNames(name_list);
19650b57cec5SDimitry Andric     } else {
1966480093f4SDimitry Andric       for (const Args::ArgEntry &arg : command) {
19670b57cec5SDimitry Andric         name_list.push_back(arg.c_str());
19680b57cec5SDimitry Andric       }
19690b57cec5SDimitry Andric     }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric     if (name_list.empty()) {
19720b57cec5SDimitry Andric       result.AppendMessage("No breakpoint names found.");
19730b57cec5SDimitry Andric     } else {
19740b57cec5SDimitry Andric       for (const std::string &name_str : name_list) {
19750b57cec5SDimitry Andric         const char *name = name_str.c_str();
19760b57cec5SDimitry Andric         // First print out the options for the name:
19770b57cec5SDimitry Andric         Status error;
19789dba64beSDimitry Andric         BreakpointName *bp_name =
19799dba64beSDimitry Andric             target.FindBreakpointName(ConstString(name), false, error);
1980480093f4SDimitry Andric         if (bp_name) {
19810b57cec5SDimitry Andric           StreamString s;
19820b57cec5SDimitry Andric           result.AppendMessageWithFormat("Name: %s\n", name);
1983480093f4SDimitry Andric           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
19840b57cec5SDimitry Andric             result.AppendMessage(s.GetString());
19850b57cec5SDimitry Andric           }
19860b57cec5SDimitry Andric 
19870b57cec5SDimitry Andric           std::unique_lock<std::recursive_mutex> lock;
19889dba64beSDimitry Andric           target.GetBreakpointList().GetListMutex(lock);
19890b57cec5SDimitry Andric 
19909dba64beSDimitry Andric           BreakpointList &breakpoints = target.GetBreakpointList();
19910b57cec5SDimitry Andric           bool any_set = false;
19920b57cec5SDimitry Andric           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
19930b57cec5SDimitry Andric             if (bp_sp->MatchesName(name)) {
19940b57cec5SDimitry Andric               StreamString s;
19950b57cec5SDimitry Andric               any_set = true;
19960b57cec5SDimitry Andric               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19970b57cec5SDimitry Andric               s.EOL();
19980b57cec5SDimitry Andric               result.AppendMessage(s.GetString());
19990b57cec5SDimitry Andric             }
20000b57cec5SDimitry Andric           }
20010b57cec5SDimitry Andric           if (!any_set)
20020b57cec5SDimitry Andric             result.AppendMessage("No breakpoints using this name.");
20030b57cec5SDimitry Andric         } else {
20040b57cec5SDimitry Andric           result.AppendMessageWithFormat("Name: %s not found.\n", name);
20050b57cec5SDimitry Andric         }
20060b57cec5SDimitry Andric       }
20070b57cec5SDimitry Andric     }
20080b57cec5SDimitry Andric     return true;
20090b57cec5SDimitry Andric   }
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric private:
20120b57cec5SDimitry Andric   BreakpointNameOptionGroup m_name_options;
20130b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
20140b57cec5SDimitry Andric };
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric // CommandObjectBreakpointName
20170b57cec5SDimitry Andric class CommandObjectBreakpointName : public CommandObjectMultiword {
20180b57cec5SDimitry Andric public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)20190b57cec5SDimitry Andric   CommandObjectBreakpointName(CommandInterpreter &interpreter)
20200b57cec5SDimitry Andric       : CommandObjectMultiword(
20210b57cec5SDimitry Andric             interpreter, "name", "Commands to manage name tags for breakpoints",
20220b57cec5SDimitry Andric             "breakpoint name <subcommand> [<command-options>]") {
20230b57cec5SDimitry Andric     CommandObjectSP add_command_object(
20240b57cec5SDimitry Andric         new CommandObjectBreakpointNameAdd(interpreter));
20250b57cec5SDimitry Andric     CommandObjectSP delete_command_object(
20260b57cec5SDimitry Andric         new CommandObjectBreakpointNameDelete(interpreter));
20270b57cec5SDimitry Andric     CommandObjectSP list_command_object(
20280b57cec5SDimitry Andric         new CommandObjectBreakpointNameList(interpreter));
20290b57cec5SDimitry Andric     CommandObjectSP configure_command_object(
20300b57cec5SDimitry Andric         new CommandObjectBreakpointNameConfigure(interpreter));
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric     LoadSubCommand("add", add_command_object);
20330b57cec5SDimitry Andric     LoadSubCommand("delete", delete_command_object);
20340b57cec5SDimitry Andric     LoadSubCommand("list", list_command_object);
20350b57cec5SDimitry Andric     LoadSubCommand("configure", configure_command_object);
20360b57cec5SDimitry Andric   }
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric   ~CommandObjectBreakpointName() override = default;
20390b57cec5SDimitry Andric };
20400b57cec5SDimitry Andric 
20410b57cec5SDimitry Andric // CommandObjectBreakpointRead
20420b57cec5SDimitry Andric #pragma mark Read::CommandOptions
20439dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_read
20449dba64beSDimitry Andric #include "CommandOptions.inc"
20450b57cec5SDimitry Andric 
20460b57cec5SDimitry Andric #pragma mark Read
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric class CommandObjectBreakpointRead : public CommandObjectParsed {
20490b57cec5SDimitry Andric public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)20500b57cec5SDimitry Andric   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
20510b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint read",
20520b57cec5SDimitry Andric                             "Read and set the breakpoints previously saved to "
20530b57cec5SDimitry Andric                             "a file with \"breakpoint write\".  ",
20540b57cec5SDimitry Andric                             nullptr),
20555ffd83dbSDimitry Andric         m_options() {}
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric   ~CommandObjectBreakpointRead() override = default;
20580b57cec5SDimitry Andric 
GetOptions()20590b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
20600b57cec5SDimitry Andric 
20610b57cec5SDimitry Andric   class CommandOptions : public Options {
20620b57cec5SDimitry Andric   public:
CommandOptions()20630b57cec5SDimitry Andric     CommandOptions() : Options() {}
20640b57cec5SDimitry Andric 
20650b57cec5SDimitry Andric     ~CommandOptions() override = default;
20660b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)20670b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
20680b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
20690b57cec5SDimitry Andric       Status error;
20700b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
20710b57cec5SDimitry Andric 
20720b57cec5SDimitry Andric       switch (short_option) {
20730b57cec5SDimitry Andric       case 'f':
20745ffd83dbSDimitry Andric         m_filename.assign(std::string(option_arg));
20750b57cec5SDimitry Andric         break;
20760b57cec5SDimitry Andric       case 'N': {
20770b57cec5SDimitry Andric         Status name_error;
20780b57cec5SDimitry Andric         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20790b57cec5SDimitry Andric                                                   name_error)) {
20800b57cec5SDimitry Andric           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20810b57cec5SDimitry Andric                                          name_error.AsCString());
20820b57cec5SDimitry Andric         }
20835ffd83dbSDimitry Andric         m_names.push_back(std::string(option_arg));
20840b57cec5SDimitry Andric         break;
20850b57cec5SDimitry Andric       }
20860b57cec5SDimitry Andric       default:
20879dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
20880b57cec5SDimitry Andric       }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric       return error;
20910b57cec5SDimitry Andric     }
20920b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)20930b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
20940b57cec5SDimitry Andric       m_filename.clear();
20950b57cec5SDimitry Andric       m_names.clear();
20960b57cec5SDimitry Andric     }
20970b57cec5SDimitry Andric 
GetDefinitions()20980b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
20990b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_read_options);
21000b57cec5SDimitry Andric     }
21010b57cec5SDimitry Andric 
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)2102af732203SDimitry Andric     void HandleOptionArgumentCompletion(
2103af732203SDimitry Andric         CompletionRequest &request, OptionElementVector &opt_element_vector,
2104af732203SDimitry Andric         int opt_element_index, CommandInterpreter &interpreter) override {
2105af732203SDimitry Andric       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2106af732203SDimitry Andric       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2107af732203SDimitry Andric 
2108af732203SDimitry Andric       switch (GetDefinitions()[opt_defs_index].short_option) {
2109af732203SDimitry Andric       case 'f':
2110af732203SDimitry Andric         CommandCompletions::InvokeCommonCompletionCallbacks(
2111af732203SDimitry Andric             interpreter, CommandCompletions::eDiskFileCompletion, request,
2112af732203SDimitry Andric             nullptr);
2113af732203SDimitry Andric         break;
2114af732203SDimitry Andric 
2115af732203SDimitry Andric       case 'N':
2116af732203SDimitry Andric         llvm::Optional<FileSpec> file_spec;
2117af732203SDimitry Andric         const llvm::StringRef dash_f("-f");
2118af732203SDimitry Andric         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2119af732203SDimitry Andric           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2120af732203SDimitry Andric             file_spec.emplace(
2121af732203SDimitry Andric                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2122af732203SDimitry Andric             break;
2123af732203SDimitry Andric           }
2124af732203SDimitry Andric         }
2125af732203SDimitry Andric         if (!file_spec)
2126af732203SDimitry Andric           return;
2127af732203SDimitry Andric 
2128af732203SDimitry Andric         FileSystem::Instance().Resolve(*file_spec);
2129af732203SDimitry Andric         Status error;
2130af732203SDimitry Andric         StructuredData::ObjectSP input_data_sp =
2131af732203SDimitry Andric             StructuredData::ParseJSONFromFile(*file_spec, error);
2132af732203SDimitry Andric         if (!error.Success())
2133af732203SDimitry Andric           return;
2134af732203SDimitry Andric 
2135af732203SDimitry Andric         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2136af732203SDimitry Andric         if (!bkpt_array)
2137af732203SDimitry Andric           return;
2138af732203SDimitry Andric 
2139af732203SDimitry Andric         const size_t num_bkpts = bkpt_array->GetSize();
2140af732203SDimitry Andric         for (size_t i = 0; i < num_bkpts; i++) {
2141af732203SDimitry Andric           StructuredData::ObjectSP bkpt_object_sp =
2142af732203SDimitry Andric               bkpt_array->GetItemAtIndex(i);
2143af732203SDimitry Andric           if (!bkpt_object_sp)
2144af732203SDimitry Andric             return;
2145af732203SDimitry Andric 
2146af732203SDimitry Andric           StructuredData::Dictionary *bkpt_dict =
2147af732203SDimitry Andric               bkpt_object_sp->GetAsDictionary();
2148af732203SDimitry Andric           if (!bkpt_dict)
2149af732203SDimitry Andric             return;
2150af732203SDimitry Andric 
2151af732203SDimitry Andric           StructuredData::ObjectSP bkpt_data_sp =
2152af732203SDimitry Andric               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2153af732203SDimitry Andric           if (!bkpt_data_sp)
2154af732203SDimitry Andric             return;
2155af732203SDimitry Andric 
2156af732203SDimitry Andric           bkpt_dict = bkpt_data_sp->GetAsDictionary();
2157af732203SDimitry Andric           if (!bkpt_dict)
2158af732203SDimitry Andric             return;
2159af732203SDimitry Andric 
2160af732203SDimitry Andric           StructuredData::Array *names_array;
2161af732203SDimitry Andric 
2162af732203SDimitry Andric           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2163af732203SDimitry Andric             return;
2164af732203SDimitry Andric 
2165af732203SDimitry Andric           size_t num_names = names_array->GetSize();
2166af732203SDimitry Andric 
2167af732203SDimitry Andric           for (size_t i = 0; i < num_names; i++) {
2168af732203SDimitry Andric             llvm::StringRef name;
2169af732203SDimitry Andric             if (names_array->GetItemAtIndexAsString(i, name))
2170af732203SDimitry Andric               request.TryCompleteCurrentArg(name);
2171af732203SDimitry Andric           }
2172af732203SDimitry Andric         }
2173af732203SDimitry Andric       }
2174af732203SDimitry Andric     }
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric     std::string m_filename;
21770b57cec5SDimitry Andric     std::vector<std::string> m_names;
21780b57cec5SDimitry Andric   };
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)21810b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
21829dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget();
21830b57cec5SDimitry Andric 
21840b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
21859dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
21860b57cec5SDimitry Andric 
21870b57cec5SDimitry Andric     FileSpec input_spec(m_options.m_filename);
21880b57cec5SDimitry Andric     FileSystem::Instance().Resolve(input_spec);
21890b57cec5SDimitry Andric     BreakpointIDList new_bps;
21909dba64beSDimitry Andric     Status error = target.CreateBreakpointsFromFile(input_spec,
21919dba64beSDimitry Andric                                                     m_options.m_names, new_bps);
21920b57cec5SDimitry Andric 
21930b57cec5SDimitry Andric     if (!error.Success()) {
21940b57cec5SDimitry Andric       result.AppendError(error.AsCString());
21950b57cec5SDimitry Andric       return false;
21960b57cec5SDimitry Andric     }
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric     Stream &output_stream = result.GetOutputStream();
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric     size_t num_breakpoints = new_bps.GetSize();
22010b57cec5SDimitry Andric     if (num_breakpoints == 0) {
22020b57cec5SDimitry Andric       result.AppendMessage("No breakpoints added.");
22030b57cec5SDimitry Andric     } else {
22040b57cec5SDimitry Andric       // No breakpoint selected; show info about all currently set breakpoints.
22050b57cec5SDimitry Andric       result.AppendMessage("New breakpoints:");
22060b57cec5SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
22070b57cec5SDimitry Andric         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
22089dba64beSDimitry Andric         Breakpoint *bp = target.GetBreakpointList()
22090b57cec5SDimitry Andric                              .FindBreakpointByID(bp_id.GetBreakpointID())
22100b57cec5SDimitry Andric                              .get();
22110b57cec5SDimitry Andric         if (bp)
22120b57cec5SDimitry Andric           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22130b57cec5SDimitry Andric                              false);
22140b57cec5SDimitry Andric       }
22150b57cec5SDimitry Andric     }
22160b57cec5SDimitry Andric     return result.Succeeded();
22170b57cec5SDimitry Andric   }
22180b57cec5SDimitry Andric 
22190b57cec5SDimitry Andric private:
22200b57cec5SDimitry Andric   CommandOptions m_options;
22210b57cec5SDimitry Andric };
22220b57cec5SDimitry Andric 
22230b57cec5SDimitry Andric // CommandObjectBreakpointWrite
22240b57cec5SDimitry Andric #pragma mark Write::CommandOptions
22259dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_write
22269dba64beSDimitry Andric #include "CommandOptions.inc"
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric #pragma mark Write
22290b57cec5SDimitry Andric class CommandObjectBreakpointWrite : public CommandObjectParsed {
22300b57cec5SDimitry Andric public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)22310b57cec5SDimitry Andric   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
22320b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint write",
22330b57cec5SDimitry Andric                             "Write the breakpoints listed to a file that can "
22340b57cec5SDimitry Andric                             "be read in with \"breakpoint read\".  "
22350b57cec5SDimitry Andric                             "If given no arguments, writes all breakpoints.",
22360b57cec5SDimitry Andric                             nullptr),
22370b57cec5SDimitry Andric         m_options() {
22380b57cec5SDimitry Andric     CommandArgumentEntry arg;
22390b57cec5SDimitry Andric     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
22400b57cec5SDimitry Andric                                       eArgTypeBreakpointIDRange);
22410b57cec5SDimitry Andric     // Add the entry for the first argument for this command to the object's
22420b57cec5SDimitry Andric     // arguments vector.
22430b57cec5SDimitry Andric     m_arguments.push_back(arg);
22440b57cec5SDimitry Andric   }
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric   ~CommandObjectBreakpointWrite() override = default;
22470b57cec5SDimitry Andric 
22485ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)22495ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
22505ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
22515ffd83dbSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
22525ffd83dbSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
22535ffd83dbSDimitry Andric         request, nullptr);
22545ffd83dbSDimitry Andric   }
22555ffd83dbSDimitry Andric 
GetOptions()22560b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
22570b57cec5SDimitry Andric 
22580b57cec5SDimitry Andric   class CommandOptions : public Options {
22590b57cec5SDimitry Andric   public:
CommandOptions()22600b57cec5SDimitry Andric     CommandOptions() : Options() {}
22610b57cec5SDimitry Andric 
22620b57cec5SDimitry Andric     ~CommandOptions() override = default;
22630b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)22640b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
22650b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
22660b57cec5SDimitry Andric       Status error;
22670b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
22680b57cec5SDimitry Andric 
22690b57cec5SDimitry Andric       switch (short_option) {
22700b57cec5SDimitry Andric       case 'f':
22715ffd83dbSDimitry Andric         m_filename.assign(std::string(option_arg));
22720b57cec5SDimitry Andric         break;
22730b57cec5SDimitry Andric       case 'a':
22740b57cec5SDimitry Andric         m_append = true;
22750b57cec5SDimitry Andric         break;
22760b57cec5SDimitry Andric       default:
22779dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
22780b57cec5SDimitry Andric       }
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric       return error;
22810b57cec5SDimitry Andric     }
22820b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)22830b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
22840b57cec5SDimitry Andric       m_filename.clear();
22850b57cec5SDimitry Andric       m_append = false;
22860b57cec5SDimitry Andric     }
22870b57cec5SDimitry Andric 
GetDefinitions()22880b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
22890b57cec5SDimitry Andric       return llvm::makeArrayRef(g_breakpoint_write_options);
22900b57cec5SDimitry Andric     }
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
22930b57cec5SDimitry Andric 
22940b57cec5SDimitry Andric     std::string m_filename;
22950b57cec5SDimitry Andric     bool m_append = false;
22960b57cec5SDimitry Andric   };
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)22990b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
23009dba64beSDimitry Andric     Target &target = GetSelectedOrDummyTarget();
23010b57cec5SDimitry Andric 
23020b57cec5SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
23039dba64beSDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric     BreakpointIDList valid_bp_ids;
23060b57cec5SDimitry Andric     if (!command.empty()) {
23070b57cec5SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
23089dba64beSDimitry Andric           command, &target, result, &valid_bp_ids,
23090b57cec5SDimitry Andric           BreakpointName::Permissions::PermissionKinds::listPerm);
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric       if (!result.Succeeded()) {
23120b57cec5SDimitry Andric         result.SetStatus(eReturnStatusFailed);
23130b57cec5SDimitry Andric         return false;
23140b57cec5SDimitry Andric       }
23150b57cec5SDimitry Andric     }
23160b57cec5SDimitry Andric     FileSpec file_spec(m_options.m_filename);
23170b57cec5SDimitry Andric     FileSystem::Instance().Resolve(file_spec);
23189dba64beSDimitry Andric     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23190b57cec5SDimitry Andric                                                      m_options.m_append);
23200b57cec5SDimitry Andric     if (!error.Success()) {
23210b57cec5SDimitry Andric       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
23220b57cec5SDimitry Andric                                    error.AsCString());
23230b57cec5SDimitry Andric     }
23240b57cec5SDimitry Andric     return result.Succeeded();
23250b57cec5SDimitry Andric   }
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric private:
23280b57cec5SDimitry Andric   CommandOptions m_options;
23290b57cec5SDimitry Andric };
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric // CommandObjectMultiwordBreakpoint
23320b57cec5SDimitry Andric #pragma mark MultiwordBreakpoint
23330b57cec5SDimitry Andric 
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)23340b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
23350b57cec5SDimitry Andric     CommandInterpreter &interpreter)
23360b57cec5SDimitry Andric     : CommandObjectMultiword(
23370b57cec5SDimitry Andric           interpreter, "breakpoint",
23380b57cec5SDimitry Andric           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
23390b57cec5SDimitry Andric           "breakpoint <subcommand> [<command-options>]") {
23400b57cec5SDimitry Andric   CommandObjectSP list_command_object(
23410b57cec5SDimitry Andric       new CommandObjectBreakpointList(interpreter));
23420b57cec5SDimitry Andric   CommandObjectSP enable_command_object(
23430b57cec5SDimitry Andric       new CommandObjectBreakpointEnable(interpreter));
23440b57cec5SDimitry Andric   CommandObjectSP disable_command_object(
23450b57cec5SDimitry Andric       new CommandObjectBreakpointDisable(interpreter));
23460b57cec5SDimitry Andric   CommandObjectSP clear_command_object(
23470b57cec5SDimitry Andric       new CommandObjectBreakpointClear(interpreter));
23480b57cec5SDimitry Andric   CommandObjectSP delete_command_object(
23490b57cec5SDimitry Andric       new CommandObjectBreakpointDelete(interpreter));
23500b57cec5SDimitry Andric   CommandObjectSP set_command_object(
23510b57cec5SDimitry Andric       new CommandObjectBreakpointSet(interpreter));
23520b57cec5SDimitry Andric   CommandObjectSP command_command_object(
23530b57cec5SDimitry Andric       new CommandObjectBreakpointCommand(interpreter));
23540b57cec5SDimitry Andric   CommandObjectSP modify_command_object(
23550b57cec5SDimitry Andric       new CommandObjectBreakpointModify(interpreter));
23560b57cec5SDimitry Andric   CommandObjectSP name_command_object(
23570b57cec5SDimitry Andric       new CommandObjectBreakpointName(interpreter));
23580b57cec5SDimitry Andric   CommandObjectSP write_command_object(
23590b57cec5SDimitry Andric       new CommandObjectBreakpointWrite(interpreter));
23600b57cec5SDimitry Andric   CommandObjectSP read_command_object(
23610b57cec5SDimitry Andric       new CommandObjectBreakpointRead(interpreter));
23620b57cec5SDimitry Andric 
23630b57cec5SDimitry Andric   list_command_object->SetCommandName("breakpoint list");
23640b57cec5SDimitry Andric   enable_command_object->SetCommandName("breakpoint enable");
23650b57cec5SDimitry Andric   disable_command_object->SetCommandName("breakpoint disable");
23660b57cec5SDimitry Andric   clear_command_object->SetCommandName("breakpoint clear");
23670b57cec5SDimitry Andric   delete_command_object->SetCommandName("breakpoint delete");
23680b57cec5SDimitry Andric   set_command_object->SetCommandName("breakpoint set");
23690b57cec5SDimitry Andric   command_command_object->SetCommandName("breakpoint command");
23700b57cec5SDimitry Andric   modify_command_object->SetCommandName("breakpoint modify");
23710b57cec5SDimitry Andric   name_command_object->SetCommandName("breakpoint name");
23720b57cec5SDimitry Andric   write_command_object->SetCommandName("breakpoint write");
23730b57cec5SDimitry Andric   read_command_object->SetCommandName("breakpoint read");
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric   LoadSubCommand("list", list_command_object);
23760b57cec5SDimitry Andric   LoadSubCommand("enable", enable_command_object);
23770b57cec5SDimitry Andric   LoadSubCommand("disable", disable_command_object);
23780b57cec5SDimitry Andric   LoadSubCommand("clear", clear_command_object);
23790b57cec5SDimitry Andric   LoadSubCommand("delete", delete_command_object);
23800b57cec5SDimitry Andric   LoadSubCommand("set", set_command_object);
23810b57cec5SDimitry Andric   LoadSubCommand("command", command_command_object);
23820b57cec5SDimitry Andric   LoadSubCommand("modify", modify_command_object);
23830b57cec5SDimitry Andric   LoadSubCommand("name", name_command_object);
23840b57cec5SDimitry Andric   LoadSubCommand("write", write_command_object);
23850b57cec5SDimitry Andric   LoadSubCommand("read", read_command_object);
23860b57cec5SDimitry Andric }
23870b57cec5SDimitry Andric 
23880b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
23890b57cec5SDimitry Andric 
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2390480093f4SDimitry Andric void CommandObjectMultiwordBreakpoint::VerifyIDs(
2391480093f4SDimitry Andric     Args &args, Target *target, bool allow_locations,
2392480093f4SDimitry Andric     CommandReturnObject &result, BreakpointIDList *valid_ids,
2393480093f4SDimitry Andric     BreakpointName::Permissions ::PermissionKinds purpose) {
23940b57cec5SDimitry Andric   // args can be strings representing 1). integers (for breakpoint ids)
23950b57cec5SDimitry Andric   //                                  2). the full breakpoint & location
23960b57cec5SDimitry Andric   //                                  canonical representation
23970b57cec5SDimitry Andric   //                                  3). the word "to" or a hyphen,
23980b57cec5SDimitry Andric   //                                  representing a range (in which case there
23990b57cec5SDimitry Andric   //                                      had *better* be an entry both before &
24000b57cec5SDimitry Andric   //                                      after of one of the first two types.
24010b57cec5SDimitry Andric   //                                  4). A breakpoint name
24020b57cec5SDimitry Andric   // If args is empty, we will use the last created breakpoint (if there is
24030b57cec5SDimitry Andric   // one.)
24040b57cec5SDimitry Andric 
24050b57cec5SDimitry Andric   Args temp_args;
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   if (args.empty()) {
24080b57cec5SDimitry Andric     if (target->GetLastCreatedBreakpoint()) {
24090b57cec5SDimitry Andric       valid_ids->AddBreakpointID(BreakpointID(
24100b57cec5SDimitry Andric           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
24110b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
24120b57cec5SDimitry Andric     } else {
24130b57cec5SDimitry Andric       result.AppendError(
24140b57cec5SDimitry Andric           "No breakpoint specified and no last created breakpoint.");
24150b57cec5SDimitry Andric     }
24160b57cec5SDimitry Andric     return;
24170b57cec5SDimitry Andric   }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
24200b57cec5SDimitry Andric   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
24210b57cec5SDimitry Andric   // id range strings over; instead generate a list of strings for all the
24220b57cec5SDimitry Andric   // breakpoint ids in the range, and shove all of those breakpoint id strings
24230b57cec5SDimitry Andric   // into TEMP_ARGS.
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
24260b57cec5SDimitry Andric                                            purpose, result, temp_args);
24270b57cec5SDimitry Andric 
24280b57cec5SDimitry Andric   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
24290b57cec5SDimitry Andric   // BreakpointIDList:
24300b57cec5SDimitry Andric 
24310b57cec5SDimitry Andric   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
24320b57cec5SDimitry Andric 
24330b57cec5SDimitry Andric   // At this point,  all of the breakpoint ids that the user passed in have
24340b57cec5SDimitry Andric   // been converted to breakpoint IDs and put into valid_ids.
24350b57cec5SDimitry Andric 
24360b57cec5SDimitry Andric   if (result.Succeeded()) {
24370b57cec5SDimitry Andric     // Now that we've converted everything from args into a list of breakpoint
24380b57cec5SDimitry Andric     // ids, go through our tentative list of breakpoint id's and verify that
24390b57cec5SDimitry Andric     // they correspond to valid/currently set breakpoints.
24400b57cec5SDimitry Andric 
24410b57cec5SDimitry Andric     const size_t count = valid_ids->GetSize();
24420b57cec5SDimitry Andric     for (size_t i = 0; i < count; ++i) {
24430b57cec5SDimitry Andric       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
24440b57cec5SDimitry Andric       Breakpoint *breakpoint =
24450b57cec5SDimitry Andric           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
24460b57cec5SDimitry Andric       if (breakpoint != nullptr) {
24470b57cec5SDimitry Andric         const size_t num_locations = breakpoint->GetNumLocations();
24480b57cec5SDimitry Andric         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
24490b57cec5SDimitry Andric           StreamString id_str;
24500b57cec5SDimitry Andric           BreakpointID::GetCanonicalReference(
24510b57cec5SDimitry Andric               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
24520b57cec5SDimitry Andric           i = valid_ids->GetSize() + 1;
24530b57cec5SDimitry Andric           result.AppendErrorWithFormat(
24540b57cec5SDimitry Andric               "'%s' is not a currently valid breakpoint/location id.\n",
24550b57cec5SDimitry Andric               id_str.GetData());
24560b57cec5SDimitry Andric         }
24570b57cec5SDimitry Andric       } else {
24580b57cec5SDimitry Andric         i = valid_ids->GetSize() + 1;
24590b57cec5SDimitry Andric         result.AppendErrorWithFormat(
24600b57cec5SDimitry Andric             "'%d' is not a currently valid breakpoint ID.\n",
24610b57cec5SDimitry Andric             cur_bp_id.GetBreakpointID());
24620b57cec5SDimitry Andric       }
24630b57cec5SDimitry Andric     }
24640b57cec5SDimitry Andric   }
24650b57cec5SDimitry Andric }
2466