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