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"
16fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
170b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
199dba64beSDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h"
21e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueFileColonLine.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueString.h"
230b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueUInt64.h"
240b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
250b57cec5SDimitry Andric #include "lldb/Target/Language.h"
260b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
270b57cec5SDimitry Andric #include "lldb/Target/Target.h"
280b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h"
290b57cec5SDimitry Andric #include "lldb/Utility/RegularExpression.h"
300b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #include <memory>
33bdd1243dSDimitry Andric #include <optional>
340b57cec5SDimitry Andric #include <vector>
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric using namespace lldb;
370b57cec5SDimitry Andric using namespace lldb_private;
380b57cec5SDimitry Andric
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)390b57cec5SDimitry Andric static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
400b57cec5SDimitry Andric lldb::DescriptionLevel level) {
410b57cec5SDimitry Andric s->IndentMore();
420b57cec5SDimitry Andric bp->GetDescription(s, level, true);
430b57cec5SDimitry Andric s->IndentLess();
440b57cec5SDimitry Andric s->EOL();
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric // Modifiable Breakpoint Options
480b57cec5SDimitry Andric #pragma mark Modify::CommandOptions
499dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_modify
509dba64beSDimitry Andric #include "CommandOptions.inc"
519dba64beSDimitry Andric
52480093f4SDimitry Andric class lldb_private::BreakpointOptionGroup : public OptionGroup {
530b57cec5SDimitry Andric public:
BreakpointOptionGroup()5404eeddc0SDimitry Andric BreakpointOptionGroup() : m_bp_opts(false) {}
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric ~BreakpointOptionGroup() override = default;
570b57cec5SDimitry Andric
GetDefinitions()580b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
59bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_modify_options);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)620b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
630b57cec5SDimitry Andric ExecutionContext *execution_context) override {
640b57cec5SDimitry Andric Status error;
65480093f4SDimitry Andric const int short_option =
66480093f4SDimitry Andric g_breakpoint_modify_options[option_idx].short_option;
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric switch (short_option) {
690b57cec5SDimitry Andric case 'c':
700b57cec5SDimitry Andric // Normally an empty breakpoint condition marks is as unset. But we need
710b57cec5SDimitry Andric // to say it was passed in.
720b57cec5SDimitry Andric m_bp_opts.SetCondition(option_arg.str().c_str());
730b57cec5SDimitry Andric m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
740b57cec5SDimitry Andric break;
750b57cec5SDimitry Andric case 'C':
765ffd83dbSDimitry Andric m_commands.push_back(std::string(option_arg));
770b57cec5SDimitry Andric break;
780b57cec5SDimitry Andric case 'd':
790b57cec5SDimitry Andric m_bp_opts.SetEnabled(false);
800b57cec5SDimitry Andric break;
810b57cec5SDimitry Andric case 'e':
820b57cec5SDimitry Andric m_bp_opts.SetEnabled(true);
830b57cec5SDimitry Andric break;
840b57cec5SDimitry Andric case 'G': {
850b57cec5SDimitry Andric bool value, success;
860b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
870b57cec5SDimitry Andric if (success) {
880b57cec5SDimitry Andric m_bp_opts.SetAutoContinue(value);
890b57cec5SDimitry Andric } else
900b57cec5SDimitry Andric error.SetErrorStringWithFormat(
910b57cec5SDimitry Andric "invalid boolean value '%s' passed for -G option",
920b57cec5SDimitry Andric option_arg.str().c_str());
93480093f4SDimitry Andric } break;
94480093f4SDimitry Andric case 'i': {
950b57cec5SDimitry Andric uint32_t ignore_count;
960b57cec5SDimitry Andric if (option_arg.getAsInteger(0, ignore_count))
970b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid ignore count '%s'",
980b57cec5SDimitry Andric option_arg.str().c_str());
990b57cec5SDimitry Andric else
1000b57cec5SDimitry Andric m_bp_opts.SetIgnoreCount(ignore_count);
101480093f4SDimitry Andric } break;
1020b57cec5SDimitry Andric case 'o': {
1030b57cec5SDimitry Andric bool value, success;
1040b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
1050b57cec5SDimitry Andric if (success) {
1060b57cec5SDimitry Andric m_bp_opts.SetOneShot(value);
1070b57cec5SDimitry Andric } else
1080b57cec5SDimitry Andric error.SetErrorStringWithFormat(
1090b57cec5SDimitry Andric "invalid boolean value '%s' passed for -o option",
1100b57cec5SDimitry Andric option_arg.str().c_str());
1110b57cec5SDimitry Andric } break;
112480093f4SDimitry Andric case 't': {
1130b57cec5SDimitry Andric lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
114349cc55cSDimitry Andric if (option_arg == "current") {
115349cc55cSDimitry Andric if (!execution_context) {
116349cc55cSDimitry Andric error.SetErrorStringWithFormat("No context to determine current "
117349cc55cSDimitry Andric "thread");
118349cc55cSDimitry Andric } else {
119349cc55cSDimitry Andric ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
120349cc55cSDimitry Andric if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
121349cc55cSDimitry Andric error.SetErrorStringWithFormat("No currently selected thread");
122349cc55cSDimitry Andric } else {
123349cc55cSDimitry Andric thread_id = ctx_thread_sp->GetID();
124349cc55cSDimitry Andric }
125349cc55cSDimitry Andric }
126bdd1243dSDimitry Andric } else if (option_arg.getAsInteger(0, thread_id)) {
1270b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid thread id string '%s'",
1280b57cec5SDimitry Andric option_arg.str().c_str());
1290b57cec5SDimitry Andric }
130bdd1243dSDimitry Andric if (thread_id != LLDB_INVALID_THREAD_ID)
1310b57cec5SDimitry Andric m_bp_opts.SetThreadID(thread_id);
132480093f4SDimitry Andric } break;
1330b57cec5SDimitry Andric case 'T':
1340b57cec5SDimitry Andric m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
1350b57cec5SDimitry Andric break;
1360b57cec5SDimitry Andric case 'q':
1370b57cec5SDimitry Andric m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
1380b57cec5SDimitry Andric break;
139480093f4SDimitry Andric case 'x': {
1400b57cec5SDimitry Andric uint32_t thread_index = UINT32_MAX;
141bdd1243dSDimitry Andric if (option_arg.getAsInteger(0, thread_index)) {
1420b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid thread index string '%s'",
1430b57cec5SDimitry Andric option_arg.str().c_str());
144bdd1243dSDimitry Andric } else {
1450b57cec5SDimitry Andric m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
146bdd1243dSDimitry Andric }
147480093f4SDimitry Andric } break;
1480b57cec5SDimitry Andric default:
1499dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric return error;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1550b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1560b57cec5SDimitry Andric m_bp_opts.Clear();
1570b57cec5SDimitry Andric m_commands.clear();
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
OptionParsingFinished(ExecutionContext * execution_context)1600b57cec5SDimitry Andric Status OptionParsingFinished(ExecutionContext *execution_context) override {
161480093f4SDimitry Andric if (!m_commands.empty()) {
1629dba64beSDimitry Andric auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric for (std::string &str : m_commands)
1650b57cec5SDimitry Andric cmd_data->user_source.AppendString(str);
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric cmd_data->stop_on_error = true;
1680b57cec5SDimitry Andric m_bp_opts.SetCommandDataCallback(cmd_data);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric return Status();
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric
GetBreakpointOptions()173480093f4SDimitry Andric const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric std::vector<std::string> m_commands;
1760b57cec5SDimitry Andric BreakpointOptions m_bp_opts;
1770b57cec5SDimitry Andric };
1789dba64beSDimitry Andric
1799dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_dummy
1809dba64beSDimitry Andric #include "CommandOptions.inc"
1810b57cec5SDimitry Andric
182480093f4SDimitry Andric class BreakpointDummyOptionGroup : public OptionGroup {
1830b57cec5SDimitry Andric public:
18481ad6265SDimitry Andric BreakpointDummyOptionGroup() = default;
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric ~BreakpointDummyOptionGroup() override = default;
1870b57cec5SDimitry Andric
GetDefinitions()1880b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
189bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_dummy_options);
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1920b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1930b57cec5SDimitry Andric ExecutionContext *execution_context) override {
1940b57cec5SDimitry Andric Status error;
195480093f4SDimitry Andric const int short_option =
196480093f4SDimitry Andric g_breakpoint_dummy_options[option_idx].short_option;
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric switch (short_option) {
1990b57cec5SDimitry Andric case 'D':
2000b57cec5SDimitry Andric m_use_dummy = true;
2010b57cec5SDimitry Andric break;
2020b57cec5SDimitry Andric default:
2039dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric return error;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)2090b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
2100b57cec5SDimitry Andric m_use_dummy = false;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric bool m_use_dummy;
2140b57cec5SDimitry Andric };
2150b57cec5SDimitry Andric
2169dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_set
2179dba64beSDimitry Andric #include "CommandOptions.inc"
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric // CommandObjectBreakpointSet
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric class CommandObjectBreakpointSet : public CommandObjectParsed {
2220b57cec5SDimitry Andric public:
2230b57cec5SDimitry Andric enum BreakpointSetType {
2240b57cec5SDimitry Andric eSetTypeInvalid,
2250b57cec5SDimitry Andric eSetTypeFileAndLine,
2260b57cec5SDimitry Andric eSetTypeAddress,
2270b57cec5SDimitry Andric eSetTypeFunctionName,
2280b57cec5SDimitry Andric eSetTypeFunctionRegexp,
2290b57cec5SDimitry Andric eSetTypeSourceRegexp,
2300b57cec5SDimitry Andric eSetTypeException,
2310b57cec5SDimitry Andric eSetTypeScripted,
2320b57cec5SDimitry Andric };
2330b57cec5SDimitry Andric
CommandObjectBreakpointSet(CommandInterpreter & interpreter)2340b57cec5SDimitry Andric CommandObjectBreakpointSet(CommandInterpreter &interpreter)
2350b57cec5SDimitry Andric : CommandObjectParsed(
2360b57cec5SDimitry Andric interpreter, "breakpoint set",
2370b57cec5SDimitry Andric "Sets a breakpoint or set of breakpoints in the executable.",
2380b57cec5SDimitry Andric "breakpoint set <cmd-options>"),
23904eeddc0SDimitry Andric m_python_class_options("scripted breakpoint", true, 'P') {
2400b57cec5SDimitry Andric // We're picking up all the normal options, commands and disable.
241480093f4SDimitry Andric m_all_options.Append(&m_python_class_options,
242480093f4SDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
2430b57cec5SDimitry Andric m_all_options.Append(&m_bp_opts,
2440b57cec5SDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
2450b57cec5SDimitry Andric LLDB_OPT_SET_ALL);
2460b57cec5SDimitry Andric m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2470b57cec5SDimitry Andric m_all_options.Append(&m_options);
2480b57cec5SDimitry Andric m_all_options.Finalize();
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric ~CommandObjectBreakpointSet() override = default;
2520b57cec5SDimitry Andric
GetOptions()2530b57cec5SDimitry Andric Options *GetOptions() override { return &m_all_options; }
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric class CommandOptions : public OptionGroup {
2560b57cec5SDimitry Andric public:
25781ad6265SDimitry Andric CommandOptions() = default;
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric ~CommandOptions() override = default;
2600b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2610b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2620b57cec5SDimitry Andric ExecutionContext *execution_context) override {
2630b57cec5SDimitry Andric Status error;
264480093f4SDimitry Andric const int short_option =
265480093f4SDimitry Andric g_breakpoint_set_options[option_idx].short_option;
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric switch (short_option) {
2680b57cec5SDimitry Andric case 'a': {
2690b57cec5SDimitry Andric m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
2700b57cec5SDimitry Andric LLDB_INVALID_ADDRESS, &error);
2710b57cec5SDimitry Andric } break;
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric case 'A':
2740b57cec5SDimitry Andric m_all_files = true;
2750b57cec5SDimitry Andric break;
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric case 'b':
2785ffd83dbSDimitry Andric m_func_names.push_back(std::string(option_arg));
2790b57cec5SDimitry Andric m_func_name_type_mask |= eFunctionNameTypeBase;
2800b57cec5SDimitry Andric break;
2810b57cec5SDimitry Andric
2825ffd83dbSDimitry Andric case 'u':
2830b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_column))
2840b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid column number: %s",
2850b57cec5SDimitry Andric option_arg.str().c_str());
2860b57cec5SDimitry Andric break;
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric case 'E': {
2890b57cec5SDimitry Andric LanguageType language = Language::GetLanguageTypeFromString(option_arg);
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric switch (language) {
2920b57cec5SDimitry Andric case eLanguageTypeC89:
2930b57cec5SDimitry Andric case eLanguageTypeC:
2940b57cec5SDimitry Andric case eLanguageTypeC99:
2950b57cec5SDimitry Andric case eLanguageTypeC11:
2960b57cec5SDimitry Andric m_exception_language = eLanguageTypeC;
2970b57cec5SDimitry Andric break;
2980b57cec5SDimitry Andric case eLanguageTypeC_plus_plus:
2990b57cec5SDimitry Andric case eLanguageTypeC_plus_plus_03:
3000b57cec5SDimitry Andric case eLanguageTypeC_plus_plus_11:
3010b57cec5SDimitry Andric case eLanguageTypeC_plus_plus_14:
3020b57cec5SDimitry Andric m_exception_language = eLanguageTypeC_plus_plus;
3030b57cec5SDimitry Andric break;
3040b57cec5SDimitry Andric case eLanguageTypeObjC:
3050b57cec5SDimitry Andric m_exception_language = eLanguageTypeObjC;
3060b57cec5SDimitry Andric break;
3070b57cec5SDimitry Andric case eLanguageTypeObjC_plus_plus:
3080b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3090b57cec5SDimitry Andric "Set exception breakpoints separately for c++ and objective-c");
3100b57cec5SDimitry Andric break;
3110b57cec5SDimitry Andric case eLanguageTypeUnknown:
3120b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3130b57cec5SDimitry Andric "Unknown language type: '%s' for exception breakpoint",
3140b57cec5SDimitry Andric option_arg.str().c_str());
3150b57cec5SDimitry Andric break;
3160b57cec5SDimitry Andric default:
3170b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3180b57cec5SDimitry Andric "Unsupported language type: '%s' for exception breakpoint",
3190b57cec5SDimitry Andric option_arg.str().c_str());
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric } break;
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric case 'f':
3240b57cec5SDimitry Andric m_filenames.AppendIfUnique(FileSpec(option_arg));
3250b57cec5SDimitry Andric break;
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric case 'F':
3285ffd83dbSDimitry Andric m_func_names.push_back(std::string(option_arg));
3290b57cec5SDimitry Andric m_func_name_type_mask |= eFunctionNameTypeFull;
3300b57cec5SDimitry Andric break;
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric case 'h': {
3330b57cec5SDimitry Andric bool success;
3340b57cec5SDimitry Andric m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
3350b57cec5SDimitry Andric if (!success)
3360b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3370b57cec5SDimitry Andric "Invalid boolean value for on-catch option: '%s'",
3380b57cec5SDimitry Andric option_arg.str().c_str());
3390b57cec5SDimitry Andric } break;
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric case 'H':
3420b57cec5SDimitry Andric m_hardware = true;
3430b57cec5SDimitry Andric break;
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric case 'K': {
3460b57cec5SDimitry Andric bool success;
3470b57cec5SDimitry Andric bool value;
3480b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, true, &success);
3490b57cec5SDimitry Andric if (value)
3500b57cec5SDimitry Andric m_skip_prologue = eLazyBoolYes;
3510b57cec5SDimitry Andric else
3520b57cec5SDimitry Andric m_skip_prologue = eLazyBoolNo;
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric if (!success)
3550b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3560b57cec5SDimitry Andric "Invalid boolean value for skip prologue option: '%s'",
3570b57cec5SDimitry Andric option_arg.str().c_str());
3580b57cec5SDimitry Andric } break;
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric case 'l':
3610b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_line_num))
3620b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid line number: %s.",
3630b57cec5SDimitry Andric option_arg.str().c_str());
3640b57cec5SDimitry Andric break;
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric case 'L':
3670b57cec5SDimitry Andric m_language = Language::GetLanguageTypeFromString(option_arg);
3680b57cec5SDimitry Andric if (m_language == eLanguageTypeUnknown)
3690b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3700b57cec5SDimitry Andric "Unknown language type: '%s' for breakpoint",
3710b57cec5SDimitry Andric option_arg.str().c_str());
3720b57cec5SDimitry Andric break;
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric case 'm': {
3750b57cec5SDimitry Andric bool success;
3760b57cec5SDimitry Andric bool value;
3770b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, true, &success);
3780b57cec5SDimitry Andric if (value)
3790b57cec5SDimitry Andric m_move_to_nearest_code = eLazyBoolYes;
3800b57cec5SDimitry Andric else
3810b57cec5SDimitry Andric m_move_to_nearest_code = eLazyBoolNo;
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric if (!success)
3840b57cec5SDimitry Andric error.SetErrorStringWithFormat(
3850b57cec5SDimitry Andric "Invalid boolean value for move-to-nearest-code option: '%s'",
3860b57cec5SDimitry Andric option_arg.str().c_str());
3870b57cec5SDimitry Andric break;
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric case 'M':
3915ffd83dbSDimitry Andric m_func_names.push_back(std::string(option_arg));
3920b57cec5SDimitry Andric m_func_name_type_mask |= eFunctionNameTypeMethod;
3930b57cec5SDimitry Andric break;
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric case 'n':
3965ffd83dbSDimitry Andric m_func_names.push_back(std::string(option_arg));
3970b57cec5SDimitry Andric m_func_name_type_mask |= eFunctionNameTypeAuto;
3980b57cec5SDimitry Andric break;
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric case 'N': {
4010b57cec5SDimitry Andric if (BreakpointID::StringIsBreakpointName(option_arg, error))
4025ffd83dbSDimitry Andric m_breakpoint_names.push_back(std::string(option_arg));
4030b57cec5SDimitry Andric else
4040b57cec5SDimitry Andric error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
4050b57cec5SDimitry Andric option_arg.str().c_str());
4060b57cec5SDimitry Andric break;
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric case 'R': {
4100b57cec5SDimitry Andric lldb::addr_t tmp_offset_addr;
4110b57cec5SDimitry Andric tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
4120b57cec5SDimitry Andric option_arg, 0, &error);
4130b57cec5SDimitry Andric if (error.Success())
4140b57cec5SDimitry Andric m_offset_addr = tmp_offset_addr;
4150b57cec5SDimitry Andric } break;
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric case 'O':
4180b57cec5SDimitry Andric m_exception_extra_args.AppendArgument("-O");
4190b57cec5SDimitry Andric m_exception_extra_args.AppendArgument(option_arg);
4200b57cec5SDimitry Andric break;
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric case 'p':
4235ffd83dbSDimitry Andric m_source_text_regexp.assign(std::string(option_arg));
4240b57cec5SDimitry Andric break;
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric case 'r':
4275ffd83dbSDimitry Andric m_func_regexp.assign(std::string(option_arg));
4280b57cec5SDimitry Andric break;
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric case 's':
4310b57cec5SDimitry Andric m_modules.AppendIfUnique(FileSpec(option_arg));
4320b57cec5SDimitry Andric break;
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andric case 'S':
4355ffd83dbSDimitry Andric m_func_names.push_back(std::string(option_arg));
4360b57cec5SDimitry Andric m_func_name_type_mask |= eFunctionNameTypeSelector;
4370b57cec5SDimitry Andric break;
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric case 'w': {
4400b57cec5SDimitry Andric bool success;
4410b57cec5SDimitry Andric m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
4420b57cec5SDimitry Andric if (!success)
4430b57cec5SDimitry Andric error.SetErrorStringWithFormat(
4440b57cec5SDimitry Andric "Invalid boolean value for on-throw option: '%s'",
4450b57cec5SDimitry Andric option_arg.str().c_str());
4460b57cec5SDimitry Andric } break;
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric case 'X':
4495ffd83dbSDimitry Andric m_source_regex_func_names.insert(std::string(option_arg));
4500b57cec5SDimitry Andric break;
4510b57cec5SDimitry Andric
452e8d8bef9SDimitry Andric case 'y':
453e8d8bef9SDimitry Andric {
454e8d8bef9SDimitry Andric OptionValueFileColonLine value;
455e8d8bef9SDimitry Andric Status fcl_err = value.SetValueFromString(option_arg);
456e8d8bef9SDimitry Andric if (!fcl_err.Success()) {
457e8d8bef9SDimitry Andric error.SetErrorStringWithFormat(
458e8d8bef9SDimitry Andric "Invalid value for file:line specifier: %s",
459e8d8bef9SDimitry Andric fcl_err.AsCString());
460e8d8bef9SDimitry Andric } else {
461e8d8bef9SDimitry Andric m_filenames.AppendIfUnique(value.GetFileSpec());
462e8d8bef9SDimitry Andric m_line_num = value.GetLineNumber();
463e8d8bef9SDimitry Andric m_column = value.GetColumnNumber();
464e8d8bef9SDimitry Andric }
465e8d8bef9SDimitry Andric } break;
466e8d8bef9SDimitry Andric
4670b57cec5SDimitry Andric default:
4689dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric return error;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)4740b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
4750b57cec5SDimitry Andric m_filenames.Clear();
4760b57cec5SDimitry Andric m_line_num = 0;
4770b57cec5SDimitry Andric m_column = 0;
4780b57cec5SDimitry Andric m_func_names.clear();
4790b57cec5SDimitry Andric m_func_name_type_mask = eFunctionNameTypeNone;
4800b57cec5SDimitry Andric m_func_regexp.clear();
4810b57cec5SDimitry Andric m_source_text_regexp.clear();
4820b57cec5SDimitry Andric m_modules.Clear();
4830b57cec5SDimitry Andric m_load_addr = LLDB_INVALID_ADDRESS;
4840b57cec5SDimitry Andric m_offset_addr = 0;
4850b57cec5SDimitry Andric m_catch_bp = false;
4860b57cec5SDimitry Andric m_throw_bp = true;
4870b57cec5SDimitry Andric m_hardware = false;
4880b57cec5SDimitry Andric m_exception_language = eLanguageTypeUnknown;
4890b57cec5SDimitry Andric m_language = lldb::eLanguageTypeUnknown;
4900b57cec5SDimitry Andric m_skip_prologue = eLazyBoolCalculate;
4910b57cec5SDimitry Andric m_breakpoint_names.clear();
4920b57cec5SDimitry Andric m_all_files = false;
4930b57cec5SDimitry Andric m_exception_extra_args.Clear();
4940b57cec5SDimitry Andric m_move_to_nearest_code = eLazyBoolCalculate;
4950b57cec5SDimitry Andric m_source_regex_func_names.clear();
4960b57cec5SDimitry Andric m_current_key.clear();
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric
GetDefinitions()4990b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
500bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_set_options);
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric // Instance variables to hold the values for command options.
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric std::string m_condition;
5060b57cec5SDimitry Andric FileSpecList m_filenames;
507fe6060f1SDimitry Andric uint32_t m_line_num = 0;
508fe6060f1SDimitry Andric uint32_t m_column = 0;
5090b57cec5SDimitry Andric std::vector<std::string> m_func_names;
5100b57cec5SDimitry Andric std::vector<std::string> m_breakpoint_names;
511fe6060f1SDimitry Andric lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5120b57cec5SDimitry Andric std::string m_func_regexp;
5130b57cec5SDimitry Andric std::string m_source_text_regexp;
5140b57cec5SDimitry Andric FileSpecList m_modules;
515fe6060f1SDimitry Andric lldb::addr_t m_load_addr = 0;
5160b57cec5SDimitry Andric lldb::addr_t m_offset_addr;
517fe6060f1SDimitry Andric bool m_catch_bp = false;
518fe6060f1SDimitry Andric bool m_throw_bp = true;
519fe6060f1SDimitry Andric bool m_hardware = false; // Request to use hardware breakpoints
520fe6060f1SDimitry Andric lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
521fe6060f1SDimitry Andric lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
522fe6060f1SDimitry Andric LazyBool m_skip_prologue = eLazyBoolCalculate;
523fe6060f1SDimitry Andric bool m_all_files = false;
5240b57cec5SDimitry Andric Args m_exception_extra_args;
525fe6060f1SDimitry Andric LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
5260b57cec5SDimitry Andric std::unordered_set<std::string> m_source_regex_func_names;
5270b57cec5SDimitry Andric std::string m_current_key;
5280b57cec5SDimitry Andric };
5290b57cec5SDimitry Andric
5300b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)531c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
5329dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric // The following are the various types of breakpoints that could be set:
5350b57cec5SDimitry Andric // 1). -f -l -p [-s -g] (setting breakpoint by source location)
5360b57cec5SDimitry Andric // 2). -a [-s -g] (setting breakpoint by address)
5370b57cec5SDimitry Andric // 3). -n [-s -g] (setting breakpoint by function name)
5380b57cec5SDimitry Andric // 4). -r [-s -g] (setting breakpoint by function name regular
5390b57cec5SDimitry Andric // expression)
5400b57cec5SDimitry Andric // 5). -p -f (setting a breakpoint by comparing a reg-exp
5410b57cec5SDimitry Andric // to source text)
5420b57cec5SDimitry Andric // 6). -E [-w -h] (setting a breakpoint for exceptions for a
5430b57cec5SDimitry Andric // given language.)
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric BreakpointSetType break_type = eSetTypeInvalid;
5460b57cec5SDimitry Andric
547480093f4SDimitry Andric if (!m_python_class_options.GetName().empty())
5480b57cec5SDimitry Andric break_type = eSetTypeScripted;
5490b57cec5SDimitry Andric else if (m_options.m_line_num != 0)
5500b57cec5SDimitry Andric break_type = eSetTypeFileAndLine;
5510b57cec5SDimitry Andric else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
5520b57cec5SDimitry Andric break_type = eSetTypeAddress;
5530b57cec5SDimitry Andric else if (!m_options.m_func_names.empty())
5540b57cec5SDimitry Andric break_type = eSetTypeFunctionName;
5550b57cec5SDimitry Andric else if (!m_options.m_func_regexp.empty())
5560b57cec5SDimitry Andric break_type = eSetTypeFunctionRegexp;
5570b57cec5SDimitry Andric else if (!m_options.m_source_text_regexp.empty())
5580b57cec5SDimitry Andric break_type = eSetTypeSourceRegexp;
5590b57cec5SDimitry Andric else if (m_options.m_exception_language != eLanguageTypeUnknown)
5600b57cec5SDimitry Andric break_type = eSetTypeException;
5610b57cec5SDimitry Andric
5620b57cec5SDimitry Andric BreakpointSP bp_sp = nullptr;
5630b57cec5SDimitry Andric FileSpec module_spec;
5640b57cec5SDimitry Andric const bool internal = false;
5650b57cec5SDimitry Andric
5660b57cec5SDimitry Andric // If the user didn't specify skip-prologue, having an offset should turn
5670b57cec5SDimitry Andric // that off.
5680b57cec5SDimitry Andric if (m_options.m_offset_addr != 0 &&
5690b57cec5SDimitry Andric m_options.m_skip_prologue == eLazyBoolCalculate)
5700b57cec5SDimitry Andric m_options.m_skip_prologue = eLazyBoolNo;
5710b57cec5SDimitry Andric
5720b57cec5SDimitry Andric switch (break_type) {
5730b57cec5SDimitry Andric case eSetTypeFileAndLine: // Breakpoint by source position
5740b57cec5SDimitry Andric {
5750b57cec5SDimitry Andric FileSpec file;
5760b57cec5SDimitry Andric const size_t num_files = m_options.m_filenames.GetSize();
5770b57cec5SDimitry Andric if (num_files == 0) {
5780b57cec5SDimitry Andric if (!GetDefaultFile(target, file, result)) {
5790b57cec5SDimitry Andric result.AppendError("No file supplied and no default file available.");
580c9157d92SDimitry Andric return;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric } else if (num_files > 1) {
5830b57cec5SDimitry Andric result.AppendError("Only one file at a time is allowed for file and "
5840b57cec5SDimitry Andric "line breakpoints.");
585c9157d92SDimitry Andric return;
5860b57cec5SDimitry Andric } else
5870b57cec5SDimitry Andric file = m_options.m_filenames.GetFileSpecAtIndex(0);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric // Only check for inline functions if
5900b57cec5SDimitry Andric LazyBool check_inlines = eLazyBoolCalculate;
5910b57cec5SDimitry Andric
5929dba64beSDimitry Andric bp_sp = target.CreateBreakpoint(
5939dba64beSDimitry Andric &(m_options.m_modules), file, m_options.m_line_num,
5949dba64beSDimitry Andric m_options.m_column, m_options.m_offset_addr, check_inlines,
5959dba64beSDimitry Andric m_options.m_skip_prologue, internal, m_options.m_hardware,
5960b57cec5SDimitry Andric m_options.m_move_to_nearest_code);
5970b57cec5SDimitry Andric } break;
5980b57cec5SDimitry Andric
5990b57cec5SDimitry Andric case eSetTypeAddress: // Breakpoint by address
6000b57cec5SDimitry Andric {
6010b57cec5SDimitry Andric // If a shared library has been specified, make an lldb_private::Address
6020b57cec5SDimitry Andric // with the library, and use that. That way the address breakpoint
6030b57cec5SDimitry Andric // will track the load location of the library.
6040b57cec5SDimitry Andric size_t num_modules_specified = m_options.m_modules.GetSize();
6050b57cec5SDimitry Andric if (num_modules_specified == 1) {
606c9157d92SDimitry Andric const FileSpec &file_spec =
607c9157d92SDimitry Andric m_options.m_modules.GetFileSpecAtIndex(0);
6089dba64beSDimitry Andric bp_sp = target.CreateAddressInModuleBreakpoint(
6099dba64beSDimitry Andric m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
6100b57cec5SDimitry Andric } else if (num_modules_specified == 0) {
6119dba64beSDimitry Andric bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
6120b57cec5SDimitry Andric m_options.m_hardware);
6130b57cec5SDimitry Andric } else {
6140b57cec5SDimitry Andric result.AppendError("Only one shared library can be specified for "
6150b57cec5SDimitry Andric "address breakpoints.");
616c9157d92SDimitry Andric return;
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric break;
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric case eSetTypeFunctionName: // Breakpoint by function name
6210b57cec5SDimitry Andric {
6220b57cec5SDimitry Andric FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andric if (name_type_mask == 0)
6250b57cec5SDimitry Andric name_type_mask = eFunctionNameTypeAuto;
6260b57cec5SDimitry Andric
6279dba64beSDimitry Andric bp_sp = target.CreateBreakpoint(
6289dba64beSDimitry Andric &(m_options.m_modules), &(m_options.m_filenames),
6299dba64beSDimitry Andric m_options.m_func_names, name_type_mask, m_options.m_language,
6309dba64beSDimitry Andric m_options.m_offset_addr, m_options.m_skip_prologue, internal,
6310b57cec5SDimitry Andric m_options.m_hardware);
6320b57cec5SDimitry Andric } break;
6330b57cec5SDimitry Andric
6340b57cec5SDimitry Andric case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
6350b57cec5SDimitry Andric // name
6360b57cec5SDimitry Andric {
6370b57cec5SDimitry Andric RegularExpression regexp(m_options.m_func_regexp);
6389dba64beSDimitry Andric if (llvm::Error err = regexp.GetError()) {
6390b57cec5SDimitry Andric result.AppendErrorWithFormat(
6405ffd83dbSDimitry Andric "Function name regular expression could not be compiled: %s",
6419dba64beSDimitry Andric llvm::toString(std::move(err)).c_str());
6425ffd83dbSDimitry Andric // Check if the incorrect regex looks like a globbing expression and
6435ffd83dbSDimitry Andric // warn the user about it.
6445ffd83dbSDimitry Andric if (!m_options.m_func_regexp.empty()) {
6455ffd83dbSDimitry Andric if (m_options.m_func_regexp[0] == '*' ||
6465ffd83dbSDimitry Andric m_options.m_func_regexp[0] == '?')
6475ffd83dbSDimitry Andric result.AppendWarning(
6485ffd83dbSDimitry Andric "Function name regex does not accept glob patterns.");
6495ffd83dbSDimitry Andric }
650c9157d92SDimitry Andric return;
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric
6539dba64beSDimitry Andric bp_sp = target.CreateFuncRegexBreakpoint(
6549dba64beSDimitry Andric &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
6559dba64beSDimitry Andric m_options.m_language, m_options.m_skip_prologue, internal,
6560b57cec5SDimitry Andric m_options.m_hardware);
657480093f4SDimitry Andric } break;
6580b57cec5SDimitry Andric case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
6590b57cec5SDimitry Andric {
6600b57cec5SDimitry Andric const size_t num_files = m_options.m_filenames.GetSize();
6610b57cec5SDimitry Andric
6620b57cec5SDimitry Andric if (num_files == 0 && !m_options.m_all_files) {
6630b57cec5SDimitry Andric FileSpec file;
6640b57cec5SDimitry Andric if (!GetDefaultFile(target, file, result)) {
6650b57cec5SDimitry Andric result.AppendError(
6660b57cec5SDimitry Andric "No files provided and could not find default file.");
667c9157d92SDimitry Andric return;
6680b57cec5SDimitry Andric } else {
6690b57cec5SDimitry Andric m_options.m_filenames.Append(file);
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
6730b57cec5SDimitry Andric RegularExpression regexp(m_options.m_source_text_regexp);
6749dba64beSDimitry Andric if (llvm::Error err = regexp.GetError()) {
6750b57cec5SDimitry Andric result.AppendErrorWithFormat(
6760b57cec5SDimitry Andric "Source text regular expression could not be compiled: \"%s\"",
6779dba64beSDimitry Andric llvm::toString(std::move(err)).c_str());
678c9157d92SDimitry Andric return;
6790b57cec5SDimitry Andric }
6809dba64beSDimitry Andric bp_sp = target.CreateSourceRegexBreakpoint(
6819dba64beSDimitry Andric &(m_options.m_modules), &(m_options.m_filenames),
6829dba64beSDimitry Andric m_options.m_source_regex_func_names, std::move(regexp), internal,
6839dba64beSDimitry Andric m_options.m_hardware, m_options.m_move_to_nearest_code);
6840b57cec5SDimitry Andric } break;
6850b57cec5SDimitry Andric case eSetTypeException: {
6860b57cec5SDimitry Andric Status precond_error;
6879dba64beSDimitry Andric bp_sp = target.CreateExceptionBreakpoint(
6889dba64beSDimitry Andric m_options.m_exception_language, m_options.m_catch_bp,
6899dba64beSDimitry Andric m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
6900b57cec5SDimitry Andric &precond_error);
6910b57cec5SDimitry Andric if (precond_error.Fail()) {
6920b57cec5SDimitry Andric result.AppendErrorWithFormat(
6930b57cec5SDimitry Andric "Error setting extra exception arguments: %s",
6940b57cec5SDimitry Andric precond_error.AsCString());
6959dba64beSDimitry Andric target.RemoveBreakpointByID(bp_sp->GetID());
696c9157d92SDimitry Andric return;
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric } break;
6990b57cec5SDimitry Andric case eSetTypeScripted: {
7000b57cec5SDimitry Andric
7010b57cec5SDimitry Andric Status error;
7029dba64beSDimitry Andric bp_sp = target.CreateScriptedBreakpoint(
703480093f4SDimitry Andric m_python_class_options.GetName().c_str(), &(m_options.m_modules),
7049dba64beSDimitry Andric &(m_options.m_filenames), false, m_options.m_hardware,
7059dba64beSDimitry Andric m_python_class_options.GetStructuredData(), &error);
7060b57cec5SDimitry Andric if (error.Fail()) {
7070b57cec5SDimitry Andric result.AppendErrorWithFormat(
708480093f4SDimitry Andric "Error setting extra exception arguments: %s", error.AsCString());
7099dba64beSDimitry Andric target.RemoveBreakpointByID(bp_sp->GetID());
710c9157d92SDimitry Andric return;
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric } break;
7130b57cec5SDimitry Andric default:
7140b57cec5SDimitry Andric break;
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric // Now set the various options that were passed in:
7180b57cec5SDimitry Andric if (bp_sp) {
719fe6060f1SDimitry Andric bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
7200b57cec5SDimitry Andric
7210b57cec5SDimitry Andric if (!m_options.m_breakpoint_names.empty()) {
7220b57cec5SDimitry Andric Status name_error;
7230b57cec5SDimitry Andric for (auto name : m_options.m_breakpoint_names) {
7249dba64beSDimitry Andric target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
7250b57cec5SDimitry Andric if (name_error.Fail()) {
7260b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid breakpoint name: %s",
7270b57cec5SDimitry Andric name.c_str());
7289dba64beSDimitry Andric target.RemoveBreakpointByID(bp_sp->GetID());
729c9157d92SDimitry Andric return;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric
7350b57cec5SDimitry Andric if (bp_sp) {
7360b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream();
7370b57cec5SDimitry Andric const bool show_locations = false;
7380b57cec5SDimitry Andric bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
7390b57cec5SDimitry Andric show_locations);
7409dba64beSDimitry Andric if (&target == &GetDummyTarget())
7410b57cec5SDimitry Andric output_stream.Printf("Breakpoint set in dummy target, will get copied "
7420b57cec5SDimitry Andric "into future targets.\n");
7430b57cec5SDimitry Andric else {
7440b57cec5SDimitry Andric // Don't print out this warning for exception breakpoints. They can
7450b57cec5SDimitry Andric // get set before the target is set, but we won't know how to actually
7460b57cec5SDimitry Andric // set the breakpoint till we run.
7470b57cec5SDimitry Andric if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
7480b57cec5SDimitry Andric output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
7490b57cec5SDimitry Andric "actual locations.\n");
7500b57cec5SDimitry Andric }
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
7530b57cec5SDimitry Andric } else if (!bp_sp) {
7540b57cec5SDimitry Andric result.AppendError("Breakpoint creation failed: No breakpoint created.");
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)7599dba64beSDimitry Andric bool GetDefaultFile(Target &target, FileSpec &file,
7600b57cec5SDimitry Andric CommandReturnObject &result) {
7610b57cec5SDimitry Andric uint32_t default_line;
7620b57cec5SDimitry Andric // First use the Source Manager's default file. Then use the current stack
7630b57cec5SDimitry Andric // frame's file.
7649dba64beSDimitry Andric if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
7650b57cec5SDimitry Andric StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
7660b57cec5SDimitry Andric if (cur_frame == nullptr) {
7670b57cec5SDimitry Andric result.AppendError(
7680b57cec5SDimitry Andric "No selected frame to use to find the default file.");
7690b57cec5SDimitry Andric return false;
7700b57cec5SDimitry Andric } else if (!cur_frame->HasDebugInformation()) {
7710b57cec5SDimitry Andric result.AppendError("Cannot use the selected frame to find the default "
7720b57cec5SDimitry Andric "file, it has no debug info.");
7730b57cec5SDimitry Andric return false;
7740b57cec5SDimitry Andric } else {
7750b57cec5SDimitry Andric const SymbolContext &sc =
7760b57cec5SDimitry Andric cur_frame->GetSymbolContext(eSymbolContextLineEntry);
7770b57cec5SDimitry Andric if (sc.line_entry.file) {
7780b57cec5SDimitry Andric file = sc.line_entry.file;
7790b57cec5SDimitry Andric } else {
7800b57cec5SDimitry Andric result.AppendError("Can't find the file for the selected frame to "
7810b57cec5SDimitry Andric "use as the default file.");
7820b57cec5SDimitry Andric return false;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric }
7850b57cec5SDimitry Andric }
7860b57cec5SDimitry Andric return true;
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric
7890b57cec5SDimitry Andric BreakpointOptionGroup m_bp_opts;
7900b57cec5SDimitry Andric BreakpointDummyOptionGroup m_dummy_options;
7919dba64beSDimitry Andric OptionGroupPythonClassWithDict m_python_class_options;
7920b57cec5SDimitry Andric CommandOptions m_options;
7930b57cec5SDimitry Andric OptionGroupOptions m_all_options;
7940b57cec5SDimitry Andric };
7950b57cec5SDimitry Andric
7960b57cec5SDimitry Andric // CommandObjectBreakpointModify
7970b57cec5SDimitry Andric #pragma mark Modify
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric class CommandObjectBreakpointModify : public CommandObjectParsed {
8000b57cec5SDimitry Andric public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)8010b57cec5SDimitry Andric CommandObjectBreakpointModify(CommandInterpreter &interpreter)
8020b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "breakpoint modify",
8030b57cec5SDimitry Andric "Modify the options on a breakpoint or set of "
8040b57cec5SDimitry Andric "breakpoints in the executable. "
8050b57cec5SDimitry Andric "If no breakpoint is specified, acts on the last "
8060b57cec5SDimitry Andric "created breakpoint. "
8070b57cec5SDimitry Andric "With the exception of -e, -d and -i, passing an "
8080b57cec5SDimitry Andric "empty argument clears the modification.",
80904eeddc0SDimitry Andric nullptr) {
8100b57cec5SDimitry Andric CommandArgumentEntry arg;
8110b57cec5SDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
8120b57cec5SDimitry Andric eArgTypeBreakpointIDRange);
8130b57cec5SDimitry Andric // Add the entry for the first argument for this command to the object's
8140b57cec5SDimitry Andric // arguments vector.
8150b57cec5SDimitry Andric m_arguments.push_back(arg);
8160b57cec5SDimitry Andric
8170b57cec5SDimitry Andric m_options.Append(&m_bp_opts,
8180b57cec5SDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
8190b57cec5SDimitry Andric LLDB_OPT_SET_ALL);
8200b57cec5SDimitry Andric m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
8210b57cec5SDimitry Andric m_options.Finalize();
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric ~CommandObjectBreakpointModify() override = default;
8250b57cec5SDimitry Andric
8265ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8275ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
8285ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
829fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
830fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
8315ffd83dbSDimitry Andric }
8325ffd83dbSDimitry Andric
GetOptions()8330b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
8340b57cec5SDimitry Andric
8350b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)836c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
8379dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
8409dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
8430b57cec5SDimitry Andric
8440b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
8459dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
8460b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
8470b57cec5SDimitry Andric
8480b57cec5SDimitry Andric if (result.Succeeded()) {
8490b57cec5SDimitry Andric const size_t count = valid_bp_ids.GetSize();
8500b57cec5SDimitry Andric for (size_t i = 0; i < count; ++i) {
8510b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8520b57cec5SDimitry Andric
8530b57cec5SDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
8540b57cec5SDimitry Andric Breakpoint *bp =
8559dba64beSDimitry Andric target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
8560b57cec5SDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
8570b57cec5SDimitry Andric BreakpointLocation *location =
8580b57cec5SDimitry Andric bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
8590b57cec5SDimitry Andric if (location)
860fe6060f1SDimitry Andric location->GetLocationOptions().CopyOverSetOptions(
861480093f4SDimitry Andric m_bp_opts.GetBreakpointOptions());
8620b57cec5SDimitry Andric } else {
863fe6060f1SDimitry Andric bp->GetOptions().CopyOverSetOptions(
864480093f4SDimitry Andric m_bp_opts.GetBreakpointOptions());
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric private:
8720b57cec5SDimitry Andric BreakpointOptionGroup m_bp_opts;
8730b57cec5SDimitry Andric BreakpointDummyOptionGroup m_dummy_opts;
8740b57cec5SDimitry Andric OptionGroupOptions m_options;
8750b57cec5SDimitry Andric };
8760b57cec5SDimitry Andric
8770b57cec5SDimitry Andric // CommandObjectBreakpointEnable
8780b57cec5SDimitry Andric #pragma mark Enable
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andric class CommandObjectBreakpointEnable : public CommandObjectParsed {
8810b57cec5SDimitry Andric public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)8820b57cec5SDimitry Andric CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
8830b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "enable",
8840b57cec5SDimitry Andric "Enable the specified disabled breakpoint(s). If "
8850b57cec5SDimitry Andric "no breakpoints are specified, enable all of them.",
8860b57cec5SDimitry Andric nullptr) {
8870b57cec5SDimitry Andric CommandArgumentEntry arg;
8880b57cec5SDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
8890b57cec5SDimitry Andric eArgTypeBreakpointIDRange);
8900b57cec5SDimitry Andric // Add the entry for the first argument for this command to the object's
8910b57cec5SDimitry Andric // arguments vector.
8920b57cec5SDimitry Andric m_arguments.push_back(arg);
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric
8950b57cec5SDimitry Andric ~CommandObjectBreakpointEnable() override = default;
8960b57cec5SDimitry Andric
8975ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8985ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
8995ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
900fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
901fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
9025ffd83dbSDimitry Andric }
9035ffd83dbSDimitry Andric
9040b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)905c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
9069dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget();
9070b57cec5SDimitry Andric
9080b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
9099dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
9100b57cec5SDimitry Andric
9119dba64beSDimitry Andric const BreakpointList &breakpoints = target.GetBreakpointList();
9120b57cec5SDimitry Andric
9130b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
9140b57cec5SDimitry Andric
9150b57cec5SDimitry Andric if (num_breakpoints == 0) {
9160b57cec5SDimitry Andric result.AppendError("No breakpoints exist to be enabled.");
917c9157d92SDimitry Andric return;
9180b57cec5SDimitry Andric }
9190b57cec5SDimitry Andric
9200b57cec5SDimitry Andric if (command.empty()) {
9210b57cec5SDimitry Andric // No breakpoint selected; enable all currently set breakpoints.
9229dba64beSDimitry Andric target.EnableAllowedBreakpoints();
9230b57cec5SDimitry Andric result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
9240b57cec5SDimitry Andric " breakpoints)\n",
9250b57cec5SDimitry Andric (uint64_t)num_breakpoints);
9260b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
9270b57cec5SDimitry Andric } else {
9280b57cec5SDimitry Andric // Particular breakpoint selected; enable that breakpoint.
9290b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
9300b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
9319dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
9320b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric if (result.Succeeded()) {
9350b57cec5SDimitry Andric int enable_count = 0;
9360b57cec5SDimitry Andric int loc_count = 0;
9370b57cec5SDimitry Andric const size_t count = valid_bp_ids.GetSize();
9380b57cec5SDimitry Andric for (size_t i = 0; i < count; ++i) {
9390b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
9420b57cec5SDimitry Andric Breakpoint *breakpoint =
9439dba64beSDimitry Andric target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
9440b57cec5SDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
9450b57cec5SDimitry Andric BreakpointLocation *location =
9460b57cec5SDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
9470b57cec5SDimitry Andric if (location) {
9480b57cec5SDimitry Andric location->SetEnabled(true);
9490b57cec5SDimitry Andric ++loc_count;
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric } else {
9520b57cec5SDimitry Andric breakpoint->SetEnabled(true);
9530b57cec5SDimitry Andric ++enable_count;
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric result.AppendMessageWithFormat("%d breakpoints enabled.\n",
9580b57cec5SDimitry Andric enable_count + loc_count);
9590b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
9600b57cec5SDimitry Andric }
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric };
9640b57cec5SDimitry Andric
9650b57cec5SDimitry Andric // CommandObjectBreakpointDisable
9660b57cec5SDimitry Andric #pragma mark Disable
9670b57cec5SDimitry Andric
9680b57cec5SDimitry Andric class CommandObjectBreakpointDisable : public CommandObjectParsed {
9690b57cec5SDimitry Andric public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)9700b57cec5SDimitry Andric CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
9710b57cec5SDimitry Andric : CommandObjectParsed(
9720b57cec5SDimitry Andric interpreter, "breakpoint disable",
9730b57cec5SDimitry Andric "Disable the specified breakpoint(s) without deleting "
9740b57cec5SDimitry Andric "them. If none are specified, disable all "
9750b57cec5SDimitry Andric "breakpoints.",
9760b57cec5SDimitry Andric nullptr) {
9770b57cec5SDimitry Andric SetHelpLong(
9780b57cec5SDimitry Andric "Disable the specified breakpoint(s) without deleting them. \
9790b57cec5SDimitry Andric If none are specified, disable all breakpoints."
9800b57cec5SDimitry Andric R"(
9810b57cec5SDimitry Andric
9820b57cec5SDimitry Andric )"
9830b57cec5SDimitry Andric "Note: disabling a breakpoint will cause none of its locations to be hit \
9840b57cec5SDimitry Andric regardless of whether individual locations are enabled or disabled. After the sequence:"
9850b57cec5SDimitry Andric R"(
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric (lldb) break disable 1
9880b57cec5SDimitry Andric (lldb) break enable 1.1
9890b57cec5SDimitry Andric
9900b57cec5SDimitry Andric execution will NOT stop at location 1.1. To achieve that, type:
9910b57cec5SDimitry Andric
9920b57cec5SDimitry Andric (lldb) break disable 1.*
9930b57cec5SDimitry Andric (lldb) break enable 1.1
9940b57cec5SDimitry Andric
9950b57cec5SDimitry Andric )"
9960b57cec5SDimitry Andric "The first command disables all locations for breakpoint 1, \
9970b57cec5SDimitry Andric the second re-enables the first location.");
9980b57cec5SDimitry Andric
9990b57cec5SDimitry Andric CommandArgumentEntry arg;
10000b57cec5SDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
10010b57cec5SDimitry Andric eArgTypeBreakpointIDRange);
10020b57cec5SDimitry Andric // Add the entry for the first argument for this command to the object's
10030b57cec5SDimitry Andric // arguments vector.
10040b57cec5SDimitry Andric m_arguments.push_back(arg);
10050b57cec5SDimitry Andric }
10060b57cec5SDimitry Andric
10070b57cec5SDimitry Andric ~CommandObjectBreakpointDisable() override = default;
10080b57cec5SDimitry Andric
10095ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)10105ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
10115ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
1012fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1013fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
10145ffd83dbSDimitry Andric }
10155ffd83dbSDimitry Andric
10160b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1017c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
10189dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget();
10190b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
10209dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
10210b57cec5SDimitry Andric
10229dba64beSDimitry Andric const BreakpointList &breakpoints = target.GetBreakpointList();
10230b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric if (num_breakpoints == 0) {
10260b57cec5SDimitry Andric result.AppendError("No breakpoints exist to be disabled.");
1027c9157d92SDimitry Andric return;
10280b57cec5SDimitry Andric }
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric if (command.empty()) {
10310b57cec5SDimitry Andric // No breakpoint selected; disable all currently set breakpoints.
10329dba64beSDimitry Andric target.DisableAllowedBreakpoints();
10330b57cec5SDimitry Andric result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
10340b57cec5SDimitry Andric " breakpoints)\n",
10350b57cec5SDimitry Andric (uint64_t)num_breakpoints);
10360b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
10370b57cec5SDimitry Andric } else {
10380b57cec5SDimitry Andric // Particular breakpoint selected; disable that breakpoint.
10390b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
10400b57cec5SDimitry Andric
10410b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
10429dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
10430b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
10440b57cec5SDimitry Andric
10450b57cec5SDimitry Andric if (result.Succeeded()) {
10460b57cec5SDimitry Andric int disable_count = 0;
10470b57cec5SDimitry Andric int loc_count = 0;
10480b57cec5SDimitry Andric const size_t count = valid_bp_ids.GetSize();
10490b57cec5SDimitry Andric for (size_t i = 0; i < count; ++i) {
10500b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10510b57cec5SDimitry Andric
10520b57cec5SDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
10530b57cec5SDimitry Andric Breakpoint *breakpoint =
10549dba64beSDimitry Andric target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
10550b57cec5SDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
10560b57cec5SDimitry Andric BreakpointLocation *location =
10570b57cec5SDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
10580b57cec5SDimitry Andric if (location) {
10590b57cec5SDimitry Andric location->SetEnabled(false);
10600b57cec5SDimitry Andric ++loc_count;
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric } else {
10630b57cec5SDimitry Andric breakpoint->SetEnabled(false);
10640b57cec5SDimitry Andric ++disable_count;
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric result.AppendMessageWithFormat("%d breakpoints disabled.\n",
10690b57cec5SDimitry Andric disable_count + loc_count);
10700b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
10710b57cec5SDimitry Andric }
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric };
10750b57cec5SDimitry Andric
10760b57cec5SDimitry Andric // CommandObjectBreakpointList
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric #pragma mark List::CommandOptions
10790b57cec5SDimitry Andric #define LLDB_OPTIONS_breakpoint_list
10800b57cec5SDimitry Andric #include "CommandOptions.inc"
10810b57cec5SDimitry Andric
10820b57cec5SDimitry Andric #pragma mark List
10830b57cec5SDimitry Andric
10840b57cec5SDimitry Andric class CommandObjectBreakpointList : public CommandObjectParsed {
10850b57cec5SDimitry Andric public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)10860b57cec5SDimitry Andric CommandObjectBreakpointList(CommandInterpreter &interpreter)
10870b57cec5SDimitry Andric : CommandObjectParsed(
10880b57cec5SDimitry Andric interpreter, "breakpoint list",
10890b57cec5SDimitry Andric "List some or all breakpoints at configurable levels of detail.",
109004eeddc0SDimitry Andric nullptr) {
10910b57cec5SDimitry Andric CommandArgumentEntry arg;
10920b57cec5SDimitry Andric CommandArgumentData bp_id_arg;
10930b57cec5SDimitry Andric
10940b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
10950b57cec5SDimitry Andric bp_id_arg.arg_type = eArgTypeBreakpointID;
10960b57cec5SDimitry Andric bp_id_arg.arg_repetition = eArgRepeatOptional;
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
10990b57cec5SDimitry Andric // argument entry.
11000b57cec5SDimitry Andric arg.push_back(bp_id_arg);
11010b57cec5SDimitry Andric
11020b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
11030b57cec5SDimitry Andric m_arguments.push_back(arg);
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andric ~CommandObjectBreakpointList() override = default;
11070b57cec5SDimitry Andric
GetOptions()11080b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andric class CommandOptions : public Options {
11110b57cec5SDimitry Andric public:
111281ad6265SDimitry Andric CommandOptions() = default;
11130b57cec5SDimitry Andric
11140b57cec5SDimitry Andric ~CommandOptions() override = default;
11150b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)11160b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
11170b57cec5SDimitry Andric ExecutionContext *execution_context) override {
11180b57cec5SDimitry Andric Status error;
11190b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
11200b57cec5SDimitry Andric
11210b57cec5SDimitry Andric switch (short_option) {
11220b57cec5SDimitry Andric case 'b':
11230b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelBrief;
11240b57cec5SDimitry Andric break;
11250b57cec5SDimitry Andric case 'D':
11260b57cec5SDimitry Andric m_use_dummy = true;
11270b57cec5SDimitry Andric break;
11280b57cec5SDimitry Andric case 'f':
11290b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelFull;
11300b57cec5SDimitry Andric break;
11310b57cec5SDimitry Andric case 'v':
11320b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelVerbose;
11330b57cec5SDimitry Andric break;
11340b57cec5SDimitry Andric case 'i':
11350b57cec5SDimitry Andric m_internal = true;
11360b57cec5SDimitry Andric break;
11370b57cec5SDimitry Andric default:
11389dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric
11410b57cec5SDimitry Andric return error;
11420b57cec5SDimitry Andric }
11430b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)11440b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
11450b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelFull;
11460b57cec5SDimitry Andric m_internal = false;
11470b57cec5SDimitry Andric m_use_dummy = false;
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric
GetDefinitions()11500b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1151bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_list_options);
11520b57cec5SDimitry Andric }
11530b57cec5SDimitry Andric
11540b57cec5SDimitry Andric // Instance variables to hold the values for command options.
11550b57cec5SDimitry Andric
1156fe6060f1SDimitry Andric lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11570b57cec5SDimitry Andric
11580b57cec5SDimitry Andric bool m_internal;
1159fe6060f1SDimitry Andric bool m_use_dummy = false;
11600b57cec5SDimitry Andric };
11610b57cec5SDimitry Andric
11620b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1163c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
11649dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11650b57cec5SDimitry Andric
11660b57cec5SDimitry Andric const BreakpointList &breakpoints =
11679dba64beSDimitry Andric target.GetBreakpointList(m_options.m_internal);
11680b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
11699dba64beSDimitry Andric target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11700b57cec5SDimitry Andric
11710b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
11720b57cec5SDimitry Andric
11730b57cec5SDimitry Andric if (num_breakpoints == 0) {
11740b57cec5SDimitry Andric result.AppendMessage("No breakpoints currently set.");
11750b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
1176c9157d92SDimitry Andric return;
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream();
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric if (command.empty()) {
11820b57cec5SDimitry Andric // No breakpoint selected; show info about all currently set breakpoints.
11830b57cec5SDimitry Andric result.AppendMessage("Current breakpoints:");
11840b57cec5SDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
11850b57cec5SDimitry Andric Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
11860b57cec5SDimitry Andric if (breakpoint->AllowList())
11870b57cec5SDimitry Andric AddBreakpointDescription(&output_stream, breakpoint,
11880b57cec5SDimitry Andric m_options.m_level);
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
11910b57cec5SDimitry Andric } else {
11920b57cec5SDimitry Andric // Particular breakpoints selected; show info about that breakpoint.
11930b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
11940b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
11959dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
11960b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
11970b57cec5SDimitry Andric
11980b57cec5SDimitry Andric if (result.Succeeded()) {
11990b57cec5SDimitry Andric for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12000b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
12010b57cec5SDimitry Andric Breakpoint *breakpoint =
12029dba64beSDimitry Andric target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
12030b57cec5SDimitry Andric AddBreakpointDescription(&output_stream, breakpoint,
12040b57cec5SDimitry Andric m_options.m_level);
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
12070b57cec5SDimitry Andric } else {
12080b57cec5SDimitry Andric result.AppendError("Invalid breakpoint ID.");
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric
12130b57cec5SDimitry Andric private:
12140b57cec5SDimitry Andric CommandOptions m_options;
12150b57cec5SDimitry Andric };
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andric // CommandObjectBreakpointClear
12180b57cec5SDimitry Andric #pragma mark Clear::CommandOptions
12190b57cec5SDimitry Andric
12209dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_clear
12219dba64beSDimitry Andric #include "CommandOptions.inc"
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric #pragma mark Clear
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andric class CommandObjectBreakpointClear : public CommandObjectParsed {
12260b57cec5SDimitry Andric public:
12270b57cec5SDimitry Andric enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12280b57cec5SDimitry Andric
CommandObjectBreakpointClear(CommandInterpreter & interpreter)12290b57cec5SDimitry Andric CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12300b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "breakpoint clear",
12310b57cec5SDimitry Andric "Delete or disable breakpoints matching the "
12320b57cec5SDimitry Andric "specified source file and line.",
123304eeddc0SDimitry Andric "breakpoint clear <cmd-options>") {}
12340b57cec5SDimitry Andric
12350b57cec5SDimitry Andric ~CommandObjectBreakpointClear() override = default;
12360b57cec5SDimitry Andric
GetOptions()12370b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
12380b57cec5SDimitry Andric
12390b57cec5SDimitry Andric class CommandOptions : public Options {
12400b57cec5SDimitry Andric public:
124181ad6265SDimitry Andric CommandOptions() = default;
12420b57cec5SDimitry Andric
12430b57cec5SDimitry Andric ~CommandOptions() override = default;
12440b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)12450b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
12460b57cec5SDimitry Andric ExecutionContext *execution_context) override {
12470b57cec5SDimitry Andric Status error;
12480b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
12490b57cec5SDimitry Andric
12500b57cec5SDimitry Andric switch (short_option) {
12510b57cec5SDimitry Andric case 'f':
12525ffd83dbSDimitry Andric m_filename.assign(std::string(option_arg));
12530b57cec5SDimitry Andric break;
12540b57cec5SDimitry Andric
12550b57cec5SDimitry Andric case 'l':
12560b57cec5SDimitry Andric option_arg.getAsInteger(0, m_line_num);
12570b57cec5SDimitry Andric break;
12580b57cec5SDimitry Andric
12590b57cec5SDimitry Andric default:
12609dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
12610b57cec5SDimitry Andric }
12620b57cec5SDimitry Andric
12630b57cec5SDimitry Andric return error;
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)12660b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
12670b57cec5SDimitry Andric m_filename.clear();
12680b57cec5SDimitry Andric m_line_num = 0;
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric
GetDefinitions()12710b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1272bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_clear_options);
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric // Instance variables to hold the values for command options.
12760b57cec5SDimitry Andric
12770b57cec5SDimitry Andric std::string m_filename;
1278fe6060f1SDimitry Andric uint32_t m_line_num = 0;
12790b57cec5SDimitry Andric };
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1282c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
12839dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget();
12840b57cec5SDimitry Andric
12850b57cec5SDimitry Andric // The following are the various types of breakpoints that could be
12860b57cec5SDimitry Andric // cleared:
12870b57cec5SDimitry Andric // 1). -f -l (clearing breakpoint by source location)
12880b57cec5SDimitry Andric
12890b57cec5SDimitry Andric BreakpointClearType break_type = eClearTypeInvalid;
12900b57cec5SDimitry Andric
12910b57cec5SDimitry Andric if (m_options.m_line_num != 0)
12920b57cec5SDimitry Andric break_type = eClearTypeFileAndLine;
12930b57cec5SDimitry Andric
12940b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
12959dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
12960b57cec5SDimitry Andric
12979dba64beSDimitry Andric BreakpointList &breakpoints = target.GetBreakpointList();
12980b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
12990b57cec5SDimitry Andric
13000b57cec5SDimitry Andric // Early return if there's no breakpoint at all.
13010b57cec5SDimitry Andric if (num_breakpoints == 0) {
13020b57cec5SDimitry Andric result.AppendError("Breakpoint clear: No breakpoint cleared.");
1303c9157d92SDimitry Andric return;
13040b57cec5SDimitry Andric }
13050b57cec5SDimitry Andric
13060b57cec5SDimitry Andric // Find matching breakpoints and delete them.
13070b57cec5SDimitry Andric
13080b57cec5SDimitry Andric // First create a copy of all the IDs.
13090b57cec5SDimitry Andric std::vector<break_id_t> BreakIDs;
13100b57cec5SDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i)
13110b57cec5SDimitry Andric BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13120b57cec5SDimitry Andric
13130b57cec5SDimitry Andric int num_cleared = 0;
13140b57cec5SDimitry Andric StreamString ss;
13150b57cec5SDimitry Andric switch (break_type) {
13160b57cec5SDimitry Andric case eClearTypeFileAndLine: // Breakpoint by source position
13170b57cec5SDimitry Andric {
13180b57cec5SDimitry Andric const ConstString filename(m_options.m_filename.c_str());
13190b57cec5SDimitry Andric BreakpointLocationCollection loc_coll;
13200b57cec5SDimitry Andric
13210b57cec5SDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
13220b57cec5SDimitry Andric Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
13250b57cec5SDimitry Andric // If the collection size is 0, it's a full match and we can just
13260b57cec5SDimitry Andric // remove the breakpoint.
13270b57cec5SDimitry Andric if (loc_coll.GetSize() == 0) {
13280b57cec5SDimitry Andric bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13290b57cec5SDimitry Andric ss.EOL();
13309dba64beSDimitry Andric target.RemoveBreakpointByID(bp->GetID());
13310b57cec5SDimitry Andric ++num_cleared;
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric }
13340b57cec5SDimitry Andric }
13350b57cec5SDimitry Andric } break;
13360b57cec5SDimitry Andric
13370b57cec5SDimitry Andric default:
13380b57cec5SDimitry Andric break;
13390b57cec5SDimitry Andric }
13400b57cec5SDimitry Andric
13410b57cec5SDimitry Andric if (num_cleared > 0) {
13420b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream();
13430b57cec5SDimitry Andric output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
13440b57cec5SDimitry Andric output_stream << ss.GetString();
13450b57cec5SDimitry Andric output_stream.EOL();
13460b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
13470b57cec5SDimitry Andric } else {
13480b57cec5SDimitry Andric result.AppendError("Breakpoint clear: No breakpoint cleared.");
13490b57cec5SDimitry Andric }
13500b57cec5SDimitry Andric }
13510b57cec5SDimitry Andric
13520b57cec5SDimitry Andric private:
13530b57cec5SDimitry Andric CommandOptions m_options;
13540b57cec5SDimitry Andric };
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric // CommandObjectBreakpointDelete
13579dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_delete
13589dba64beSDimitry Andric #include "CommandOptions.inc"
13590b57cec5SDimitry Andric
13600b57cec5SDimitry Andric #pragma mark Delete
13610b57cec5SDimitry Andric
13620b57cec5SDimitry Andric class CommandObjectBreakpointDelete : public CommandObjectParsed {
13630b57cec5SDimitry Andric public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)13640b57cec5SDimitry Andric CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
13650b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "breakpoint delete",
13660b57cec5SDimitry Andric "Delete the specified breakpoint(s). If no "
13670b57cec5SDimitry Andric "breakpoints are specified, delete them all.",
136804eeddc0SDimitry Andric nullptr) {
13690b57cec5SDimitry Andric CommandArgumentEntry arg;
13700b57cec5SDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
13710b57cec5SDimitry Andric eArgTypeBreakpointIDRange);
13720b57cec5SDimitry Andric // Add the entry for the first argument for this command to the object's
13730b57cec5SDimitry Andric // arguments vector.
13740b57cec5SDimitry Andric m_arguments.push_back(arg);
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric
13770b57cec5SDimitry Andric ~CommandObjectBreakpointDelete() override = default;
13780b57cec5SDimitry Andric
13795ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)13805ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
13815ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
1382fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1383fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
13845ffd83dbSDimitry Andric }
13855ffd83dbSDimitry Andric
GetOptions()13860b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
13870b57cec5SDimitry Andric
13880b57cec5SDimitry Andric class CommandOptions : public Options {
13890b57cec5SDimitry Andric public:
139081ad6265SDimitry Andric CommandOptions() = default;
13910b57cec5SDimitry Andric
13920b57cec5SDimitry Andric ~CommandOptions() override = default;
13930b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13940b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
13950b57cec5SDimitry Andric ExecutionContext *execution_context) override {
13960b57cec5SDimitry Andric Status error;
13970b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
13980b57cec5SDimitry Andric
13990b57cec5SDimitry Andric switch (short_option) {
14000b57cec5SDimitry Andric case 'f':
14010b57cec5SDimitry Andric m_force = true;
14020b57cec5SDimitry Andric break;
14030b57cec5SDimitry Andric
14040b57cec5SDimitry Andric case 'D':
14050b57cec5SDimitry Andric m_use_dummy = true;
14060b57cec5SDimitry Andric break;
14070b57cec5SDimitry Andric
1408e8d8bef9SDimitry Andric case 'd':
1409e8d8bef9SDimitry Andric m_delete_disabled = true;
1410e8d8bef9SDimitry Andric break;
1411e8d8bef9SDimitry Andric
14120b57cec5SDimitry Andric default:
14139dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric
14160b57cec5SDimitry Andric return error;
14170b57cec5SDimitry Andric }
14180b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)14190b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
14200b57cec5SDimitry Andric m_use_dummy = false;
14210b57cec5SDimitry Andric m_force = false;
1422e8d8bef9SDimitry Andric m_delete_disabled = false;
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric
GetDefinitions()14250b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1426bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_delete_options);
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric
14290b57cec5SDimitry Andric // Instance variables to hold the values for command options.
1430fe6060f1SDimitry Andric bool m_use_dummy = false;
1431fe6060f1SDimitry Andric bool m_force = false;
1432fe6060f1SDimitry Andric bool m_delete_disabled = false;
14330b57cec5SDimitry Andric };
14340b57cec5SDimitry Andric
14350b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1436c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
14379dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1438e8d8bef9SDimitry Andric result.Clear();
14390b57cec5SDimitry Andric
14400b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
14419dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
14420b57cec5SDimitry Andric
1443e8d8bef9SDimitry Andric BreakpointList &breakpoints = target.GetBreakpointList();
14440b57cec5SDimitry Andric
14450b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
14460b57cec5SDimitry Andric
14470b57cec5SDimitry Andric if (num_breakpoints == 0) {
14480b57cec5SDimitry Andric result.AppendError("No breakpoints exist to be deleted.");
1449c9157d92SDimitry Andric return;
14500b57cec5SDimitry Andric }
14510b57cec5SDimitry Andric
1452fe6060f1SDimitry Andric // Handle the delete all breakpoints case:
1453e8d8bef9SDimitry Andric if (command.empty() && !m_options.m_delete_disabled) {
14540b57cec5SDimitry Andric if (!m_options.m_force &&
14550b57cec5SDimitry Andric !m_interpreter.Confirm(
14560b57cec5SDimitry Andric "About to delete all breakpoints, do you want to do that?",
14570b57cec5SDimitry Andric true)) {
14580b57cec5SDimitry Andric result.AppendMessage("Operation cancelled...");
14590b57cec5SDimitry Andric } else {
14609dba64beSDimitry Andric target.RemoveAllowedBreakpoints();
14610b57cec5SDimitry Andric result.AppendMessageWithFormat(
14620b57cec5SDimitry Andric "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
14630b57cec5SDimitry Andric (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14640b57cec5SDimitry Andric }
14650b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
1466c9157d92SDimitry Andric return;
1467fe6060f1SDimitry Andric }
1468fe6060f1SDimitry Andric
1469fe6060f1SDimitry Andric // Either we have some kind of breakpoint specification(s),
1470fe6060f1SDimitry Andric // or we are handling "break disable --deleted". Gather the list
1471fe6060f1SDimitry Andric // of breakpoints to delete here, the we'll delete them below.
14720b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
1473e8d8bef9SDimitry Andric
1474e8d8bef9SDimitry Andric if (m_options.m_delete_disabled) {
1475e8d8bef9SDimitry Andric BreakpointIDList excluded_bp_ids;
1476e8d8bef9SDimitry Andric
1477e8d8bef9SDimitry Andric if (!command.empty()) {
1478e8d8bef9SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1479e8d8bef9SDimitry Andric command, &target, result, &excluded_bp_ids,
1480e8d8bef9SDimitry Andric BreakpointName::Permissions::PermissionKinds::deletePerm);
1481fe6060f1SDimitry Andric if (!result.Succeeded())
1482c9157d92SDimitry Andric return;
1483e8d8bef9SDimitry Andric }
1484fe6060f1SDimitry Andric
1485e8d8bef9SDimitry Andric for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1486e8d8bef9SDimitry Andric if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1487e8d8bef9SDimitry Andric BreakpointID bp_id(breakpoint_sp->GetID());
1488e8d8bef9SDimitry Andric size_t pos = 0;
1489e8d8bef9SDimitry Andric if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
1490e8d8bef9SDimitry Andric valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
1491e8d8bef9SDimitry Andric }
1492e8d8bef9SDimitry Andric }
1493e8d8bef9SDimitry Andric if (valid_bp_ids.GetSize() == 0) {
1494e8d8bef9SDimitry Andric result.AppendError("No disabled breakpoints.");
1495c9157d92SDimitry Andric return;
1496e8d8bef9SDimitry Andric }
1497e8d8bef9SDimitry Andric } else {
14980b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
14999dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
15000b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::deletePerm);
1501fe6060f1SDimitry Andric if (!result.Succeeded())
1502c9157d92SDimitry Andric return;
1503e8d8bef9SDimitry Andric }
15040b57cec5SDimitry Andric
15050b57cec5SDimitry Andric int delete_count = 0;
15060b57cec5SDimitry Andric int disable_count = 0;
15070b57cec5SDimitry Andric const size_t count = valid_bp_ids.GetSize();
15080b57cec5SDimitry Andric for (size_t i = 0; i < count; ++i) {
15090b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15100b57cec5SDimitry Andric
15110b57cec5SDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
15120b57cec5SDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
15130b57cec5SDimitry Andric Breakpoint *breakpoint =
15149dba64beSDimitry Andric target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
15150b57cec5SDimitry Andric BreakpointLocation *location =
15160b57cec5SDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
15170b57cec5SDimitry Andric // It makes no sense to try to delete individual locations, so we
15180b57cec5SDimitry Andric // disable them instead.
15190b57cec5SDimitry Andric if (location) {
15200b57cec5SDimitry Andric location->SetEnabled(false);
15210b57cec5SDimitry Andric ++disable_count;
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric } else {
15249dba64beSDimitry Andric target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15250b57cec5SDimitry Andric ++delete_count;
15260b57cec5SDimitry Andric }
15270b57cec5SDimitry Andric }
15280b57cec5SDimitry Andric }
15290b57cec5SDimitry Andric result.AppendMessageWithFormat(
15300b57cec5SDimitry Andric "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15310b57cec5SDimitry Andric delete_count, disable_count);
15320b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
15330b57cec5SDimitry Andric }
15340b57cec5SDimitry Andric
15350b57cec5SDimitry Andric private:
15360b57cec5SDimitry Andric CommandOptions m_options;
15370b57cec5SDimitry Andric };
15380b57cec5SDimitry Andric
15390b57cec5SDimitry Andric // CommandObjectBreakpointName
15409dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_name
15419dba64beSDimitry Andric #include "CommandOptions.inc"
15420b57cec5SDimitry Andric
15430b57cec5SDimitry Andric class BreakpointNameOptionGroup : public OptionGroup {
15440b57cec5SDimitry Andric public:
BreakpointNameOptionGroup()15450b57cec5SDimitry Andric BreakpointNameOptionGroup()
154604eeddc0SDimitry Andric : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
15470b57cec5SDimitry Andric
15480b57cec5SDimitry Andric ~BreakpointNameOptionGroup() override = default;
15490b57cec5SDimitry Andric
GetDefinitions()15500b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1551bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_name_options);
15520b57cec5SDimitry Andric }
15530b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)15540b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
15550b57cec5SDimitry Andric ExecutionContext *execution_context) override {
15560b57cec5SDimitry Andric Status error;
15570b57cec5SDimitry Andric const int short_option = g_breakpoint_name_options[option_idx].short_option;
15580b57cec5SDimitry Andric
15590b57cec5SDimitry Andric switch (short_option) {
15600b57cec5SDimitry Andric case 'N':
15610b57cec5SDimitry Andric if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
15620b57cec5SDimitry Andric error.Success())
15630b57cec5SDimitry Andric m_name.SetValueFromString(option_arg);
15640b57cec5SDimitry Andric break;
15650b57cec5SDimitry Andric case 'B':
15660b57cec5SDimitry Andric if (m_breakpoint.SetValueFromString(option_arg).Fail())
15670b57cec5SDimitry Andric error.SetErrorStringWithFormat(
15680b57cec5SDimitry Andric "unrecognized value \"%s\" for breakpoint",
15690b57cec5SDimitry Andric option_arg.str().c_str());
15700b57cec5SDimitry Andric break;
15710b57cec5SDimitry Andric case 'D':
15720b57cec5SDimitry Andric if (m_use_dummy.SetValueFromString(option_arg).Fail())
15730b57cec5SDimitry Andric error.SetErrorStringWithFormat(
15740b57cec5SDimitry Andric "unrecognized value \"%s\" for use-dummy",
15750b57cec5SDimitry Andric option_arg.str().c_str());
15760b57cec5SDimitry Andric break;
15770b57cec5SDimitry Andric case 'H':
15780b57cec5SDimitry Andric m_help_string.SetValueFromString(option_arg);
15790b57cec5SDimitry Andric break;
15800b57cec5SDimitry Andric
15810b57cec5SDimitry Andric default:
15829dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric return error;
15850b57cec5SDimitry Andric }
15860b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)15870b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
15880b57cec5SDimitry Andric m_name.Clear();
15890b57cec5SDimitry Andric m_breakpoint.Clear();
15900b57cec5SDimitry Andric m_use_dummy.Clear();
15910b57cec5SDimitry Andric m_use_dummy.SetDefaultValue(false);
15920b57cec5SDimitry Andric m_help_string.Clear();
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric
15950b57cec5SDimitry Andric OptionValueString m_name;
15960b57cec5SDimitry Andric OptionValueUInt64 m_breakpoint;
15970b57cec5SDimitry Andric OptionValueBoolean m_use_dummy;
15980b57cec5SDimitry Andric OptionValueString m_help_string;
15990b57cec5SDimitry Andric };
16000b57cec5SDimitry Andric
16019dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_access
16029dba64beSDimitry Andric #include "CommandOptions.inc"
16030b57cec5SDimitry Andric
16040b57cec5SDimitry Andric class BreakpointAccessOptionGroup : public OptionGroup {
16050b57cec5SDimitry Andric public:
160681ad6265SDimitry Andric BreakpointAccessOptionGroup() = default;
16070b57cec5SDimitry Andric
16080b57cec5SDimitry Andric ~BreakpointAccessOptionGroup() override = default;
16090b57cec5SDimitry Andric
GetDefinitions()16100b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1611bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_access_options);
16120b57cec5SDimitry Andric }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)16130b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
16140b57cec5SDimitry Andric ExecutionContext *execution_context) override {
16150b57cec5SDimitry Andric Status error;
1616480093f4SDimitry Andric const int short_option =
1617480093f4SDimitry Andric g_breakpoint_access_options[option_idx].short_option;
16180b57cec5SDimitry Andric
16190b57cec5SDimitry Andric switch (short_option) {
16200b57cec5SDimitry Andric case 'L': {
16210b57cec5SDimitry Andric bool value, success;
16220b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
16230b57cec5SDimitry Andric if (success) {
16240b57cec5SDimitry Andric m_permissions.SetAllowList(value);
16250b57cec5SDimitry Andric } else
16260b57cec5SDimitry Andric error.SetErrorStringWithFormat(
16270b57cec5SDimitry Andric "invalid boolean value '%s' passed for -L option",
16280b57cec5SDimitry Andric option_arg.str().c_str());
16290b57cec5SDimitry Andric } break;
16300b57cec5SDimitry Andric case 'A': {
16310b57cec5SDimitry Andric bool value, success;
16320b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
16330b57cec5SDimitry Andric if (success) {
16340b57cec5SDimitry Andric m_permissions.SetAllowDisable(value);
16350b57cec5SDimitry Andric } else
16360b57cec5SDimitry Andric error.SetErrorStringWithFormat(
16370b57cec5SDimitry Andric "invalid boolean value '%s' passed for -L option",
16380b57cec5SDimitry Andric option_arg.str().c_str());
16390b57cec5SDimitry Andric } break;
16400b57cec5SDimitry Andric case 'D': {
16410b57cec5SDimitry Andric bool value, success;
16420b57cec5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
16430b57cec5SDimitry Andric if (success) {
16440b57cec5SDimitry Andric m_permissions.SetAllowDelete(value);
16450b57cec5SDimitry Andric } else
16460b57cec5SDimitry Andric error.SetErrorStringWithFormat(
16470b57cec5SDimitry Andric "invalid boolean value '%s' passed for -L option",
16480b57cec5SDimitry Andric option_arg.str().c_str());
16490b57cec5SDimitry Andric } break;
16509dba64beSDimitry Andric default:
16519dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
16520b57cec5SDimitry Andric }
16530b57cec5SDimitry Andric
16540b57cec5SDimitry Andric return error;
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1657480093f4SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {}
16580b57cec5SDimitry Andric
GetPermissions() const1659480093f4SDimitry Andric const BreakpointName::Permissions &GetPermissions() const {
16600b57cec5SDimitry Andric return m_permissions;
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric BreakpointName::Permissions m_permissions;
16630b57cec5SDimitry Andric };
16640b57cec5SDimitry Andric
16650b57cec5SDimitry Andric class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
16660b57cec5SDimitry Andric public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)16670b57cec5SDimitry Andric CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
16680b57cec5SDimitry Andric : CommandObjectParsed(
1669480093f4SDimitry Andric interpreter, "configure",
1670480093f4SDimitry Andric "Configure the options for the breakpoint"
16710b57cec5SDimitry Andric " name provided. "
16720b57cec5SDimitry Andric "If you provide a breakpoint id, the options will be copied from "
16730b57cec5SDimitry Andric "the breakpoint, otherwise only the options specified will be set "
16740b57cec5SDimitry Andric "on the name.",
16750b57cec5SDimitry Andric "breakpoint name configure <command-options> "
167604eeddc0SDimitry Andric "<breakpoint-name-list>") {
16770b57cec5SDimitry Andric // Create the first variant for the first (and only) argument for this
16780b57cec5SDimitry Andric // command.
16790b57cec5SDimitry Andric CommandArgumentEntry arg1;
16800b57cec5SDimitry Andric CommandArgumentData id_arg;
16810b57cec5SDimitry Andric id_arg.arg_type = eArgTypeBreakpointName;
16820b57cec5SDimitry Andric id_arg.arg_repetition = eArgRepeatOptional;
16830b57cec5SDimitry Andric arg1.push_back(id_arg);
16840b57cec5SDimitry Andric m_arguments.push_back(arg1);
16850b57cec5SDimitry Andric
1686480093f4SDimitry Andric m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1687480093f4SDimitry Andric m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
16880b57cec5SDimitry Andric LLDB_OPT_SET_ALL);
1689480093f4SDimitry Andric m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
16900b57cec5SDimitry Andric LLDB_OPT_SET_ALL);
16910b57cec5SDimitry Andric m_option_group.Finalize();
16920b57cec5SDimitry Andric }
16930b57cec5SDimitry Andric
16940b57cec5SDimitry Andric ~CommandObjectBreakpointNameConfigure() override = default;
16950b57cec5SDimitry Andric
GetOptions()16960b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
16970b57cec5SDimitry Andric
16980b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1699c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
17000b57cec5SDimitry Andric
17010b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount();
17020b57cec5SDimitry Andric if (argc == 0) {
17030b57cec5SDimitry Andric result.AppendError("No names provided.");
1704c9157d92SDimitry Andric return;
17050b57cec5SDimitry Andric }
17060b57cec5SDimitry Andric
17079dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget(false);
17080b57cec5SDimitry Andric
17090b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
17109dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
17110b57cec5SDimitry Andric
17120b57cec5SDimitry Andric // Make a pass through first to see that all the names are legal.
17130b57cec5SDimitry Andric for (auto &entry : command.entries()) {
17140b57cec5SDimitry Andric Status error;
1715480093f4SDimitry Andric if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
17160b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
17170b57cec5SDimitry Andric entry.c_str(), error.AsCString());
1718c9157d92SDimitry Andric return;
17190b57cec5SDimitry Andric }
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric // Now configure them, we already pre-checked the names so we don't need to
17220b57cec5SDimitry Andric // check the error:
17230b57cec5SDimitry Andric BreakpointSP bp_sp;
1724480093f4SDimitry Andric if (m_bp_id.m_breakpoint.OptionWasSet()) {
1725fe013be4SDimitry Andric lldb::break_id_t bp_id =
1726fe013be4SDimitry Andric m_bp_id.m_breakpoint.GetValueAs<uint64_t>().value_or(0);
17279dba64beSDimitry Andric bp_sp = target.GetBreakpointByID(bp_id);
1728480093f4SDimitry Andric if (!bp_sp) {
17290b57cec5SDimitry Andric result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
17300b57cec5SDimitry Andric bp_id);
1731c9157d92SDimitry Andric return;
17320b57cec5SDimitry Andric }
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric
17350b57cec5SDimitry Andric Status error;
17360b57cec5SDimitry Andric for (auto &entry : command.entries()) {
17370b57cec5SDimitry Andric ConstString name(entry.c_str());
17389dba64beSDimitry Andric BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
17390b57cec5SDimitry Andric if (!bp_name)
17400b57cec5SDimitry Andric continue;
17410b57cec5SDimitry Andric if (m_bp_id.m_help_string.OptionWasSet())
1742fe013be4SDimitry Andric bp_name->SetHelp(m_bp_id.m_help_string.GetValueAs<llvm::StringRef>()
1743fe013be4SDimitry Andric .value_or("")
1744fe013be4SDimitry Andric .str()
1745fe013be4SDimitry Andric .c_str());
17460b57cec5SDimitry Andric
17470b57cec5SDimitry Andric if (bp_sp)
1748fe6060f1SDimitry Andric target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
17490b57cec5SDimitry Andric m_access_options.GetPermissions());
17500b57cec5SDimitry Andric else
17519dba64beSDimitry Andric target.ConfigureBreakpointName(*bp_name,
17520b57cec5SDimitry Andric m_bp_opts.GetBreakpointOptions(),
17530b57cec5SDimitry Andric m_access_options.GetPermissions());
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric
17570b57cec5SDimitry Andric private:
17580b57cec5SDimitry Andric BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
17590b57cec5SDimitry Andric BreakpointOptionGroup m_bp_opts;
17600b57cec5SDimitry Andric BreakpointAccessOptionGroup m_access_options;
17610b57cec5SDimitry Andric OptionGroupOptions m_option_group;
17620b57cec5SDimitry Andric };
17630b57cec5SDimitry Andric
17640b57cec5SDimitry Andric class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17650b57cec5SDimitry Andric public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)17660b57cec5SDimitry Andric CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
17670b57cec5SDimitry Andric : CommandObjectParsed(
17680b57cec5SDimitry Andric interpreter, "add", "Add a name to the breakpoints provided.",
176904eeddc0SDimitry Andric "breakpoint name add <command-options> <breakpoint-id-list>") {
17700b57cec5SDimitry Andric // Create the first variant for the first (and only) argument for this
17710b57cec5SDimitry Andric // command.
17720b57cec5SDimitry Andric CommandArgumentEntry arg1;
17730b57cec5SDimitry Andric CommandArgumentData id_arg;
17740b57cec5SDimitry Andric id_arg.arg_type = eArgTypeBreakpointID;
17750b57cec5SDimitry Andric id_arg.arg_repetition = eArgRepeatOptional;
17760b57cec5SDimitry Andric arg1.push_back(id_arg);
17770b57cec5SDimitry Andric m_arguments.push_back(arg1);
17780b57cec5SDimitry Andric
17790b57cec5SDimitry Andric m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17800b57cec5SDimitry Andric m_option_group.Finalize();
17810b57cec5SDimitry Andric }
17820b57cec5SDimitry Andric
17830b57cec5SDimitry Andric ~CommandObjectBreakpointNameAdd() override = default;
17840b57cec5SDimitry Andric
17855ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)17865ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
17875ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
1788fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1789fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
17905ffd83dbSDimitry Andric }
17915ffd83dbSDimitry Andric
GetOptions()17920b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
17930b57cec5SDimitry Andric
17940b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1795c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
17960b57cec5SDimitry Andric if (!m_name_options.m_name.OptionWasSet()) {
1797fe6060f1SDimitry Andric result.AppendError("No name option provided.");
1798c9157d92SDimitry Andric return;
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric
18019dba64beSDimitry Andric Target &target =
18020b57cec5SDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18030b57cec5SDimitry Andric
18040b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
18059dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
18060b57cec5SDimitry Andric
18079dba64beSDimitry Andric const BreakpointList &breakpoints = target.GetBreakpointList();
18080b57cec5SDimitry Andric
18090b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
18100b57cec5SDimitry Andric if (num_breakpoints == 0) {
1811fe6060f1SDimitry Andric result.AppendError("No breakpoints, cannot add names.");
1812c9157d92SDimitry Andric return;
18130b57cec5SDimitry Andric }
18140b57cec5SDimitry Andric
18150b57cec5SDimitry Andric // Particular breakpoint selected; disable that breakpoint.
18160b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
18170b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
18189dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
18190b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
18200b57cec5SDimitry Andric
18210b57cec5SDimitry Andric if (result.Succeeded()) {
18220b57cec5SDimitry Andric if (valid_bp_ids.GetSize() == 0) {
1823fe6060f1SDimitry Andric result.AppendError("No breakpoints specified, cannot add names.");
1824c9157d92SDimitry Andric return;
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric size_t num_valid_ids = valid_bp_ids.GetSize();
18270b57cec5SDimitry Andric const char *bp_name = m_name_options.m_name.GetCurrentValue();
18280b57cec5SDimitry Andric Status error; // This error reports illegal names, but we've already
18290b57cec5SDimitry Andric // checked that, so we don't need to check it again here.
18300b57cec5SDimitry Andric for (size_t index = 0; index < num_valid_ids; index++) {
18310b57cec5SDimitry Andric lldb::break_id_t bp_id =
18320b57cec5SDimitry Andric valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18330b57cec5SDimitry Andric BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
18349dba64beSDimitry Andric target.AddNameToBreakpoint(bp_sp, bp_name, error);
18350b57cec5SDimitry Andric }
18360b57cec5SDimitry Andric }
18370b57cec5SDimitry Andric }
18380b57cec5SDimitry Andric
18390b57cec5SDimitry Andric private:
18400b57cec5SDimitry Andric BreakpointNameOptionGroup m_name_options;
18410b57cec5SDimitry Andric OptionGroupOptions m_option_group;
18420b57cec5SDimitry Andric };
18430b57cec5SDimitry Andric
18440b57cec5SDimitry Andric class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18450b57cec5SDimitry Andric public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)18460b57cec5SDimitry Andric CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
18470b57cec5SDimitry Andric : CommandObjectParsed(
18480b57cec5SDimitry Andric interpreter, "delete",
18490b57cec5SDimitry Andric "Delete a name from the breakpoints provided.",
185004eeddc0SDimitry Andric "breakpoint name delete <command-options> <breakpoint-id-list>") {
18510b57cec5SDimitry Andric // Create the first variant for the first (and only) argument for this
18520b57cec5SDimitry Andric // command.
18530b57cec5SDimitry Andric CommandArgumentEntry arg1;
18540b57cec5SDimitry Andric CommandArgumentData id_arg;
18550b57cec5SDimitry Andric id_arg.arg_type = eArgTypeBreakpointID;
18560b57cec5SDimitry Andric id_arg.arg_repetition = eArgRepeatOptional;
18570b57cec5SDimitry Andric arg1.push_back(id_arg);
18580b57cec5SDimitry Andric m_arguments.push_back(arg1);
18590b57cec5SDimitry Andric
18600b57cec5SDimitry Andric m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18610b57cec5SDimitry Andric m_option_group.Finalize();
18620b57cec5SDimitry Andric }
18630b57cec5SDimitry Andric
18640b57cec5SDimitry Andric ~CommandObjectBreakpointNameDelete() override = default;
18650b57cec5SDimitry Andric
18665ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)18675ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
18685ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
1869fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1870fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
18715ffd83dbSDimitry Andric }
18725ffd83dbSDimitry Andric
GetOptions()18730b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
18740b57cec5SDimitry Andric
18750b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1876c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
18770b57cec5SDimitry Andric if (!m_name_options.m_name.OptionWasSet()) {
1878fe6060f1SDimitry Andric result.AppendError("No name option provided.");
1879c9157d92SDimitry Andric return;
18800b57cec5SDimitry Andric }
18810b57cec5SDimitry Andric
18829dba64beSDimitry Andric Target &target =
18830b57cec5SDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18840b57cec5SDimitry Andric
18850b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
18869dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
18870b57cec5SDimitry Andric
18889dba64beSDimitry Andric const BreakpointList &breakpoints = target.GetBreakpointList();
18890b57cec5SDimitry Andric
18900b57cec5SDimitry Andric size_t num_breakpoints = breakpoints.GetSize();
18910b57cec5SDimitry Andric if (num_breakpoints == 0) {
1892fe6060f1SDimitry Andric result.AppendError("No breakpoints, cannot delete names.");
1893c9157d92SDimitry Andric return;
18940b57cec5SDimitry Andric }
18950b57cec5SDimitry Andric
18960b57cec5SDimitry Andric // Particular breakpoint selected; disable that breakpoint.
18970b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
18980b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
18999dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
19000b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::deletePerm);
19010b57cec5SDimitry Andric
19020b57cec5SDimitry Andric if (result.Succeeded()) {
19030b57cec5SDimitry Andric if (valid_bp_ids.GetSize() == 0) {
1904fe6060f1SDimitry Andric result.AppendError("No breakpoints specified, cannot delete names.");
1905c9157d92SDimitry Andric return;
19060b57cec5SDimitry Andric }
19070b57cec5SDimitry Andric ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19080b57cec5SDimitry Andric size_t num_valid_ids = valid_bp_ids.GetSize();
19090b57cec5SDimitry Andric for (size_t index = 0; index < num_valid_ids; index++) {
19100b57cec5SDimitry Andric lldb::break_id_t bp_id =
19110b57cec5SDimitry Andric valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19120b57cec5SDimitry Andric BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
19139dba64beSDimitry Andric target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19140b57cec5SDimitry Andric }
19150b57cec5SDimitry Andric }
19160b57cec5SDimitry Andric }
19170b57cec5SDimitry Andric
19180b57cec5SDimitry Andric private:
19190b57cec5SDimitry Andric BreakpointNameOptionGroup m_name_options;
19200b57cec5SDimitry Andric OptionGroupOptions m_option_group;
19210b57cec5SDimitry Andric };
19220b57cec5SDimitry Andric
19230b57cec5SDimitry Andric class CommandObjectBreakpointNameList : public CommandObjectParsed {
19240b57cec5SDimitry Andric public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)19250b57cec5SDimitry Andric CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
19260b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "list",
19270b57cec5SDimitry Andric "List either the names for a breakpoint or info "
19280b57cec5SDimitry Andric "about a given name. With no arguments, lists all "
19290b57cec5SDimitry Andric "names",
193004eeddc0SDimitry Andric "breakpoint name list <command-options>") {
19310b57cec5SDimitry Andric m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19320b57cec5SDimitry Andric m_option_group.Finalize();
19330b57cec5SDimitry Andric }
19340b57cec5SDimitry Andric
19350b57cec5SDimitry Andric ~CommandObjectBreakpointNameList() override = default;
19360b57cec5SDimitry Andric
GetOptions()19370b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
19380b57cec5SDimitry Andric
19390b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1940c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
19419dba64beSDimitry Andric Target &target =
19420b57cec5SDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19430b57cec5SDimitry Andric
19440b57cec5SDimitry Andric std::vector<std::string> name_list;
19450b57cec5SDimitry Andric if (command.empty()) {
19469dba64beSDimitry Andric target.GetBreakpointNames(name_list);
19470b57cec5SDimitry Andric } else {
1948480093f4SDimitry Andric for (const Args::ArgEntry &arg : command) {
19490b57cec5SDimitry Andric name_list.push_back(arg.c_str());
19500b57cec5SDimitry Andric }
19510b57cec5SDimitry Andric }
19520b57cec5SDimitry Andric
19530b57cec5SDimitry Andric if (name_list.empty()) {
19540b57cec5SDimitry Andric result.AppendMessage("No breakpoint names found.");
19550b57cec5SDimitry Andric } else {
19560b57cec5SDimitry Andric for (const std::string &name_str : name_list) {
19570b57cec5SDimitry Andric const char *name = name_str.c_str();
19580b57cec5SDimitry Andric // First print out the options for the name:
19590b57cec5SDimitry Andric Status error;
19609dba64beSDimitry Andric BreakpointName *bp_name =
19619dba64beSDimitry Andric target.FindBreakpointName(ConstString(name), false, error);
1962480093f4SDimitry Andric if (bp_name) {
19630b57cec5SDimitry Andric StreamString s;
19640b57cec5SDimitry Andric result.AppendMessageWithFormat("Name: %s\n", name);
1965480093f4SDimitry Andric if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
19660b57cec5SDimitry Andric result.AppendMessage(s.GetString());
19670b57cec5SDimitry Andric }
19680b57cec5SDimitry Andric
19690b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
19709dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
19710b57cec5SDimitry Andric
19729dba64beSDimitry Andric BreakpointList &breakpoints = target.GetBreakpointList();
19730b57cec5SDimitry Andric bool any_set = false;
19740b57cec5SDimitry Andric for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
19750b57cec5SDimitry Andric if (bp_sp->MatchesName(name)) {
19760b57cec5SDimitry Andric StreamString s;
19770b57cec5SDimitry Andric any_set = true;
19780b57cec5SDimitry Andric bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19790b57cec5SDimitry Andric s.EOL();
19800b57cec5SDimitry Andric result.AppendMessage(s.GetString());
19810b57cec5SDimitry Andric }
19820b57cec5SDimitry Andric }
19830b57cec5SDimitry Andric if (!any_set)
19840b57cec5SDimitry Andric result.AppendMessage("No breakpoints using this name.");
19850b57cec5SDimitry Andric } else {
19860b57cec5SDimitry Andric result.AppendMessageWithFormat("Name: %s not found.\n", name);
19870b57cec5SDimitry Andric }
19880b57cec5SDimitry Andric }
19890b57cec5SDimitry Andric }
19900b57cec5SDimitry Andric }
19910b57cec5SDimitry Andric
19920b57cec5SDimitry Andric private:
19930b57cec5SDimitry Andric BreakpointNameOptionGroup m_name_options;
19940b57cec5SDimitry Andric OptionGroupOptions m_option_group;
19950b57cec5SDimitry Andric };
19960b57cec5SDimitry Andric
19970b57cec5SDimitry Andric // CommandObjectBreakpointName
19980b57cec5SDimitry Andric class CommandObjectBreakpointName : public CommandObjectMultiword {
19990b57cec5SDimitry Andric public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)20000b57cec5SDimitry Andric CommandObjectBreakpointName(CommandInterpreter &interpreter)
20010b57cec5SDimitry Andric : CommandObjectMultiword(
200281ad6265SDimitry Andric interpreter, "name", "Commands to manage breakpoint names") {
200381ad6265SDimitry Andric
200481ad6265SDimitry Andric
200581ad6265SDimitry Andric SetHelpLong(
200681ad6265SDimitry Andric R"(
200781ad6265SDimitry Andric Breakpoint names provide a general tagging mechanism for breakpoints. Each
200881ad6265SDimitry Andric breakpoint name can be added to any number of breakpoints, and each breakpoint
200981ad6265SDimitry Andric can have any number of breakpoint names attached to it. For instance:
201081ad6265SDimitry Andric
201181ad6265SDimitry Andric (lldb) break name add -N MyName 1-10
201281ad6265SDimitry Andric
201381ad6265SDimitry Andric adds the name MyName to breakpoints 1-10, and:
201481ad6265SDimitry Andric
201581ad6265SDimitry Andric (lldb) break set -n myFunc -N Name1 -N Name2
201681ad6265SDimitry Andric
201781ad6265SDimitry Andric adds two names to the breakpoint set at myFunc.
201881ad6265SDimitry Andric
201981ad6265SDimitry Andric They have a number of interrelated uses:
202081ad6265SDimitry Andric
202181ad6265SDimitry Andric 1) They provide a stable way to refer to a breakpoint (e.g. in another
202281ad6265SDimitry Andric breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
202381ad6265SDimitry Andric it depends on the order of breakpoint creation. Giving a name to the breakpoint
202481ad6265SDimitry Andric you want to act on, and then referring to it by name, is more robust:
202581ad6265SDimitry Andric
202681ad6265SDimitry Andric (lldb) break set -n myFunc -N BKPT1
202781ad6265SDimitry Andric (lldb) break set -n myOtherFunc -C "break disable BKPT1"
202881ad6265SDimitry Andric
202981ad6265SDimitry Andric 2) This is actually just a specific use of a more general feature of breakpoint
203081ad6265SDimitry Andric names. The <breakpt-id-list> argument type used to specify one or more
203181ad6265SDimitry Andric breakpoints in most of the commands that deal with breakpoints also accepts
203281ad6265SDimitry Andric breakpoint names. That allows you to refer to one breakpoint in a stable
203381ad6265SDimitry Andric manner, but also makes them a convenient grouping mechanism, allowing you to
203481ad6265SDimitry Andric easily act on a group of breakpoints by using their name, for instance disabling
203581ad6265SDimitry Andric them all in one action:
203681ad6265SDimitry Andric
203781ad6265SDimitry Andric (lldb) break set -n myFunc -N Group1
203881ad6265SDimitry Andric (lldb) break set -n myOtherFunc -N Group1
203981ad6265SDimitry Andric (lldb) break disable Group1
204081ad6265SDimitry Andric
204181ad6265SDimitry Andric 3) But breakpoint names are also entities in their own right, and can be
204281ad6265SDimitry Andric configured with all the modifiable attributes of a breakpoint. Then when you
204381ad6265SDimitry Andric add a breakpoint name to a breakpoint, the breakpoint will be configured to
204481ad6265SDimitry Andric match the state of the breakpoint name. The link between the name and the
204581ad6265SDimitry Andric breakpoints sharing it remains live, so if you change the configuration on the
204681ad6265SDimitry Andric name, it will also change the configurations on the breakpoints:
204781ad6265SDimitry Andric
204881ad6265SDimitry Andric (lldb) break name configure -i 10 IgnoreSome
204981ad6265SDimitry Andric (lldb) break set -n myFunc -N IgnoreSome
205081ad6265SDimitry Andric (lldb) break list IgnoreSome
205181ad6265SDimitry Andric 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
205281ad6265SDimitry Andric Names:
205381ad6265SDimitry Andric IgnoreSome
205481ad6265SDimitry Andric (lldb) break name configure -i 5 IgnoreSome
205581ad6265SDimitry Andric (lldb) break list IgnoreSome
205681ad6265SDimitry Andric 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
205781ad6265SDimitry Andric Names:
205881ad6265SDimitry Andric IgnoreSome
205981ad6265SDimitry Andric
206081ad6265SDimitry Andric Options that are not configured on a breakpoint name don't affect the value of
206181ad6265SDimitry Andric those options on the breakpoints they are added to. So for instance, if Name1
206281ad6265SDimitry Andric has the -i option configured and Name2 the -c option, adding both names to a
206381ad6265SDimitry Andric breakpoint will set the -i option from Name1 and the -c option from Name2, and
206481ad6265SDimitry Andric the other options will be unaltered.
206581ad6265SDimitry Andric
206681ad6265SDimitry Andric If you add multiple names to a breakpoint which have configured values for
206781ad6265SDimitry Andric the same option, the last name added's value wins.
206881ad6265SDimitry Andric
206981ad6265SDimitry Andric The "liveness" of these settings is one way, from name to breakpoint.
207081ad6265SDimitry Andric If you use "break modify" to change an option that is also configured on a name
207181ad6265SDimitry Andric which that breakpoint has, the "break modify" command will override the setting
207281ad6265SDimitry Andric for that breakpoint, but won't change the value configured in the name or on the
207381ad6265SDimitry Andric other breakpoints sharing that name.
207481ad6265SDimitry Andric
207581ad6265SDimitry Andric 4) Breakpoint names are also a convenient way to copy option sets from one
207681ad6265SDimitry Andric breakpoint to another. Using the -B option to "breakpoint name configure" makes
207781ad6265SDimitry Andric a name configured with all the options of the original breakpoint. Then
207881ad6265SDimitry Andric adding that name to another breakpoint copies over all the values from the
207981ad6265SDimitry Andric original breakpoint to the new one.
208081ad6265SDimitry Andric
208181ad6265SDimitry Andric 5) You can also use breakpoint names to hide breakpoints from the breakpoint
208281ad6265SDimitry Andric operations that act on all breakpoints: "break delete", "break disable" and
208381ad6265SDimitry Andric "break list". You do that by specifying a "false" value for the
208481ad6265SDimitry Andric --allow-{list,delete,disable} options to "breakpoint name configure" and then
208581ad6265SDimitry Andric adding that name to a breakpoint.
208681ad6265SDimitry Andric
208781ad6265SDimitry Andric This won't keep the breakpoint from being deleted or disabled if you refer to it
208881ad6265SDimitry Andric specifically by ID. The point of the feature is to make sure users don't
208981ad6265SDimitry Andric inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
209081ad6265SDimitry Andric for its own purposes) as part of a "delete all" or "disable all" operation. The
209181ad6265SDimitry Andric list hiding is because it's confusing for people to see breakpoints they
209281ad6265SDimitry Andric didn't set.
209381ad6265SDimitry Andric
209481ad6265SDimitry Andric )");
20950b57cec5SDimitry Andric CommandObjectSP add_command_object(
20960b57cec5SDimitry Andric new CommandObjectBreakpointNameAdd(interpreter));
20970b57cec5SDimitry Andric CommandObjectSP delete_command_object(
20980b57cec5SDimitry Andric new CommandObjectBreakpointNameDelete(interpreter));
20990b57cec5SDimitry Andric CommandObjectSP list_command_object(
21000b57cec5SDimitry Andric new CommandObjectBreakpointNameList(interpreter));
21010b57cec5SDimitry Andric CommandObjectSP configure_command_object(
21020b57cec5SDimitry Andric new CommandObjectBreakpointNameConfigure(interpreter));
21030b57cec5SDimitry Andric
21040b57cec5SDimitry Andric LoadSubCommand("add", add_command_object);
21050b57cec5SDimitry Andric LoadSubCommand("delete", delete_command_object);
21060b57cec5SDimitry Andric LoadSubCommand("list", list_command_object);
21070b57cec5SDimitry Andric LoadSubCommand("configure", configure_command_object);
21080b57cec5SDimitry Andric }
21090b57cec5SDimitry Andric
21100b57cec5SDimitry Andric ~CommandObjectBreakpointName() override = default;
21110b57cec5SDimitry Andric };
21120b57cec5SDimitry Andric
21130b57cec5SDimitry Andric // CommandObjectBreakpointRead
21140b57cec5SDimitry Andric #pragma mark Read::CommandOptions
21159dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_read
21169dba64beSDimitry Andric #include "CommandOptions.inc"
21170b57cec5SDimitry Andric
21180b57cec5SDimitry Andric #pragma mark Read
21190b57cec5SDimitry Andric
21200b57cec5SDimitry Andric class CommandObjectBreakpointRead : public CommandObjectParsed {
21210b57cec5SDimitry Andric public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)21220b57cec5SDimitry Andric CommandObjectBreakpointRead(CommandInterpreter &interpreter)
21230b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "breakpoint read",
21240b57cec5SDimitry Andric "Read and set the breakpoints previously saved to "
21250b57cec5SDimitry Andric "a file with \"breakpoint write\". ",
212604eeddc0SDimitry Andric nullptr) {}
21270b57cec5SDimitry Andric
21280b57cec5SDimitry Andric ~CommandObjectBreakpointRead() override = default;
21290b57cec5SDimitry Andric
GetOptions()21300b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
21310b57cec5SDimitry Andric
21320b57cec5SDimitry Andric class CommandOptions : public Options {
21330b57cec5SDimitry Andric public:
213481ad6265SDimitry Andric CommandOptions() = default;
21350b57cec5SDimitry Andric
21360b57cec5SDimitry Andric ~CommandOptions() override = default;
21370b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)21380b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
21390b57cec5SDimitry Andric ExecutionContext *execution_context) override {
21400b57cec5SDimitry Andric Status error;
21410b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
21420b57cec5SDimitry Andric
21430b57cec5SDimitry Andric switch (short_option) {
21440b57cec5SDimitry Andric case 'f':
21455ffd83dbSDimitry Andric m_filename.assign(std::string(option_arg));
21460b57cec5SDimitry Andric break;
21470b57cec5SDimitry Andric case 'N': {
21480b57cec5SDimitry Andric Status name_error;
21490b57cec5SDimitry Andric if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
21500b57cec5SDimitry Andric name_error)) {
21510b57cec5SDimitry Andric error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21520b57cec5SDimitry Andric name_error.AsCString());
21530b57cec5SDimitry Andric }
21545ffd83dbSDimitry Andric m_names.push_back(std::string(option_arg));
21550b57cec5SDimitry Andric break;
21560b57cec5SDimitry Andric }
21570b57cec5SDimitry Andric default:
21589dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
21590b57cec5SDimitry Andric }
21600b57cec5SDimitry Andric
21610b57cec5SDimitry Andric return error;
21620b57cec5SDimitry Andric }
21630b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)21640b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
21650b57cec5SDimitry Andric m_filename.clear();
21660b57cec5SDimitry Andric m_names.clear();
21670b57cec5SDimitry Andric }
21680b57cec5SDimitry Andric
GetDefinitions()21690b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2170bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_read_options);
21710b57cec5SDimitry Andric }
21720b57cec5SDimitry Andric
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)2173e8d8bef9SDimitry Andric void HandleOptionArgumentCompletion(
2174e8d8bef9SDimitry Andric CompletionRequest &request, OptionElementVector &opt_element_vector,
2175e8d8bef9SDimitry Andric int opt_element_index, CommandInterpreter &interpreter) override {
2176e8d8bef9SDimitry Andric int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2177e8d8bef9SDimitry Andric int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2178e8d8bef9SDimitry Andric
2179e8d8bef9SDimitry Andric switch (GetDefinitions()[opt_defs_index].short_option) {
2180e8d8bef9SDimitry Andric case 'f':
2181fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2182fe013be4SDimitry Andric interpreter, lldb::eDiskFileCompletion, request, nullptr);
2183e8d8bef9SDimitry Andric break;
2184e8d8bef9SDimitry Andric
2185e8d8bef9SDimitry Andric case 'N':
2186bdd1243dSDimitry Andric std::optional<FileSpec> file_spec;
2187e8d8bef9SDimitry Andric const llvm::StringRef dash_f("-f");
2188e8d8bef9SDimitry Andric for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2189e8d8bef9SDimitry Andric if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2190e8d8bef9SDimitry Andric file_spec.emplace(
2191e8d8bef9SDimitry Andric request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2192e8d8bef9SDimitry Andric break;
2193e8d8bef9SDimitry Andric }
2194e8d8bef9SDimitry Andric }
2195e8d8bef9SDimitry Andric if (!file_spec)
2196e8d8bef9SDimitry Andric return;
2197e8d8bef9SDimitry Andric
2198e8d8bef9SDimitry Andric FileSystem::Instance().Resolve(*file_spec);
2199e8d8bef9SDimitry Andric Status error;
2200e8d8bef9SDimitry Andric StructuredData::ObjectSP input_data_sp =
2201e8d8bef9SDimitry Andric StructuredData::ParseJSONFromFile(*file_spec, error);
2202e8d8bef9SDimitry Andric if (!error.Success())
2203e8d8bef9SDimitry Andric return;
2204e8d8bef9SDimitry Andric
2205e8d8bef9SDimitry Andric StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2206e8d8bef9SDimitry Andric if (!bkpt_array)
2207e8d8bef9SDimitry Andric return;
2208e8d8bef9SDimitry Andric
2209e8d8bef9SDimitry Andric const size_t num_bkpts = bkpt_array->GetSize();
2210e8d8bef9SDimitry Andric for (size_t i = 0; i < num_bkpts; i++) {
2211e8d8bef9SDimitry Andric StructuredData::ObjectSP bkpt_object_sp =
2212e8d8bef9SDimitry Andric bkpt_array->GetItemAtIndex(i);
2213e8d8bef9SDimitry Andric if (!bkpt_object_sp)
2214e8d8bef9SDimitry Andric return;
2215e8d8bef9SDimitry Andric
2216e8d8bef9SDimitry Andric StructuredData::Dictionary *bkpt_dict =
2217e8d8bef9SDimitry Andric bkpt_object_sp->GetAsDictionary();
2218e8d8bef9SDimitry Andric if (!bkpt_dict)
2219e8d8bef9SDimitry Andric return;
2220e8d8bef9SDimitry Andric
2221e8d8bef9SDimitry Andric StructuredData::ObjectSP bkpt_data_sp =
2222e8d8bef9SDimitry Andric bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2223e8d8bef9SDimitry Andric if (!bkpt_data_sp)
2224e8d8bef9SDimitry Andric return;
2225e8d8bef9SDimitry Andric
2226e8d8bef9SDimitry Andric bkpt_dict = bkpt_data_sp->GetAsDictionary();
2227e8d8bef9SDimitry Andric if (!bkpt_dict)
2228e8d8bef9SDimitry Andric return;
2229e8d8bef9SDimitry Andric
2230e8d8bef9SDimitry Andric StructuredData::Array *names_array;
2231e8d8bef9SDimitry Andric
2232e8d8bef9SDimitry Andric if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2233e8d8bef9SDimitry Andric return;
2234e8d8bef9SDimitry Andric
2235e8d8bef9SDimitry Andric size_t num_names = names_array->GetSize();
2236e8d8bef9SDimitry Andric
2237e8d8bef9SDimitry Andric for (size_t i = 0; i < num_names; i++) {
2238c9157d92SDimitry Andric if (std::optional<llvm::StringRef> maybe_name =
2239c9157d92SDimitry Andric names_array->GetItemAtIndexAsString(i))
2240c9157d92SDimitry Andric request.TryCompleteCurrentArg(*maybe_name);
2241e8d8bef9SDimitry Andric }
2242e8d8bef9SDimitry Andric }
2243e8d8bef9SDimitry Andric }
2244e8d8bef9SDimitry Andric }
22450b57cec5SDimitry Andric
22460b57cec5SDimitry Andric std::string m_filename;
22470b57cec5SDimitry Andric std::vector<std::string> m_names;
22480b57cec5SDimitry Andric };
22490b57cec5SDimitry Andric
22500b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2251c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
22529dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget();
22530b57cec5SDimitry Andric
22540b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
22559dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
22560b57cec5SDimitry Andric
22570b57cec5SDimitry Andric FileSpec input_spec(m_options.m_filename);
22580b57cec5SDimitry Andric FileSystem::Instance().Resolve(input_spec);
22590b57cec5SDimitry Andric BreakpointIDList new_bps;
22609dba64beSDimitry Andric Status error = target.CreateBreakpointsFromFile(input_spec,
22619dba64beSDimitry Andric m_options.m_names, new_bps);
22620b57cec5SDimitry Andric
22630b57cec5SDimitry Andric if (!error.Success()) {
22640b57cec5SDimitry Andric result.AppendError(error.AsCString());
2265c9157d92SDimitry Andric return;
22660b57cec5SDimitry Andric }
22670b57cec5SDimitry Andric
22680b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream();
22690b57cec5SDimitry Andric
22700b57cec5SDimitry Andric size_t num_breakpoints = new_bps.GetSize();
22710b57cec5SDimitry Andric if (num_breakpoints == 0) {
22720b57cec5SDimitry Andric result.AppendMessage("No breakpoints added.");
22730b57cec5SDimitry Andric } else {
22740b57cec5SDimitry Andric // No breakpoint selected; show info about all currently set breakpoints.
22750b57cec5SDimitry Andric result.AppendMessage("New breakpoints:");
22760b57cec5SDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
22770b57cec5SDimitry Andric BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
22789dba64beSDimitry Andric Breakpoint *bp = target.GetBreakpointList()
22790b57cec5SDimitry Andric .FindBreakpointByID(bp_id.GetBreakpointID())
22800b57cec5SDimitry Andric .get();
22810b57cec5SDimitry Andric if (bp)
22820b57cec5SDimitry Andric bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22830b57cec5SDimitry Andric false);
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric }
22860b57cec5SDimitry Andric }
22870b57cec5SDimitry Andric
22880b57cec5SDimitry Andric private:
22890b57cec5SDimitry Andric CommandOptions m_options;
22900b57cec5SDimitry Andric };
22910b57cec5SDimitry Andric
22920b57cec5SDimitry Andric // CommandObjectBreakpointWrite
22930b57cec5SDimitry Andric #pragma mark Write::CommandOptions
22949dba64beSDimitry Andric #define LLDB_OPTIONS_breakpoint_write
22959dba64beSDimitry Andric #include "CommandOptions.inc"
22960b57cec5SDimitry Andric
22970b57cec5SDimitry Andric #pragma mark Write
22980b57cec5SDimitry Andric class CommandObjectBreakpointWrite : public CommandObjectParsed {
22990b57cec5SDimitry Andric public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)23000b57cec5SDimitry Andric CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
23010b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "breakpoint write",
23020b57cec5SDimitry Andric "Write the breakpoints listed to a file that can "
23030b57cec5SDimitry Andric "be read in with \"breakpoint read\". "
23040b57cec5SDimitry Andric "If given no arguments, writes all breakpoints.",
230504eeddc0SDimitry Andric nullptr) {
23060b57cec5SDimitry Andric CommandArgumentEntry arg;
23070b57cec5SDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
23080b57cec5SDimitry Andric eArgTypeBreakpointIDRange);
23090b57cec5SDimitry Andric // Add the entry for the first argument for this command to the object's
23100b57cec5SDimitry Andric // arguments vector.
23110b57cec5SDimitry Andric m_arguments.push_back(arg);
23120b57cec5SDimitry Andric }
23130b57cec5SDimitry Andric
23140b57cec5SDimitry Andric ~CommandObjectBreakpointWrite() override = default;
23150b57cec5SDimitry Andric
23165ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)23175ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
23185ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
2319fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2320fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
23215ffd83dbSDimitry Andric }
23225ffd83dbSDimitry Andric
GetOptions()23230b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
23240b57cec5SDimitry Andric
23250b57cec5SDimitry Andric class CommandOptions : public Options {
23260b57cec5SDimitry Andric public:
232781ad6265SDimitry Andric CommandOptions() = default;
23280b57cec5SDimitry Andric
23290b57cec5SDimitry Andric ~CommandOptions() override = default;
23300b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)23310b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
23320b57cec5SDimitry Andric ExecutionContext *execution_context) override {
23330b57cec5SDimitry Andric Status error;
23340b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
23350b57cec5SDimitry Andric
23360b57cec5SDimitry Andric switch (short_option) {
23370b57cec5SDimitry Andric case 'f':
23385ffd83dbSDimitry Andric m_filename.assign(std::string(option_arg));
23390b57cec5SDimitry Andric break;
23400b57cec5SDimitry Andric case 'a':
23410b57cec5SDimitry Andric m_append = true;
23420b57cec5SDimitry Andric break;
23430b57cec5SDimitry Andric default:
23449dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
23450b57cec5SDimitry Andric }
23460b57cec5SDimitry Andric
23470b57cec5SDimitry Andric return error;
23480b57cec5SDimitry Andric }
23490b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)23500b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
23510b57cec5SDimitry Andric m_filename.clear();
23520b57cec5SDimitry Andric m_append = false;
23530b57cec5SDimitry Andric }
23540b57cec5SDimitry Andric
GetDefinitions()23550b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2356bdd1243dSDimitry Andric return llvm::ArrayRef(g_breakpoint_write_options);
23570b57cec5SDimitry Andric }
23580b57cec5SDimitry Andric
23590b57cec5SDimitry Andric // Instance variables to hold the values for command options.
23600b57cec5SDimitry Andric
23610b57cec5SDimitry Andric std::string m_filename;
23620b57cec5SDimitry Andric bool m_append = false;
23630b57cec5SDimitry Andric };
23640b57cec5SDimitry Andric
23650b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2366c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
23679dba64beSDimitry Andric Target &target = GetSelectedOrDummyTarget();
23680b57cec5SDimitry Andric
23690b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
23709dba64beSDimitry Andric target.GetBreakpointList().GetListMutex(lock);
23710b57cec5SDimitry Andric
23720b57cec5SDimitry Andric BreakpointIDList valid_bp_ids;
23730b57cec5SDimitry Andric if (!command.empty()) {
23740b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
23759dba64beSDimitry Andric command, &target, result, &valid_bp_ids,
23760b57cec5SDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
23770b57cec5SDimitry Andric
23780b57cec5SDimitry Andric if (!result.Succeeded()) {
23790b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed);
2380c9157d92SDimitry Andric return;
23810b57cec5SDimitry Andric }
23820b57cec5SDimitry Andric }
23830b57cec5SDimitry Andric FileSpec file_spec(m_options.m_filename);
23840b57cec5SDimitry Andric FileSystem::Instance().Resolve(file_spec);
23859dba64beSDimitry Andric Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23860b57cec5SDimitry Andric m_options.m_append);
23870b57cec5SDimitry Andric if (!error.Success()) {
23880b57cec5SDimitry Andric result.AppendErrorWithFormat("error serializing breakpoints: %s.",
23890b57cec5SDimitry Andric error.AsCString());
23900b57cec5SDimitry Andric }
23910b57cec5SDimitry Andric }
23920b57cec5SDimitry Andric
23930b57cec5SDimitry Andric private:
23940b57cec5SDimitry Andric CommandOptions m_options;
23950b57cec5SDimitry Andric };
23960b57cec5SDimitry Andric
23970b57cec5SDimitry Andric // CommandObjectMultiwordBreakpoint
23980b57cec5SDimitry Andric #pragma mark MultiwordBreakpoint
23990b57cec5SDimitry Andric
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)24000b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
24010b57cec5SDimitry Andric CommandInterpreter &interpreter)
24020b57cec5SDimitry Andric : CommandObjectMultiword(
24030b57cec5SDimitry Andric interpreter, "breakpoint",
24040b57cec5SDimitry Andric "Commands for operating on breakpoints (see 'help b' for shorthand.)",
24050b57cec5SDimitry Andric "breakpoint <subcommand> [<command-options>]") {
24060b57cec5SDimitry Andric CommandObjectSP list_command_object(
24070b57cec5SDimitry Andric new CommandObjectBreakpointList(interpreter));
24080b57cec5SDimitry Andric CommandObjectSP enable_command_object(
24090b57cec5SDimitry Andric new CommandObjectBreakpointEnable(interpreter));
24100b57cec5SDimitry Andric CommandObjectSP disable_command_object(
24110b57cec5SDimitry Andric new CommandObjectBreakpointDisable(interpreter));
24120b57cec5SDimitry Andric CommandObjectSP clear_command_object(
24130b57cec5SDimitry Andric new CommandObjectBreakpointClear(interpreter));
24140b57cec5SDimitry Andric CommandObjectSP delete_command_object(
24150b57cec5SDimitry Andric new CommandObjectBreakpointDelete(interpreter));
24160b57cec5SDimitry Andric CommandObjectSP set_command_object(
24170b57cec5SDimitry Andric new CommandObjectBreakpointSet(interpreter));
24180b57cec5SDimitry Andric CommandObjectSP command_command_object(
24190b57cec5SDimitry Andric new CommandObjectBreakpointCommand(interpreter));
24200b57cec5SDimitry Andric CommandObjectSP modify_command_object(
24210b57cec5SDimitry Andric new CommandObjectBreakpointModify(interpreter));
24220b57cec5SDimitry Andric CommandObjectSP name_command_object(
24230b57cec5SDimitry Andric new CommandObjectBreakpointName(interpreter));
24240b57cec5SDimitry Andric CommandObjectSP write_command_object(
24250b57cec5SDimitry Andric new CommandObjectBreakpointWrite(interpreter));
24260b57cec5SDimitry Andric CommandObjectSP read_command_object(
24270b57cec5SDimitry Andric new CommandObjectBreakpointRead(interpreter));
24280b57cec5SDimitry Andric
24290b57cec5SDimitry Andric list_command_object->SetCommandName("breakpoint list");
24300b57cec5SDimitry Andric enable_command_object->SetCommandName("breakpoint enable");
24310b57cec5SDimitry Andric disable_command_object->SetCommandName("breakpoint disable");
24320b57cec5SDimitry Andric clear_command_object->SetCommandName("breakpoint clear");
24330b57cec5SDimitry Andric delete_command_object->SetCommandName("breakpoint delete");
24340b57cec5SDimitry Andric set_command_object->SetCommandName("breakpoint set");
24350b57cec5SDimitry Andric command_command_object->SetCommandName("breakpoint command");
24360b57cec5SDimitry Andric modify_command_object->SetCommandName("breakpoint modify");
24370b57cec5SDimitry Andric name_command_object->SetCommandName("breakpoint name");
24380b57cec5SDimitry Andric write_command_object->SetCommandName("breakpoint write");
24390b57cec5SDimitry Andric read_command_object->SetCommandName("breakpoint read");
24400b57cec5SDimitry Andric
24410b57cec5SDimitry Andric LoadSubCommand("list", list_command_object);
24420b57cec5SDimitry Andric LoadSubCommand("enable", enable_command_object);
24430b57cec5SDimitry Andric LoadSubCommand("disable", disable_command_object);
24440b57cec5SDimitry Andric LoadSubCommand("clear", clear_command_object);
24450b57cec5SDimitry Andric LoadSubCommand("delete", delete_command_object);
24460b57cec5SDimitry Andric LoadSubCommand("set", set_command_object);
24470b57cec5SDimitry Andric LoadSubCommand("command", command_command_object);
24480b57cec5SDimitry Andric LoadSubCommand("modify", modify_command_object);
24490b57cec5SDimitry Andric LoadSubCommand("name", name_command_object);
24500b57cec5SDimitry Andric LoadSubCommand("write", write_command_object);
24510b57cec5SDimitry Andric LoadSubCommand("read", read_command_object);
24520b57cec5SDimitry Andric }
24530b57cec5SDimitry Andric
24540b57cec5SDimitry Andric CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
24550b57cec5SDimitry Andric
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2456480093f4SDimitry Andric void CommandObjectMultiwordBreakpoint::VerifyIDs(
2457480093f4SDimitry Andric Args &args, Target *target, bool allow_locations,
2458480093f4SDimitry Andric CommandReturnObject &result, BreakpointIDList *valid_ids,
2459480093f4SDimitry Andric BreakpointName::Permissions ::PermissionKinds purpose) {
24600b57cec5SDimitry Andric // args can be strings representing 1). integers (for breakpoint ids)
24610b57cec5SDimitry Andric // 2). the full breakpoint & location
24620b57cec5SDimitry Andric // canonical representation
24630b57cec5SDimitry Andric // 3). the word "to" or a hyphen,
24640b57cec5SDimitry Andric // representing a range (in which case there
24650b57cec5SDimitry Andric // had *better* be an entry both before &
24660b57cec5SDimitry Andric // after of one of the first two types.
24670b57cec5SDimitry Andric // 4). A breakpoint name
24680b57cec5SDimitry Andric // If args is empty, we will use the last created breakpoint (if there is
24690b57cec5SDimitry Andric // one.)
24700b57cec5SDimitry Andric
24710b57cec5SDimitry Andric Args temp_args;
24720b57cec5SDimitry Andric
24730b57cec5SDimitry Andric if (args.empty()) {
24740b57cec5SDimitry Andric if (target->GetLastCreatedBreakpoint()) {
24750b57cec5SDimitry Andric valid_ids->AddBreakpointID(BreakpointID(
24760b57cec5SDimitry Andric target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
24770b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
24780b57cec5SDimitry Andric } else {
24790b57cec5SDimitry Andric result.AppendError(
24800b57cec5SDimitry Andric "No breakpoint specified and no last created breakpoint.");
24810b57cec5SDimitry Andric }
24820b57cec5SDimitry Andric return;
24830b57cec5SDimitry Andric }
24840b57cec5SDimitry Andric
24850b57cec5SDimitry Andric // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
24860b57cec5SDimitry Andric // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
24870b57cec5SDimitry Andric // id range strings over; instead generate a list of strings for all the
24880b57cec5SDimitry Andric // breakpoint ids in the range, and shove all of those breakpoint id strings
24890b57cec5SDimitry Andric // into TEMP_ARGS.
24900b57cec5SDimitry Andric
2491*a58f00eaSDimitry Andric if (llvm::Error err = BreakpointIDList::FindAndReplaceIDRanges(
2492*a58f00eaSDimitry Andric args, target, allow_locations, purpose, temp_args)) {
2493*a58f00eaSDimitry Andric result.SetError(std::move(err));
2494*a58f00eaSDimitry Andric return;
2495*a58f00eaSDimitry Andric }
2496*a58f00eaSDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
24970b57cec5SDimitry Andric
24980b57cec5SDimitry Andric // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
24990b57cec5SDimitry Andric // BreakpointIDList:
25000b57cec5SDimitry Andric
2501cdc20ff6SDimitry Andric for (llvm::StringRef temp_arg : temp_args.GetArgumentArrayRef())
2502cdc20ff6SDimitry Andric if (auto bp_id = BreakpointID::ParseCanonicalReference(temp_arg))
2503cdc20ff6SDimitry Andric valid_ids->AddBreakpointID(*bp_id);
25040b57cec5SDimitry Andric
25050b57cec5SDimitry Andric // At this point, all of the breakpoint ids that the user passed in have
25060b57cec5SDimitry Andric // been converted to breakpoint IDs and put into valid_ids.
25070b57cec5SDimitry Andric
25080b57cec5SDimitry Andric // Now that we've converted everything from args into a list of breakpoint
25090b57cec5SDimitry Andric // ids, go through our tentative list of breakpoint id's and verify that
25100b57cec5SDimitry Andric // they correspond to valid/currently set breakpoints.
25110b57cec5SDimitry Andric
25120b57cec5SDimitry Andric const size_t count = valid_ids->GetSize();
25130b57cec5SDimitry Andric for (size_t i = 0; i < count; ++i) {
25140b57cec5SDimitry Andric BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
25150b57cec5SDimitry Andric Breakpoint *breakpoint =
25160b57cec5SDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
25170b57cec5SDimitry Andric if (breakpoint != nullptr) {
25180b57cec5SDimitry Andric const size_t num_locations = breakpoint->GetNumLocations();
25190b57cec5SDimitry Andric if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
25200b57cec5SDimitry Andric StreamString id_str;
25210b57cec5SDimitry Andric BreakpointID::GetCanonicalReference(
25220b57cec5SDimitry Andric &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
25230b57cec5SDimitry Andric i = valid_ids->GetSize() + 1;
25240b57cec5SDimitry Andric result.AppendErrorWithFormat(
25250b57cec5SDimitry Andric "'%s' is not a currently valid breakpoint/location id.\n",
25260b57cec5SDimitry Andric id_str.GetData());
25270b57cec5SDimitry Andric }
25280b57cec5SDimitry Andric } else {
25290b57cec5SDimitry Andric i = valid_ids->GetSize() + 1;
25300b57cec5SDimitry Andric result.AppendErrorWithFormat(
25310b57cec5SDimitry Andric "'%d' is not a currently valid breakpoint ID.\n",
25320b57cec5SDimitry Andric cur_bp_id.GetBreakpointID());
25330b57cec5SDimitry Andric }
25340b57cec5SDimitry Andric }
25350b57cec5SDimitry Andric }
2536