130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h" 109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h" 1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h" 16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 230e0984eeSJim Ingham #include "lldb/Target/Language.h" 24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 25b9c1b51eSKate Stone #include "lldb/Target/Target.h" 261b54c88cSJim Ingham #include "lldb/Target/Thread.h" 271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 3030fdc8d8SChris Lattner 31796ac80bSJonas Devlieghere #include <memory> 32796ac80bSJonas Devlieghere #include <vector> 33796ac80bSJonas Devlieghere 3430fdc8d8SChris Lattner using namespace lldb; 3530fdc8d8SChris Lattner using namespace lldb_private; 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 38b9c1b51eSKate Stone lldb::DescriptionLevel level) { 3930fdc8d8SChris Lattner s->IndentMore(); 4030fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4130fdc8d8SChris Lattner s->IndentLess(); 4230fdc8d8SChris Lattner s->EOL(); 4330fdc8d8SChris Lattner } 4430fdc8d8SChris Lattner 45b842f2ecSJim Ingham // Modifiable Breakpoint Options 46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 478fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_modify_options[] = { 48b842f2ecSJim Ingham // clang-format off 498fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, 508fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, 518fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, 528fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, 538fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, 548fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, 558fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 568fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, 578fe53c49STatyana Krasnukha { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." }, 588fe53c49STatyana Krasnukha { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." }, 598fe53c49STatyana Krasnukha { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, 60b842f2ecSJim Ingham // clang-format on 61b842f2ecSJim Ingham }; 62b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup 63b842f2ecSJim Ingham { 64b842f2ecSJim Ingham public: 65b842f2ecSJim Ingham BreakpointOptionGroup() : 66b842f2ecSJim Ingham OptionGroup(), 67b842f2ecSJim Ingham m_bp_opts(false) {} 68b842f2ecSJim Ingham 69b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 70b842f2ecSJim Ingham 71b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 72b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 73b842f2ecSJim Ingham } 74b842f2ecSJim Ingham 75b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 76b842f2ecSJim Ingham ExecutionContext *execution_context) override { 77b842f2ecSJim Ingham Status error; 78b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 79b842f2ecSJim Ingham 80b842f2ecSJim Ingham switch (short_option) { 81b842f2ecSJim Ingham case 'c': 8205097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 8305097246SAdrian Prantl // to say it was passed in. 84b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 85b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 86b842f2ecSJim Ingham break; 87b842f2ecSJim Ingham case 'C': 88b842f2ecSJim Ingham m_commands.push_back(option_arg); 89b842f2ecSJim Ingham break; 90b842f2ecSJim Ingham case 'd': 91b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 92b842f2ecSJim Ingham break; 93b842f2ecSJim Ingham case 'e': 94b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 95b842f2ecSJim Ingham break; 96b842f2ecSJim Ingham case 'G': { 97b842f2ecSJim Ingham bool value, success; 9847cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 99b842f2ecSJim Ingham if (success) { 100b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 101b842f2ecSJim Ingham } else 102b842f2ecSJim Ingham error.SetErrorStringWithFormat( 103b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 104b842f2ecSJim Ingham option_arg.str().c_str()); 105b842f2ecSJim Ingham } 106b842f2ecSJim Ingham break; 107b842f2ecSJim Ingham case 'i': 108b842f2ecSJim Ingham { 109b842f2ecSJim Ingham uint32_t ignore_count; 110b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 111b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 112b842f2ecSJim Ingham option_arg.str().c_str()); 113b842f2ecSJim Ingham else 114b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 115b842f2ecSJim Ingham } 116b842f2ecSJim Ingham break; 117b842f2ecSJim Ingham case 'o': { 118b842f2ecSJim Ingham bool value, success; 11947cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 120b842f2ecSJim Ingham if (success) { 121b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 122b842f2ecSJim Ingham } else 123b842f2ecSJim Ingham error.SetErrorStringWithFormat( 124b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 125b842f2ecSJim Ingham option_arg.str().c_str()); 126b842f2ecSJim Ingham } break; 127b842f2ecSJim Ingham case 't': 128b842f2ecSJim Ingham { 129b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 130b842f2ecSJim Ingham if (option_arg[0] != '\0') { 131b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 132b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 133b842f2ecSJim Ingham option_arg.str().c_str()); 134b842f2ecSJim Ingham } 135b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 136b842f2ecSJim Ingham } 137b842f2ecSJim Ingham break; 138b842f2ecSJim Ingham case 'T': 139b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 140b842f2ecSJim Ingham break; 141b842f2ecSJim Ingham case 'q': 142b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 143b842f2ecSJim Ingham break; 144b842f2ecSJim Ingham case 'x': 145b842f2ecSJim Ingham { 146b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 147b842f2ecSJim Ingham if (option_arg[0] != '\n') { 148b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 149b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 150b842f2ecSJim Ingham option_arg.str().c_str()); 151b842f2ecSJim Ingham } 152b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 153b842f2ecSJim Ingham } 154b842f2ecSJim Ingham break; 155b842f2ecSJim Ingham default: 156b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 157b842f2ecSJim Ingham short_option); 158b842f2ecSJim Ingham break; 159b842f2ecSJim Ingham } 160b842f2ecSJim Ingham 161b842f2ecSJim Ingham return error; 162b842f2ecSJim Ingham } 163b842f2ecSJim Ingham 164b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 165b842f2ecSJim Ingham m_bp_opts.Clear(); 166b842f2ecSJim Ingham m_commands.clear(); 167b842f2ecSJim Ingham } 168b842f2ecSJim Ingham 169b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 170b842f2ecSJim Ingham if (!m_commands.empty()) 171b842f2ecSJim Ingham { 172b842f2ecSJim Ingham if (!m_commands.empty()) 173b842f2ecSJim Ingham { 174b842f2ecSJim Ingham auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); 175b842f2ecSJim Ingham 176b842f2ecSJim Ingham for (std::string &str : m_commands) 177b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 178b842f2ecSJim Ingham 179b842f2ecSJim Ingham cmd_data->stop_on_error = true; 180b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 181b842f2ecSJim Ingham } 182b842f2ecSJim Ingham } 183b842f2ecSJim Ingham return Status(); 184b842f2ecSJim Ingham } 185b842f2ecSJim Ingham 186b842f2ecSJim Ingham const BreakpointOptions &GetBreakpointOptions() 187b842f2ecSJim Ingham { 188b842f2ecSJim Ingham return m_bp_opts; 189b842f2ecSJim Ingham } 190b842f2ecSJim Ingham 191b842f2ecSJim Ingham std::vector<std::string> m_commands; 192b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 193b842f2ecSJim Ingham 194b842f2ecSJim Ingham }; 1958fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_dummy_options[] = { 196b842f2ecSJim Ingham // clang-format off 1978fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " 198b842f2ecSJim Ingham "which prime new targets." }, 199b842f2ecSJim Ingham // clang-format on 200b842f2ecSJim Ingham }; 201b842f2ecSJim Ingham 202b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup 203b842f2ecSJim Ingham { 204b842f2ecSJim Ingham public: 205b842f2ecSJim Ingham BreakpointDummyOptionGroup() : 206b842f2ecSJim Ingham OptionGroup() {} 207b842f2ecSJim Ingham 208b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 209b842f2ecSJim Ingham 210b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 211b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 212b842f2ecSJim Ingham } 213b842f2ecSJim Ingham 214b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 215b842f2ecSJim Ingham ExecutionContext *execution_context) override { 216b842f2ecSJim Ingham Status error; 217b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 218b842f2ecSJim Ingham 219b842f2ecSJim Ingham switch (short_option) { 220b842f2ecSJim Ingham case 'D': 221b842f2ecSJim Ingham m_use_dummy = true; 222b842f2ecSJim Ingham break; 223b842f2ecSJim Ingham default: 224b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 225b842f2ecSJim Ingham short_option); 226b842f2ecSJim Ingham break; 227b842f2ecSJim Ingham } 228b842f2ecSJim Ingham 229b842f2ecSJim Ingham return error; 230b842f2ecSJim Ingham } 231b842f2ecSJim Ingham 232b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 233b842f2ecSJim Ingham m_use_dummy = false; 234b842f2ecSJim Ingham } 235b842f2ecSJim Ingham 236b842f2ecSJim Ingham bool m_use_dummy; 237b842f2ecSJim Ingham 238b842f2ecSJim Ingham }; 239b842f2ecSJim Ingham 2401f0f5b5bSZachary Turner // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 2411f0f5b5bSZachary Turner // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 2423815e702SJim Ingham #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10) 2431f0f5b5bSZachary Turner #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 2443815e702SJim Ingham #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10) 2453815e702SJim Ingham #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2) 2461f0f5b5bSZachary Turner #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 2471f0f5b5bSZachary Turner #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 2481f0f5b5bSZachary Turner 2498fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_set_options[] = { 2501f0f5b5bSZachary Turner // clang-format off 2518fe53c49STatyana Krasnukha { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " 2521f0f5b5bSZachary Turner "multiple times to specify multiple shared libraries." }, 2538fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, 2548fe53c49STatyana Krasnukha { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " 2551f0f5b5bSZachary Turner "lldb only looks for files that are #included if they use the standard include " 2561f0f5b5bSZachary Turner "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 2571f0f5b5bSZachary Turner "#included, set target.inline-breakpoint-strategy to \"always\"." }, 2588fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, 2591f0f5b5bSZachary Turner 26005097246SAdrian Prantl // Comment out this option for the moment, as we don't actually use it, but 26105097246SAdrian Prantl // will in the future. This way users won't see it, but the infrastructure is 26205097246SAdrian Prantl // left in place. 2631f0f5b5bSZachary Turner // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 2641f0f5b5bSZachary Turner // "Set the breakpoint by source location at this particular column."}, 2651f0f5b5bSZachary Turner 2668fe53c49STatyana Krasnukha { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " 2671f0f5b5bSZachary Turner "a particular binary, then the address will be converted to a \"file\" " 2681f0f5b5bSZachary Turner "address, so that the breakpoint will track that binary+offset no matter where " 2691f0f5b5bSZachary Turner "the binary eventually loads. Alternately, if you also specify the module - " 2701f0f5b5bSZachary Turner "with the -s option - then the address will be treated as a file address in " 2711f0f5b5bSZachary Turner "that module, and resolved accordingly. Again, this will allow lldb to track " 2721f0f5b5bSZachary Turner "that offset on subsequent reloads. The module need not have been loaded at " 2731f0f5b5bSZachary Turner "the time you specify this breakpoint, and will get resolved when the module " 2741f0f5b5bSZachary Turner "is loaded." }, 2758fe53c49STatyana Krasnukha { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " 2761f0f5b5bSZachary Turner "one breakpoint for multiple names" }, 2778fe53c49STatyana Krasnukha { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " 2781f0f5b5bSZachary Turner "functions. Can be repeated multiple times." }, 2798fe53c49STatyana Krasnukha { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " 2804e8be2c9SAdrian Prantl "namespaces and all arguments, and for Objective-C this means a full function " 2811f0f5b5bSZachary Turner "prototype with class and selector. Can be repeated multiple times to make " 2821f0f5b5bSZachary Turner "one breakpoint for multiple names." }, 2838fe53c49STatyana Krasnukha { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " 2841f0f5b5bSZachary Turner "make one breakpoint for multiple Selectors." }, 2858fe53c49STatyana Krasnukha { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " 2861f0f5b5bSZachary Turner "make one breakpoint for multiple methods." }, 2878fe53c49STatyana Krasnukha { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " 2881f0f5b5bSZachary Turner "the function name(s)." }, 2898fe53c49STatyana Krasnukha { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " 2901f0f5b5bSZachary Turner "ignored). Can be repeated multiple times to make one breakpoint for multiple " 2911f0f5b5bSZachary Turner "symbols." }, 2928fe53c49STatyana Krasnukha { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " 2931f0f5b5bSZachary Turner "against the source text in a source file or files specified with the -f " 2941f0f5b5bSZachary Turner "option. The -f option can be specified more than once. If no source files " 2951f0f5b5bSZachary Turner "are specified, uses the current \"default source file\". If you want to " 2961f0f5b5bSZachary Turner "match against all source files, pass the \"--all-files\" option." }, 2978fe53c49STatyana Krasnukha { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." }, 2988fe53c49STatyana Krasnukha { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, 2998fe53c49STatyana Krasnukha { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, 3008fe53c49STatyana Krasnukha { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, 3018fe53c49STatyana Krasnukha { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " 3021f0f5b5bSZachary Turner "options, on throw but not catch.)" }, 3038fe53c49STatyana Krasnukha { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, 3048fe53c49STatyana Krasnukha { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, 3051f0f5b5bSZachary Turner 3061f0f5b5bSZachary Turner // Don't add this option till it actually does something useful... 3071f0f5b5bSZachary Turner // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 3081f0f5b5bSZachary Turner // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, 3091f0f5b5bSZachary Turner 3108fe53c49STatyana Krasnukha { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " 3111f0f5b5bSZachary Turner "(note: currently only implemented for setting breakpoints on identifiers). " 3121f0f5b5bSZachary Turner "If not set the target.language setting is used." }, 3138fe53c49STatyana Krasnukha { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " 3141f0f5b5bSZachary Turner "If not set the target.skip-prologue setting is used." }, 3158fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, 3168fe53c49STatyana Krasnukha { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " 3171f0f5b5bSZachary Turner "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, 3188fe53c49STatyana Krasnukha { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " 3191f0f5b5bSZachary Turner "setting is used." }, 3201f0f5b5bSZachary Turner // clang-format on 3211f0f5b5bSZachary Turner }; 3221f0f5b5bSZachary Turner 3235a988416SJim Ingham // CommandObjectBreakpointSet 32430fdc8d8SChris Lattner 325b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 3265a988416SJim Ingham public: 327*efe8e7e3SFangrui Song enum BreakpointSetType { 3285a988416SJim Ingham eSetTypeInvalid, 3295a988416SJim Ingham eSetTypeFileAndLine, 3305a988416SJim Ingham eSetTypeAddress, 3315a988416SJim Ingham eSetTypeFunctionName, 3325a988416SJim Ingham eSetTypeFunctionRegexp, 3335a988416SJim Ingham eSetTypeSourceRegexp, 3343815e702SJim Ingham eSetTypeException, 3353815e702SJim Ingham eSetTypeScripted, 336*efe8e7e3SFangrui Song }; 3375a988416SJim Ingham 338b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 339b9c1b51eSKate Stone : CommandObjectParsed( 340b9c1b51eSKate Stone interpreter, "breakpoint set", 3415a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 3425a988416SJim Ingham "breakpoint set <cmd-options>"), 343b842f2ecSJim Ingham m_bp_opts(), m_options() { 344b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 345b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 346b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 347b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 348b842f2ecSJim Ingham m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 349b842f2ecSJim Ingham m_all_options.Append(&m_options); 350b842f2ecSJim Ingham m_all_options.Finalize(); 351b842f2ecSJim Ingham } 3525a988416SJim Ingham 3539e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 3545a988416SJim Ingham 355b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 3565a988416SJim Ingham 357b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 3585a988416SJim Ingham public: 359b9c1b51eSKate Stone CommandOptions() 360b842f2ecSJim Ingham : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 361b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 362b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 363b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 364a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 36523b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 366b842f2ecSJim Ingham m_skip_prologue(eLazyBoolCalculate), 367b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 36830fdc8d8SChris Lattner 3699e85e5a8SEugene Zelenko ~CommandOptions() override = default; 37087df91b8SJim Ingham 37197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 372b9c1b51eSKate Stone ExecutionContext *execution_context) override { 37397206d57SZachary Turner Status error; 374b842f2ecSJim Ingham const int short_option = g_breakpoint_set_options[option_idx].short_option; 37530fdc8d8SChris Lattner 376b9c1b51eSKate Stone switch (short_option) { 377b9c1b51eSKate Stone case 'a': { 37847cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 379e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 380b9c1b51eSKate Stone } break; 38130fdc8d8SChris Lattner 382e732052fSJim Ingham case 'A': 383e732052fSJim Ingham m_all_files = true; 384e732052fSJim Ingham break; 385e732052fSJim Ingham 386ca36cd16SJim Ingham case 'b': 387ca36cd16SJim Ingham m_func_names.push_back(option_arg); 388ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 389ca36cd16SJim Ingham break; 390ca36cd16SJim Ingham 391fe11483bSZachary Turner case 'C': 392fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 393b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 394fe11483bSZachary Turner option_arg.str().c_str()); 39530fdc8d8SChris Lattner break; 3969e85e5a8SEugene Zelenko 397b9c1b51eSKate Stone case 'E': { 398fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 399fab10e89SJim Ingham 400b9c1b51eSKate Stone switch (language) { 401fab10e89SJim Ingham case eLanguageTypeC89: 402fab10e89SJim Ingham case eLanguageTypeC: 403fab10e89SJim Ingham case eLanguageTypeC99: 4041d0089faSBruce Mitchener case eLanguageTypeC11: 405a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 406fab10e89SJim Ingham break; 407fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 4081d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 4091d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 4102ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 411a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 412fab10e89SJim Ingham break; 413fab10e89SJim Ingham case eLanguageTypeObjC: 414a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 415fab10e89SJim Ingham break; 416fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 417b9c1b51eSKate Stone error.SetErrorStringWithFormat( 418b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 419fab10e89SJim Ingham break; 420fab10e89SJim Ingham case eLanguageTypeUnknown: 421b9c1b51eSKate Stone error.SetErrorStringWithFormat( 422b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 423fe11483bSZachary Turner option_arg.str().c_str()); 424fab10e89SJim Ingham break; 425fab10e89SJim Ingham default: 426b9c1b51eSKate Stone error.SetErrorStringWithFormat( 427b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 428fe11483bSZachary Turner option_arg.str().c_str()); 429fab10e89SJim Ingham } 430b9c1b51eSKate Stone } break; 431ca36cd16SJim Ingham 432ca36cd16SJim Ingham case 'f': 4338f3be7a3SJonas Devlieghere m_filenames.AppendIfUnique(FileSpec(option_arg)); 434fab10e89SJim Ingham break; 435ca36cd16SJim Ingham 436ca36cd16SJim Ingham case 'F': 437ca36cd16SJim Ingham m_func_names.push_back(option_arg); 438ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 439ca36cd16SJim Ingham break; 440ca36cd16SJim Ingham 441b9c1b51eSKate Stone case 'h': { 442fab10e89SJim Ingham bool success; 44347cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 444fab10e89SJim Ingham if (!success) 445b9c1b51eSKate Stone error.SetErrorStringWithFormat( 446fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 447fe11483bSZachary Turner option_arg.str().c_str()); 448b9c1b51eSKate Stone } break; 449eb023e75SGreg Clayton 450eb023e75SGreg Clayton case 'H': 451eb023e75SGreg Clayton m_hardware = true; 452eb023e75SGreg Clayton break; 453eb023e75SGreg Clayton 4543815e702SJim Ingham case 'k': { 4553815e702SJim Ingham if (m_current_key.empty()) 4563815e702SJim Ingham m_current_key.assign(option_arg); 4573815e702SJim Ingham else 4583815e702SJim Ingham error.SetErrorStringWithFormat("Key: %s missing value.", 4593815e702SJim Ingham m_current_key.c_str()); 4603815e702SJim Ingham 4613815e702SJim Ingham } break; 462b9c1b51eSKate Stone case 'K': { 463a8558b62SJim Ingham bool success; 464a8558b62SJim Ingham bool value; 46547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 466a8558b62SJim Ingham if (value) 467a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 468a8558b62SJim Ingham else 469a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 470a8558b62SJim Ingham 471a8558b62SJim Ingham if (!success) 472b9c1b51eSKate Stone error.SetErrorStringWithFormat( 473b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 474fe11483bSZachary Turner option_arg.str().c_str()); 475b9c1b51eSKate Stone } break; 476ca36cd16SJim Ingham 477fe11483bSZachary Turner case 'l': 478fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 479b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 480fe11483bSZachary Turner option_arg.str().c_str()); 481ca36cd16SJim Ingham break; 482055ad9beSIlia K 48323b1decbSDawn Perchik case 'L': 484fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 48523b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 486b9c1b51eSKate Stone error.SetErrorStringWithFormat( 487fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 488fe11483bSZachary Turner option_arg.str().c_str()); 48923b1decbSDawn Perchik break; 49023b1decbSDawn Perchik 491b9c1b51eSKate Stone case 'm': { 492055ad9beSIlia K bool success; 493055ad9beSIlia K bool value; 49447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 495055ad9beSIlia K if (value) 496055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 497055ad9beSIlia K else 498055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 499055ad9beSIlia K 500055ad9beSIlia K if (!success) 501b9c1b51eSKate Stone error.SetErrorStringWithFormat( 502b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 503fe11483bSZachary Turner option_arg.str().c_str()); 504055ad9beSIlia K break; 505055ad9beSIlia K } 506055ad9beSIlia K 507ca36cd16SJim Ingham case 'M': 508ca36cd16SJim Ingham m_func_names.push_back(option_arg); 509ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 510ca36cd16SJim Ingham break; 511ca36cd16SJim Ingham 512ca36cd16SJim Ingham case 'n': 513ca36cd16SJim Ingham m_func_names.push_back(option_arg); 514ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 515ca36cd16SJim Ingham break; 516ca36cd16SJim Ingham 5176fa7681bSZachary Turner case 'N': { 518fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 5195e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 520ff9a91eaSJim Ingham else 521ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 522fe11483bSZachary Turner option_arg.str().c_str()); 5235e09c8c3SJim Ingham break; 5246fa7681bSZachary Turner } 5255e09c8c3SJim Ingham 526b9c1b51eSKate Stone case 'R': { 5272411167fSJim Ingham lldb::addr_t tmp_offset_addr; 52847cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 52947cbf4a0SPavel Labath option_arg, 0, &error); 5302411167fSJim Ingham if (error.Success()) 5312411167fSJim Ingham m_offset_addr = tmp_offset_addr; 532b9c1b51eSKate Stone } break; 5332411167fSJim Ingham 534a72b31c7SJim Ingham case 'O': 535fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 536fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 537a72b31c7SJim Ingham break; 538a72b31c7SJim Ingham 539ca36cd16SJim Ingham case 'p': 540ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 541ca36cd16SJim Ingham break; 542ca36cd16SJim Ingham 5433815e702SJim Ingham case 'P': 5443815e702SJim Ingham m_python_class.assign(option_arg); 5453815e702SJim Ingham break; 5463815e702SJim Ingham 547ca36cd16SJim Ingham case 'r': 548ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 549ca36cd16SJim Ingham break; 550ca36cd16SJim Ingham 551ca36cd16SJim Ingham case 's': 5528f3be7a3SJonas Devlieghere m_modules.AppendIfUnique(FileSpec(option_arg)); 553ca36cd16SJim Ingham break; 554ca36cd16SJim Ingham 555ca36cd16SJim Ingham case 'S': 556ca36cd16SJim Ingham m_func_names.push_back(option_arg); 557ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 558ca36cd16SJim Ingham break; 559ca36cd16SJim Ingham 5603815e702SJim Ingham case 'v': { 5613815e702SJim Ingham if (!m_current_key.empty()) { 5623815e702SJim Ingham m_extra_args_sp->AddStringItem(m_current_key, option_arg); 5633815e702SJim Ingham m_current_key.clear(); 5643815e702SJim Ingham } 5653815e702SJim Ingham else 5663815e702SJim Ingham error.SetErrorStringWithFormat("Value \"%s\" missing matching key.", 5673815e702SJim Ingham option_arg.str().c_str()); 5683815e702SJim Ingham } break; 5693815e702SJim Ingham 570b9c1b51eSKate Stone case 'w': { 571ca36cd16SJim Ingham bool success; 57247cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 573ca36cd16SJim Ingham if (!success) 574b9c1b51eSKate Stone error.SetErrorStringWithFormat( 575fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 576fe11483bSZachary Turner option_arg.str().c_str()); 577b9c1b51eSKate Stone } break; 578ca36cd16SJim Ingham 57976bb8d67SJim Ingham case 'X': 58076bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 58176bb8d67SJim Ingham break; 58276bb8d67SJim Ingham 58330fdc8d8SChris Lattner default: 584b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 585b9c1b51eSKate Stone short_option); 58630fdc8d8SChris Lattner break; 58730fdc8d8SChris Lattner } 58830fdc8d8SChris Lattner 58930fdc8d8SChris Lattner return error; 59030fdc8d8SChris Lattner } 5919e85e5a8SEugene Zelenko 592b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 59387df91b8SJim Ingham m_filenames.Clear(); 59430fdc8d8SChris Lattner m_line_num = 0; 59530fdc8d8SChris Lattner m_column = 0; 596fab10e89SJim Ingham m_func_names.clear(); 5971f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 59830fdc8d8SChris Lattner m_func_regexp.clear(); 5991f746071SGreg Clayton m_source_text_regexp.clear(); 60087df91b8SJim Ingham m_modules.Clear(); 6011f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 6022411167fSJim Ingham m_offset_addr = 0; 603fab10e89SJim Ingham m_catch_bp = false; 604fab10e89SJim Ingham m_throw_bp = true; 605eb023e75SGreg Clayton m_hardware = false; 606a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 60723b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 608a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 6095e09c8c3SJim Ingham m_breakpoint_names.clear(); 610e732052fSJim Ingham m_all_files = false; 611a72b31c7SJim Ingham m_exception_extra_args.Clear(); 612055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 61376bb8d67SJim Ingham m_source_regex_func_names.clear(); 6143815e702SJim Ingham m_python_class.clear(); 615796ac80bSJonas Devlieghere m_extra_args_sp = std::make_shared<StructuredData::Dictionary>(); 6163815e702SJim Ingham m_current_key.clear(); 61730fdc8d8SChris Lattner } 61830fdc8d8SChris Lattner 6191f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 62070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 6211f0f5b5bSZachary Turner } 62230fdc8d8SChris Lattner 6235a988416SJim Ingham // Instance variables to hold the values for command options. 624969795f1SJim Ingham 6255a988416SJim Ingham std::string m_condition; 6265a988416SJim Ingham FileSpecList m_filenames; 6275a988416SJim Ingham uint32_t m_line_num; 6285a988416SJim Ingham uint32_t m_column; 6295a988416SJim Ingham std::vector<std::string> m_func_names; 6305e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 631117b1fa1SZachary Turner lldb::FunctionNameType m_func_name_type_mask; 6325a988416SJim Ingham std::string m_func_regexp; 6335a988416SJim Ingham std::string m_source_text_regexp; 6345a988416SJim Ingham FileSpecList m_modules; 6355a988416SJim Ingham lldb::addr_t m_load_addr; 6362411167fSJim Ingham lldb::addr_t m_offset_addr; 6375a988416SJim Ingham bool m_catch_bp; 6385a988416SJim Ingham bool m_throw_bp; 639eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 640a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 64123b1decbSDawn Perchik lldb::LanguageType m_language; 6425a988416SJim Ingham LazyBool m_skip_prologue; 643e732052fSJim Ingham bool m_all_files; 644a72b31c7SJim Ingham Args m_exception_extra_args; 645055ad9beSIlia K LazyBool m_move_to_nearest_code; 64676bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 6473815e702SJim Ingham std::string m_python_class; 6483815e702SJim Ingham StructuredData::DictionarySP m_extra_args_sp; 6493815e702SJim Ingham std::string m_current_key; 6505a988416SJim Ingham }; 6515a988416SJim Ingham 6525a988416SJim Ingham protected: 653b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 654b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 65533df7cd3SJim Ingham 656b9c1b51eSKate Stone if (target == nullptr) { 657b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 658b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 65930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 66030fdc8d8SChris Lattner return false; 66130fdc8d8SChris Lattner } 66230fdc8d8SChris Lattner 66330fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 66430fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 66530fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 66630fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 667b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 668b9c1b51eSKate Stone // expression) 669b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 670b9c1b51eSKate Stone // to source text) 671b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 672b9c1b51eSKate Stone // given language.) 67330fdc8d8SChris Lattner 67430fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 67530fdc8d8SChris Lattner 6763815e702SJim Ingham if (!m_options.m_python_class.empty()) 6773815e702SJim Ingham break_type = eSetTypeScripted; 6783815e702SJim Ingham else if (m_options.m_line_num != 0) 67930fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 68030fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 68130fdc8d8SChris Lattner break_type = eSetTypeAddress; 682fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 68330fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 68430fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 68530fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 686969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 687969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 688a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 689fab10e89SJim Ingham break_type = eSetTypeException; 69030fdc8d8SChris Lattner 691b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 692274060b6SGreg Clayton FileSpec module_spec; 693a8558b62SJim Ingham const bool internal = false; 694a8558b62SJim Ingham 695b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 696b9c1b51eSKate Stone // that off. 697b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 698b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 6992411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 7002411167fSJim Ingham 701b9c1b51eSKate Stone switch (break_type) { 70230fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 70330fdc8d8SChris Lattner { 70430fdc8d8SChris Lattner FileSpec file; 705c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 706b9c1b51eSKate Stone if (num_files == 0) { 707b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 70887df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 70987df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 71087df91b8SJim Ingham return false; 71187df91b8SJim Ingham } 712b9c1b51eSKate Stone } else if (num_files > 1) { 713b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 714b9c1b51eSKate Stone "line breakpoints."); 71587df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 71687df91b8SJim Ingham return false; 717b9c1b51eSKate Stone } else 71887df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 71930fdc8d8SChris Lattner 7201f746071SGreg Clayton // Only check for inline functions if 7211f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 7221f746071SGreg Clayton 723b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 724b842f2ecSJim Ingham file, 725b842f2ecSJim Ingham m_options.m_line_num, 726431b1584SAdrian Prantl m_options.m_column, 727b842f2ecSJim Ingham m_options.m_offset_addr, 728b842f2ecSJim Ingham check_inlines, 729b842f2ecSJim Ingham m_options.m_skip_prologue, 730b842f2ecSJim Ingham internal, 731b842f2ecSJim Ingham m_options.m_hardware, 732b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 733b9c1b51eSKate Stone } break; 7346eee5aa0SGreg Clayton 73530fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 736055a08a4SJim Ingham { 737b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 738b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 739b842f2ecSJim Ingham // will track the load location of the library. 740055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 741b9c1b51eSKate Stone if (num_modules_specified == 1) { 742b9c1b51eSKate Stone const FileSpec *file_spec = 743b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 744b842f2ecSJim Ingham bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 745b9c1b51eSKate Stone internal, file_spec, 746b842f2ecSJim Ingham m_options.m_hardware); 747b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 748b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, 749b842f2ecSJim Ingham m_options.m_hardware); 750b9c1b51eSKate Stone } else { 751b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 752b9c1b51eSKate Stone "address breakpoints."); 753055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 754055a08a4SJim Ingham return false; 755055a08a4SJim Ingham } 75630fdc8d8SChris Lattner break; 757055a08a4SJim Ingham } 75830fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 7590c5cd90dSGreg Clayton { 760117b1fa1SZachary Turner FunctionNameType name_type_mask = m_options.m_func_name_type_mask; 7610c5cd90dSGreg Clayton 7620c5cd90dSGreg Clayton if (name_type_mask == 0) 763e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 7640c5cd90dSGreg Clayton 765b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 766b842f2ecSJim Ingham &(m_options.m_filenames), 767b842f2ecSJim Ingham m_options.m_func_names, 768b842f2ecSJim Ingham name_type_mask, 769b842f2ecSJim Ingham m_options.m_language, 770b842f2ecSJim Ingham m_options.m_offset_addr, 771b842f2ecSJim Ingham m_options.m_skip_prologue, 772b842f2ecSJim Ingham internal, 773b842f2ecSJim Ingham m_options.m_hardware); 774b9c1b51eSKate Stone } break; 7750c5cd90dSGreg Clayton 776b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 777b9c1b51eSKate Stone // name 77830fdc8d8SChris Lattner { 77995eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 780b9c1b51eSKate Stone if (!regexp.IsValid()) { 781969795f1SJim Ingham char err_str[1024]; 782969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 783b9c1b51eSKate Stone result.AppendErrorWithFormat( 784b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 785969795f1SJim Ingham err_str); 78630fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 787969795f1SJim Ingham return false; 78830fdc8d8SChris Lattner } 78987df91b8SJim Ingham 790b842f2ecSJim Ingham bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), 791b842f2ecSJim Ingham &(m_options.m_filenames), 792b842f2ecSJim Ingham regexp, 793b842f2ecSJim Ingham m_options.m_language, 794b842f2ecSJim Ingham m_options.m_skip_prologue, 795b842f2ecSJim Ingham internal, 796b842f2ecSJim Ingham m_options.m_hardware); 797e14dc268SJim Ingham } 798e14dc268SJim Ingham break; 799969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 800969795f1SJim Ingham { 801c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 80287df91b8SJim Ingham 803b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 804969795f1SJim Ingham FileSpec file; 805b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 806b9c1b51eSKate Stone result.AppendError( 807b9c1b51eSKate Stone "No files provided and could not find default file."); 80887df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 80987df91b8SJim Ingham return false; 810b9c1b51eSKate Stone } else { 81187df91b8SJim Ingham m_options.m_filenames.Append(file); 81287df91b8SJim Ingham } 81387df91b8SJim Ingham } 8140c5cd90dSGreg Clayton 81595eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 816b9c1b51eSKate Stone if (!regexp.IsValid()) { 817969795f1SJim Ingham char err_str[1024]; 818969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 819b9c1b51eSKate Stone result.AppendErrorWithFormat( 820b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 821969795f1SJim Ingham err_str); 822969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 823969795f1SJim Ingham return false; 824969795f1SJim Ingham } 825b842f2ecSJim Ingham bp_sp = 826b842f2ecSJim Ingham target->CreateSourceRegexBreakpoint(&(m_options.m_modules), 827b842f2ecSJim Ingham &(m_options.m_filenames), 828b842f2ecSJim Ingham m_options 829b842f2ecSJim Ingham .m_source_regex_func_names, 830b842f2ecSJim Ingham regexp, 831b842f2ecSJim Ingham internal, 832b842f2ecSJim Ingham m_options.m_hardware, 833b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 834b9c1b51eSKate Stone } break; 835b9c1b51eSKate Stone case eSetTypeException: { 83697206d57SZachary Turner Status precond_error; 837b842f2ecSJim Ingham bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, 838b842f2ecSJim Ingham m_options.m_catch_bp, 839b842f2ecSJim Ingham m_options.m_throw_bp, 840b842f2ecSJim Ingham internal, 841b842f2ecSJim Ingham &m_options 842b842f2ecSJim Ingham .m_exception_extra_args, 843b842f2ecSJim Ingham &precond_error); 844b9c1b51eSKate Stone if (precond_error.Fail()) { 845b9c1b51eSKate Stone result.AppendErrorWithFormat( 846b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 847a72b31c7SJim Ingham precond_error.AsCString()); 848b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 849a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 850a72b31c7SJim Ingham return false; 851a72b31c7SJim Ingham } 852b9c1b51eSKate Stone } break; 8533815e702SJim Ingham case eSetTypeScripted: { 8543815e702SJim Ingham 8553815e702SJim Ingham Status error; 8563815e702SJim Ingham bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, 8573815e702SJim Ingham &(m_options.m_modules), 8583815e702SJim Ingham &(m_options.m_filenames), 8593815e702SJim Ingham false, 8603815e702SJim Ingham m_options.m_hardware, 8613815e702SJim Ingham m_options.m_extra_args_sp, 8623815e702SJim Ingham &error); 8633815e702SJim Ingham if (error.Fail()) { 8643815e702SJim Ingham result.AppendErrorWithFormat( 8653815e702SJim Ingham "Error setting extra exception arguments: %s", 8663815e702SJim Ingham error.AsCString()); 8673815e702SJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 8683815e702SJim Ingham result.SetStatus(eReturnStatusFailed); 8693815e702SJim Ingham return false; 8703815e702SJim Ingham } 8713815e702SJim Ingham } break; 87230fdc8d8SChris Lattner default: 87330fdc8d8SChris Lattner break; 87430fdc8d8SChris Lattner } 87530fdc8d8SChris Lattner 8761b54c88cSJim Ingham // Now set the various options that were passed in: 877b842f2ecSJim Ingham if (bp_sp) { 878b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 879ca36cd16SJim Ingham 880b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 88197206d57SZachary Turner Status name_error; 882ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 883b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 884ff9a91eaSJim Ingham if (name_error.Fail()) { 885ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 886ff9a91eaSJim Ingham name.c_str()); 887b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 888ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 889ff9a91eaSJim Ingham return false; 890ff9a91eaSJim Ingham } 891ff9a91eaSJim Ingham } 8925e09c8c3SJim Ingham } 8931b54c88cSJim Ingham } 8941b54c88cSJim Ingham 895b842f2ecSJim Ingham if (bp_sp) { 89685e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 8971391cc7dSJim Ingham const bool show_locations = false; 898b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 899b9c1b51eSKate Stone show_locations); 90057179860SJonas Devlieghere if (target == GetDebugger().GetDummyTarget()) 901b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 902b9c1b51eSKate Stone "into future targets.\n"); 903b9c1b51eSKate Stone else { 90405097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 90505097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 90605097246SAdrian Prantl // set the breakpoint till we run. 907b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 908b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 909b9c1b51eSKate Stone "actual locations.\n"); 9104aeb1989SJim Ingham } 9114aeb1989SJim Ingham } 91230fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 913b842f2ecSJim Ingham } else if (!bp_sp) { 91430fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 91530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 91630fdc8d8SChris Lattner } 91730fdc8d8SChris Lattner 91830fdc8d8SChris Lattner return result.Succeeded(); 91930fdc8d8SChris Lattner } 92030fdc8d8SChris Lattner 9215a988416SJim Ingham private: 922b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 923b9c1b51eSKate Stone CommandReturnObject &result) { 9245a988416SJim Ingham uint32_t default_line; 92505097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 92605097246SAdrian Prantl // frame's file. 927b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 928b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 929b9c1b51eSKate Stone if (cur_frame == nullptr) { 930b9c1b51eSKate Stone result.AppendError( 931b9c1b51eSKate Stone "No selected frame to use to find the default file."); 9325a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9335a988416SJim Ingham return false; 934b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 935b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 936b9c1b51eSKate Stone "file, it has no debug info."); 9375a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9385a988416SJim Ingham return false; 939b9c1b51eSKate Stone } else { 940b9c1b51eSKate Stone const SymbolContext &sc = 941b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 942b9c1b51eSKate Stone if (sc.line_entry.file) { 9435a988416SJim Ingham file = sc.line_entry.file; 944b9c1b51eSKate Stone } else { 945b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 946b9c1b51eSKate Stone "use as the default file."); 9475a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9485a988416SJim Ingham return false; 9495a988416SJim Ingham } 9505a988416SJim Ingham } 9515a988416SJim Ingham } 9525a988416SJim Ingham return true; 9535a988416SJim Ingham } 9545a988416SJim Ingham 955b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 956b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 9575a988416SJim Ingham CommandOptions m_options; 958b842f2ecSJim Ingham OptionGroupOptions m_all_options; 9595a988416SJim Ingham }; 9609e85e5a8SEugene Zelenko 9615a988416SJim Ingham // CommandObjectBreakpointModify 9625a988416SJim Ingham #pragma mark Modify 9635a988416SJim Ingham 964b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 9655a988416SJim Ingham public: 966b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 967b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 968b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 969b9c1b51eSKate Stone "breakpoints in the executable. " 970b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 971b9c1b51eSKate Stone "created breakpoint. " 972b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 973b9c1b51eSKate Stone "empty argument clears the modification.", 9749e85e5a8SEugene Zelenko nullptr), 975b9c1b51eSKate Stone m_options() { 9765a988416SJim Ingham CommandArgumentEntry arg; 977b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 978b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 979b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 980b9c1b51eSKate Stone // arguments vector. 9815a988416SJim Ingham m_arguments.push_back(arg); 982b842f2ecSJim Ingham 983b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 984b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 985b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 986b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 987b842f2ecSJim Ingham m_options.Finalize(); 9885a988416SJim Ingham } 9895a988416SJim Ingham 9909e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 9915a988416SJim Ingham 992b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 9935a988416SJim Ingham 9945a988416SJim Ingham protected: 995b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 996b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 997b9c1b51eSKate Stone if (target == nullptr) { 9985a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9995a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10005a988416SJim Ingham return false; 10015a988416SJim Ingham } 10025a988416SJim Ingham 1003bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1004bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10055a988416SJim Ingham 10065a988416SJim Ingham BreakpointIDList valid_bp_ids; 10075a988416SJim Ingham 1008b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1009b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1010b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10115a988416SJim Ingham 1012b9c1b51eSKate Stone if (result.Succeeded()) { 10135a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1014b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10155a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10165a988416SJim Ingham 1017b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1018b9c1b51eSKate Stone Breakpoint *bp = 1019b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1020b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1021b9c1b51eSKate Stone BreakpointLocation *location = 1022b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1023b842f2ecSJim Ingham if (location) 1024b842f2ecSJim Ingham location->GetLocationOptions() 1025b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 1026b9c1b51eSKate Stone } else { 1027b842f2ecSJim Ingham bp->GetOptions() 1028b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 10295a988416SJim Ingham } 10305a988416SJim Ingham } 10315a988416SJim Ingham } 10325a988416SJim Ingham } 10335a988416SJim Ingham 10345a988416SJim Ingham return result.Succeeded(); 10355a988416SJim Ingham } 10365a988416SJim Ingham 10375a988416SJim Ingham private: 1038b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1039b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 1040b842f2ecSJim Ingham OptionGroupOptions m_options; 10415a988416SJim Ingham }; 10425a988416SJim Ingham 10435a988416SJim Ingham // CommandObjectBreakpointEnable 10445a988416SJim Ingham #pragma mark Enable 10455a988416SJim Ingham 1046b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10475a988416SJim Ingham public: 1048b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1049b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1050b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1051b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1052b9c1b51eSKate Stone nullptr) { 10535a988416SJim Ingham CommandArgumentEntry arg; 1054b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1055b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1056b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1057b9c1b51eSKate Stone // arguments vector. 10585a988416SJim Ingham m_arguments.push_back(arg); 10595a988416SJim Ingham } 10605a988416SJim Ingham 10619e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10625a988416SJim Ingham 10635a988416SJim Ingham protected: 1064b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1065893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1066b9c1b51eSKate Stone if (target == nullptr) { 10675a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10685a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10695a988416SJim Ingham return false; 10705a988416SJim Ingham } 10715a988416SJim Ingham 1072bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1073bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10745a988416SJim Ingham 10755a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 10765a988416SJim Ingham 10775a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10785a988416SJim Ingham 1079b9c1b51eSKate Stone if (num_breakpoints == 0) { 10805a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 10815a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10825a988416SJim Ingham return false; 10835a988416SJim Ingham } 10845a988416SJim Ingham 108511eb9c64SZachary Turner if (command.empty()) { 10865a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 1087b842f2ecSJim Ingham target->EnableAllowedBreakpoints(); 1088b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1089b9c1b51eSKate Stone " breakpoints)\n", 1090b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10915a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1092b9c1b51eSKate Stone } else { 10935a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 10945a988416SJim Ingham BreakpointIDList valid_bp_ids; 1095b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1096b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1097b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10985a988416SJim Ingham 1099b9c1b51eSKate Stone if (result.Succeeded()) { 11005a988416SJim Ingham int enable_count = 0; 11015a988416SJim Ingham int loc_count = 0; 11025a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1103b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11045a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11055a988416SJim Ingham 1106b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1107b9c1b51eSKate Stone Breakpoint *breakpoint = 1108b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1109b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1110b9c1b51eSKate Stone BreakpointLocation *location = 1111b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1112b9c1b51eSKate Stone if (location) { 11135a988416SJim Ingham location->SetEnabled(true); 11145a988416SJim Ingham ++loc_count; 11155a988416SJim Ingham } 1116b9c1b51eSKate Stone } else { 11175a988416SJim Ingham breakpoint->SetEnabled(true); 11185a988416SJim Ingham ++enable_count; 11195a988416SJim Ingham } 11205a988416SJim Ingham } 11215a988416SJim Ingham } 1122b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1123b9c1b51eSKate Stone enable_count + loc_count); 11245a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11255a988416SJim Ingham } 11265a988416SJim Ingham } 11275a988416SJim Ingham 11285a988416SJim Ingham return result.Succeeded(); 11295a988416SJim Ingham } 11305a988416SJim Ingham }; 11315a988416SJim Ingham 11325a988416SJim Ingham // CommandObjectBreakpointDisable 11335a988416SJim Ingham #pragma mark Disable 11345a988416SJim Ingham 1135b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 11365a988416SJim Ingham public: 11377428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1138b9c1b51eSKate Stone : CommandObjectParsed( 1139b9c1b51eSKate Stone interpreter, "breakpoint disable", 1140b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 11417428a18cSKate Stone "them. If none are specified, disable all " 11427428a18cSKate Stone "breakpoints.", 1143b9c1b51eSKate Stone nullptr) { 1144b9c1b51eSKate Stone SetHelpLong( 1145b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11467428a18cSKate Stone If none are specified, disable all breakpoints." 11477428a18cSKate Stone R"( 1148ea671fbdSKate Stone 11497428a18cSKate Stone )" 11507428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11517428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11527428a18cSKate Stone R"( 1153ea671fbdSKate Stone 1154ea671fbdSKate Stone (lldb) break disable 1 1155ea671fbdSKate Stone (lldb) break enable 1.1 1156ea671fbdSKate Stone 1157ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1158ea671fbdSKate Stone 1159ea671fbdSKate Stone (lldb) break disable 1.* 1160ea671fbdSKate Stone (lldb) break enable 1.1 1161ea671fbdSKate Stone 11627428a18cSKate Stone )" 11637428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 11647428a18cSKate Stone the second re-enables the first location."); 1165b0fac509SJim Ingham 11665a988416SJim Ingham CommandArgumentEntry arg; 1167b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1168b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1169b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1170b9c1b51eSKate Stone // arguments vector. 11715a988416SJim Ingham m_arguments.push_back(arg); 11725a988416SJim Ingham } 11735a988416SJim Ingham 11749e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 11755a988416SJim Ingham 11765a988416SJim Ingham protected: 1177b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1178893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1179b9c1b51eSKate Stone if (target == nullptr) { 11805a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 11815a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11825a988416SJim Ingham return false; 11835a988416SJim Ingham } 11845a988416SJim Ingham 1185bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1186bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 11875a988416SJim Ingham 11885a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 11895a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11905a988416SJim Ingham 1191b9c1b51eSKate Stone if (num_breakpoints == 0) { 11925a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 11935a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11945a988416SJim Ingham return false; 11955a988416SJim Ingham } 11965a988416SJim Ingham 119711eb9c64SZachary Turner if (command.empty()) { 11985a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1199b842f2ecSJim Ingham target->DisableAllowedBreakpoints(); 1200b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1201b9c1b51eSKate Stone " breakpoints)\n", 1202b9c1b51eSKate Stone (uint64_t)num_breakpoints); 12035a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1204b9c1b51eSKate Stone } else { 12055a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 12065a988416SJim Ingham BreakpointIDList valid_bp_ids; 12075a988416SJim Ingham 1208b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1209b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1210b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 12115a988416SJim Ingham 1212b9c1b51eSKate Stone if (result.Succeeded()) { 12135a988416SJim Ingham int disable_count = 0; 12145a988416SJim Ingham int loc_count = 0; 12155a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1216b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 12175a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 12185a988416SJim Ingham 1219b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1220b9c1b51eSKate Stone Breakpoint *breakpoint = 1221b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1222b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1223b9c1b51eSKate Stone BreakpointLocation *location = 1224b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1225b9c1b51eSKate Stone if (location) { 12265a988416SJim Ingham location->SetEnabled(false); 12275a988416SJim Ingham ++loc_count; 12285a988416SJim Ingham } 1229b9c1b51eSKate Stone } else { 12305a988416SJim Ingham breakpoint->SetEnabled(false); 12315a988416SJim Ingham ++disable_count; 12325a988416SJim Ingham } 12335a988416SJim Ingham } 12345a988416SJim Ingham } 1235b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1236b9c1b51eSKate Stone disable_count + loc_count); 12375a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12385a988416SJim Ingham } 12395a988416SJim Ingham } 12405a988416SJim Ingham 12415a988416SJim Ingham return result.Succeeded(); 12425a988416SJim Ingham } 12435a988416SJim Ingham }; 12445a988416SJim Ingham 12455a988416SJim Ingham // CommandObjectBreakpointList 12461f0f5b5bSZachary Turner 12471f0f5b5bSZachary Turner #pragma mark List::CommandOptions 12488fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_list_options[] = { 12491f0f5b5bSZachary Turner // clang-format off 12508fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 12518fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, 12521f0f5b5bSZachary Turner // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 12531f0f5b5bSZachary Turner // But I need to see it for now, and don't want to wait. 12548fe53c49STatyana Krasnukha { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, 12558fe53c49STatyana Krasnukha { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 12568fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, 12571f0f5b5bSZachary Turner // clang-format on 12581f0f5b5bSZachary Turner }; 12591f0f5b5bSZachary Turner 12605a988416SJim Ingham #pragma mark List 12615a988416SJim Ingham 1262b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12635a988416SJim Ingham public: 1264b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1265b9c1b51eSKate Stone : CommandObjectParsed( 1266b9c1b51eSKate Stone interpreter, "breakpoint list", 12675a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 12689e85e5a8SEugene Zelenko nullptr), 1269b9c1b51eSKate Stone m_options() { 12705a988416SJim Ingham CommandArgumentEntry arg; 12715a988416SJim Ingham CommandArgumentData bp_id_arg; 12725a988416SJim Ingham 12735a988416SJim Ingham // Define the first (and only) variant of this arg. 12745a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 12755a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 12765a988416SJim Ingham 1277b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1278b9c1b51eSKate Stone // argument entry. 12795a988416SJim Ingham arg.push_back(bp_id_arg); 12805a988416SJim Ingham 12815a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12825a988416SJim Ingham m_arguments.push_back(arg); 12835a988416SJim Ingham } 12845a988416SJim Ingham 12859e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 12865a988416SJim Ingham 1287b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12885a988416SJim Ingham 1289b9c1b51eSKate Stone class CommandOptions : public Options { 12905a988416SJim Ingham public: 1291b9c1b51eSKate Stone CommandOptions() 1292b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 12935a988416SJim Ingham } 12945a988416SJim Ingham 12959e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12965a988416SJim Ingham 129797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1298b9c1b51eSKate Stone ExecutionContext *execution_context) override { 129997206d57SZachary Turner Status error; 13003bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13015a988416SJim Ingham 1302b9c1b51eSKate Stone switch (short_option) { 13035a988416SJim Ingham case 'b': 13045a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 13055a988416SJim Ingham break; 130633df7cd3SJim Ingham case 'D': 130733df7cd3SJim Ingham m_use_dummy = true; 130833df7cd3SJim Ingham break; 13095a988416SJim Ingham case 'f': 13105a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13115a988416SJim Ingham break; 13125a988416SJim Ingham case 'v': 13135a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 13145a988416SJim Ingham break; 13155a988416SJim Ingham case 'i': 13165a988416SJim Ingham m_internal = true; 13175a988416SJim Ingham break; 13185a988416SJim Ingham default: 1319b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1320b9c1b51eSKate Stone short_option); 13215a988416SJim Ingham break; 13225a988416SJim Ingham } 13235a988416SJim Ingham 13245a988416SJim Ingham return error; 13255a988416SJim Ingham } 13265a988416SJim Ingham 1327b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13285a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13295a988416SJim Ingham m_internal = false; 133033df7cd3SJim Ingham m_use_dummy = false; 13315a988416SJim Ingham } 13325a988416SJim Ingham 13331f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 133470602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 13351f0f5b5bSZachary Turner } 13365a988416SJim Ingham 13375a988416SJim Ingham // Instance variables to hold the values for command options. 13385a988416SJim Ingham 13395a988416SJim Ingham lldb::DescriptionLevel m_level; 13405a988416SJim Ingham 13415a988416SJim Ingham bool m_internal; 134233df7cd3SJim Ingham bool m_use_dummy; 13435a988416SJim Ingham }; 13445a988416SJim Ingham 13455a988416SJim Ingham protected: 1346b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 134733df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 134833df7cd3SJim Ingham 1349b9c1b51eSKate Stone if (target == nullptr) { 13505a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13525a988416SJim Ingham return true; 13535a988416SJim Ingham } 13545a988416SJim Ingham 1355b9c1b51eSKate Stone const BreakpointList &breakpoints = 1356b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1357bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1358bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13595a988416SJim Ingham 13605a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13615a988416SJim Ingham 1362b9c1b51eSKate Stone if (num_breakpoints == 0) { 13635a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13645a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13655a988416SJim Ingham return true; 13665a988416SJim Ingham } 13675a988416SJim Ingham 13685a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13695a988416SJim Ingham 137011eb9c64SZachary Turner if (command.empty()) { 13715a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 13725a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1373b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13745a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1375b842f2ecSJim Ingham if (breakpoint->AllowList()) 1376b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1377b842f2ecSJim Ingham m_options.m_level); 13785a988416SJim Ingham } 13795a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1380b9c1b51eSKate Stone } else { 13815a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 13825a988416SJim Ingham BreakpointIDList valid_bp_ids; 1383b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1384b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1385b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 13865a988416SJim Ingham 1387b9c1b51eSKate Stone if (result.Succeeded()) { 1388b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 13895a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1390b9c1b51eSKate Stone Breakpoint *breakpoint = 1391b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1392b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1393b9c1b51eSKate Stone m_options.m_level); 13945a988416SJim Ingham } 13955a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1396b9c1b51eSKate Stone } else { 13977428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 13985a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13995a988416SJim Ingham } 14005a988416SJim Ingham } 14015a988416SJim Ingham 14025a988416SJim Ingham return result.Succeeded(); 14035a988416SJim Ingham } 14045a988416SJim Ingham 14055a988416SJim Ingham private: 14065a988416SJim Ingham CommandOptions m_options; 14075a988416SJim Ingham }; 14085a988416SJim Ingham 14095a988416SJim Ingham // CommandObjectBreakpointClear 14101f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 14111f0f5b5bSZachary Turner 14128fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_clear_options[] = { 14131f0f5b5bSZachary Turner // clang-format off 14148fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, 14158fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } 14161f0f5b5bSZachary Turner // clang-format on 14171f0f5b5bSZachary Turner }; 14181f0f5b5bSZachary Turner 14195a988416SJim Ingham #pragma mark Clear 14205a988416SJim Ingham 1421b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 14225a988416SJim Ingham public: 1423*efe8e7e3SFangrui Song enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 14245a988416SJim Ingham 14257428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 14267428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1427b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1428b9c1b51eSKate Stone "specified source file and line.", 14295a988416SJim Ingham "breakpoint clear <cmd-options>"), 1430b9c1b51eSKate Stone m_options() {} 14315a988416SJim Ingham 14329e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 14335a988416SJim Ingham 1434b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14355a988416SJim Ingham 1436b9c1b51eSKate Stone class CommandOptions : public Options { 14375a988416SJim Ingham public: 1438b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 14395a988416SJim Ingham 14409e85e5a8SEugene Zelenko ~CommandOptions() override = default; 14415a988416SJim Ingham 144297206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1443b9c1b51eSKate Stone ExecutionContext *execution_context) override { 144497206d57SZachary Turner Status error; 14453bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14465a988416SJim Ingham 1447b9c1b51eSKate Stone switch (short_option) { 14485a988416SJim Ingham case 'f': 14495a988416SJim Ingham m_filename.assign(option_arg); 14505a988416SJim Ingham break; 14515a988416SJim Ingham 14525a988416SJim Ingham case 'l': 1453fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 14545a988416SJim Ingham break; 14555a988416SJim Ingham 14565a988416SJim Ingham default: 1457b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1458b9c1b51eSKate Stone short_option); 14595a988416SJim Ingham break; 14605a988416SJim Ingham } 14615a988416SJim Ingham 14625a988416SJim Ingham return error; 14635a988416SJim Ingham } 14645a988416SJim Ingham 1465b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14665a988416SJim Ingham m_filename.clear(); 14675a988416SJim Ingham m_line_num = 0; 14685a988416SJim Ingham } 14695a988416SJim Ingham 14701f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 147170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 14721f0f5b5bSZachary Turner } 14735a988416SJim Ingham 14745a988416SJim Ingham // Instance variables to hold the values for command options. 14755a988416SJim Ingham 14765a988416SJim Ingham std::string m_filename; 14775a988416SJim Ingham uint32_t m_line_num; 14785a988416SJim Ingham }; 14795a988416SJim Ingham 14805a988416SJim Ingham protected: 1481b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1482893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1483b9c1b51eSKate Stone if (target == nullptr) { 14845a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 14855a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14865a988416SJim Ingham return false; 14875a988416SJim Ingham } 14885a988416SJim Ingham 148905097246SAdrian Prantl // The following are the various types of breakpoints that could be 149005097246SAdrian Prantl // cleared: 14915a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 14925a988416SJim Ingham 14935a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 14945a988416SJim Ingham 14955a988416SJim Ingham if (m_options.m_line_num != 0) 14965a988416SJim Ingham break_type = eClearTypeFileAndLine; 14975a988416SJim Ingham 1498bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1499bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15005a988416SJim Ingham 15015a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 15025a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15035a988416SJim Ingham 15045a988416SJim Ingham // Early return if there's no breakpoint at all. 1505b9c1b51eSKate Stone if (num_breakpoints == 0) { 15065a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15075a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15085a988416SJim Ingham return result.Succeeded(); 15095a988416SJim Ingham } 15105a988416SJim Ingham 15115a988416SJim Ingham // Find matching breakpoints and delete them. 15125a988416SJim Ingham 15135a988416SJim Ingham // First create a copy of all the IDs. 15145a988416SJim Ingham std::vector<break_id_t> BreakIDs; 15155a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 15169e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 15175a988416SJim Ingham 15185a988416SJim Ingham int num_cleared = 0; 15195a988416SJim Ingham StreamString ss; 1520b9c1b51eSKate Stone switch (break_type) { 15215a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 15225a988416SJim Ingham { 15235a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 15245a988416SJim Ingham BreakpointLocationCollection loc_coll; 15255a988416SJim Ingham 1526b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 15275a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 15285a988416SJim Ingham 1529b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1530b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1531b9c1b51eSKate Stone // remove the breakpoint. 1532b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 15335a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 15345a988416SJim Ingham ss.EOL(); 15355a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15365a988416SJim Ingham ++num_cleared; 15375a988416SJim Ingham } 15385a988416SJim Ingham } 15395a988416SJim Ingham } 1540b9c1b51eSKate Stone } break; 15415a988416SJim Ingham 15425a988416SJim Ingham default: 15435a988416SJim Ingham break; 15445a988416SJim Ingham } 15455a988416SJim Ingham 1546b9c1b51eSKate Stone if (num_cleared > 0) { 15475a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15485a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1549c156427dSZachary Turner output_stream << ss.GetString(); 15505a988416SJim Ingham output_stream.EOL(); 15515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1552b9c1b51eSKate Stone } else { 15535a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15545a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15555a988416SJim Ingham } 15565a988416SJim Ingham 15575a988416SJim Ingham return result.Succeeded(); 15585a988416SJim Ingham } 15595a988416SJim Ingham 15605a988416SJim Ingham private: 15615a988416SJim Ingham CommandOptions m_options; 15625a988416SJim Ingham }; 15635a988416SJim Ingham 15645a988416SJim Ingham // CommandObjectBreakpointDelete 15658fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_delete_options[] = { 15661f0f5b5bSZachary Turner // clang-format off 15678fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, 15688fe53c49STatyana Krasnukha { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, 15691f0f5b5bSZachary Turner // clang-format on 15701f0f5b5bSZachary Turner }; 15711f0f5b5bSZachary Turner 15725a988416SJim Ingham #pragma mark Delete 15735a988416SJim Ingham 1574b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 15755a988416SJim Ingham public: 1576b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1577b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1578b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1579b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 15809e85e5a8SEugene Zelenko nullptr), 1581b9c1b51eSKate Stone m_options() { 15825a988416SJim Ingham CommandArgumentEntry arg; 1583b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1584b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1585b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1586b9c1b51eSKate Stone // arguments vector. 15875a988416SJim Ingham m_arguments.push_back(arg); 15885a988416SJim Ingham } 15895a988416SJim Ingham 15909e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 15915a988416SJim Ingham 1592b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 159333df7cd3SJim Ingham 1594b9c1b51eSKate Stone class CommandOptions : public Options { 159533df7cd3SJim Ingham public: 1596b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 159733df7cd3SJim Ingham 15989e85e5a8SEugene Zelenko ~CommandOptions() override = default; 159933df7cd3SJim Ingham 160097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1601b9c1b51eSKate Stone ExecutionContext *execution_context) override { 160297206d57SZachary Turner Status error; 160333df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 160433df7cd3SJim Ingham 1605b9c1b51eSKate Stone switch (short_option) { 160633df7cd3SJim Ingham case 'f': 160733df7cd3SJim Ingham m_force = true; 160833df7cd3SJim Ingham break; 160933df7cd3SJim Ingham 161033df7cd3SJim Ingham case 'D': 161133df7cd3SJim Ingham m_use_dummy = true; 161233df7cd3SJim Ingham break; 161333df7cd3SJim Ingham 161433df7cd3SJim Ingham default: 1615b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1616b9c1b51eSKate Stone short_option); 161733df7cd3SJim Ingham break; 161833df7cd3SJim Ingham } 161933df7cd3SJim Ingham 162033df7cd3SJim Ingham return error; 162133df7cd3SJim Ingham } 162233df7cd3SJim Ingham 1623b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 162433df7cd3SJim Ingham m_use_dummy = false; 162533df7cd3SJim Ingham m_force = false; 162633df7cd3SJim Ingham } 162733df7cd3SJim Ingham 16281f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 162970602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 16301f0f5b5bSZachary Turner } 163133df7cd3SJim Ingham 163233df7cd3SJim Ingham // Instance variables to hold the values for command options. 163333df7cd3SJim Ingham bool m_use_dummy; 163433df7cd3SJim Ingham bool m_force; 163533df7cd3SJim Ingham }; 163633df7cd3SJim Ingham 16375a988416SJim Ingham protected: 1638b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 163933df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 164033df7cd3SJim Ingham 1641b9c1b51eSKate Stone if (target == nullptr) { 16425a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16435a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16445a988416SJim Ingham return false; 16455a988416SJim Ingham } 16465a988416SJim Ingham 1647bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1648bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16495a988416SJim Ingham 16505a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16515a988416SJim Ingham 16525a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16535a988416SJim Ingham 1654b9c1b51eSKate Stone if (num_breakpoints == 0) { 16555a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 16565a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16575a988416SJim Ingham return false; 16585a988416SJim Ingham } 16595a988416SJim Ingham 166011eb9c64SZachary Turner if (command.empty()) { 1661b9c1b51eSKate Stone if (!m_options.m_force && 1662b9c1b51eSKate Stone !m_interpreter.Confirm( 1663b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1664b9c1b51eSKate Stone true)) { 16655a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1666b9c1b51eSKate Stone } else { 1667b842f2ecSJim Ingham target->RemoveAllowedBreakpoints(); 1668b9c1b51eSKate Stone result.AppendMessageWithFormat( 1669b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1670b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 16715a988416SJim Ingham } 16725a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1673b9c1b51eSKate Stone } else { 16745a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 16755a988416SJim Ingham BreakpointIDList valid_bp_ids; 1676b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1677b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1678b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 16795a988416SJim Ingham 1680b9c1b51eSKate Stone if (result.Succeeded()) { 16815a988416SJim Ingham int delete_count = 0; 16825a988416SJim Ingham int disable_count = 0; 16835a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1684b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 16855a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 16865a988416SJim Ingham 1687b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1688b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1689b9c1b51eSKate Stone Breakpoint *breakpoint = 1690b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1691b9c1b51eSKate Stone BreakpointLocation *location = 1692b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1693b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1694b9c1b51eSKate Stone // disable them instead. 1695b9c1b51eSKate Stone if (location) { 16965a988416SJim Ingham location->SetEnabled(false); 16975a988416SJim Ingham ++disable_count; 16985a988416SJim Ingham } 1699b9c1b51eSKate Stone } else { 17005a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 17015a988416SJim Ingham ++delete_count; 17025a988416SJim Ingham } 17035a988416SJim Ingham } 17045a988416SJim Ingham } 1705b9c1b51eSKate Stone result.AppendMessageWithFormat( 1706b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 17075a988416SJim Ingham delete_count, disable_count); 17085a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 17095a988416SJim Ingham } 17105a988416SJim Ingham } 17115a988416SJim Ingham return result.Succeeded(); 17125a988416SJim Ingham } 17139e85e5a8SEugene Zelenko 171433df7cd3SJim Ingham private: 171533df7cd3SJim Ingham CommandOptions m_options; 171633df7cd3SJim Ingham }; 171733df7cd3SJim Ingham 17185e09c8c3SJim Ingham // CommandObjectBreakpointName 17195e09c8c3SJim Ingham 17208fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_name_options[] = { 1721ac9c3a62SKate Stone // clang-format off 17228fe53c49STatyana Krasnukha {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 17238fe53c49STatyana Krasnukha {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 17248fe53c49STatyana Krasnukha {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 17258fe53c49STatyana Krasnukha {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."}, 1726ac9c3a62SKate Stone // clang-format on 17275e09c8c3SJim Ingham }; 1728b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 17295e09c8c3SJim Ingham public: 1730b9c1b51eSKate Stone BreakpointNameOptionGroup() 1731b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17325e09c8c3SJim Ingham } 17335e09c8c3SJim Ingham 17349e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17355e09c8c3SJim Ingham 17361f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 173770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 17385e09c8c3SJim Ingham } 17395e09c8c3SJim Ingham 174097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1741b9c1b51eSKate Stone ExecutionContext *execution_context) override { 174297206d57SZachary Turner Status error; 17435e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 17445e09c8c3SJim Ingham 1745b9c1b51eSKate Stone switch (short_option) { 17465e09c8c3SJim Ingham case 'N': 1747fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1748b9c1b51eSKate Stone error.Success()) 1749fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 17505e09c8c3SJim Ingham break; 17515e09c8c3SJim Ingham case 'B': 1752fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1753b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17548cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1755fe11483bSZachary Turner option_arg.str().c_str()); 17565e09c8c3SJim Ingham break; 17575e09c8c3SJim Ingham case 'D': 1758fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1759b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17608cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1761fe11483bSZachary Turner option_arg.str().c_str()); 17625e09c8c3SJim Ingham break; 1763e9632ebaSJim Ingham case 'H': 1764e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1765e9632ebaSJim Ingham break; 17665e09c8c3SJim Ingham 17675e09c8c3SJim Ingham default: 1768b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1769b9c1b51eSKate Stone short_option); 17705e09c8c3SJim Ingham break; 17715e09c8c3SJim Ingham } 17725e09c8c3SJim Ingham return error; 17735e09c8c3SJim Ingham } 17745e09c8c3SJim Ingham 1775b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 17765e09c8c3SJim Ingham m_name.Clear(); 17775e09c8c3SJim Ingham m_breakpoint.Clear(); 17785e09c8c3SJim Ingham m_use_dummy.Clear(); 17795e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1780e9632ebaSJim Ingham m_help_string.Clear(); 17815e09c8c3SJim Ingham } 17825e09c8c3SJim Ingham 17835e09c8c3SJim Ingham OptionValueString m_name; 17845e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 17855e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1786e9632ebaSJim Ingham OptionValueString m_help_string; 17875e09c8c3SJim Ingham }; 17885e09c8c3SJim Ingham 17898fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_access_options[] = { 1790b842f2ecSJim Ingham // clang-format off 17918fe53c49STatyana Krasnukha {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, 17928fe53c49STatyana Krasnukha {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, 17938fe53c49STatyana Krasnukha {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, 1794b842f2ecSJim Ingham // clang-format on 1795b842f2ecSJim Ingham }; 1796b842f2ecSJim Ingham 17978fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup { 1798b842f2ecSJim Ingham public: 17998fe53c49STatyana Krasnukha BreakpointAccessOptionGroup() : OptionGroup() {} 1800b842f2ecSJim Ingham 1801b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1802b842f2ecSJim Ingham 1803b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1804b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1805b842f2ecSJim Ingham } 1806b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1807b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1808b842f2ecSJim Ingham Status error; 1809b842f2ecSJim Ingham const int short_option 1810b842f2ecSJim Ingham = g_breakpoint_access_options[option_idx].short_option; 1811b842f2ecSJim Ingham 1812b842f2ecSJim Ingham switch (short_option) { 1813b842f2ecSJim Ingham case 'L': { 1814b842f2ecSJim Ingham bool value, success; 181547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1816b842f2ecSJim Ingham if (success) { 1817b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1818b842f2ecSJim Ingham } else 1819b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1820b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1821b842f2ecSJim Ingham option_arg.str().c_str()); 1822b842f2ecSJim Ingham } break; 1823b842f2ecSJim Ingham case 'A': { 1824b842f2ecSJim Ingham bool value, success; 182547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1826b842f2ecSJim Ingham if (success) { 1827b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1828b842f2ecSJim Ingham } else 1829b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1830b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1831b842f2ecSJim Ingham option_arg.str().c_str()); 1832b842f2ecSJim Ingham } break; 1833b842f2ecSJim Ingham case 'D': { 1834b842f2ecSJim Ingham bool value, success; 183547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1836b842f2ecSJim Ingham if (success) { 1837b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1838b842f2ecSJim Ingham } else 1839b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1840b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1841b842f2ecSJim Ingham option_arg.str().c_str()); 1842b842f2ecSJim Ingham } break; 1843b842f2ecSJim Ingham 1844b842f2ecSJim Ingham } 1845b842f2ecSJim Ingham 1846b842f2ecSJim Ingham return error; 1847b842f2ecSJim Ingham } 1848b842f2ecSJim Ingham 1849b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 1850b842f2ecSJim Ingham } 1851b842f2ecSJim Ingham 1852b842f2ecSJim Ingham const BreakpointName::Permissions &GetPermissions() const 1853b842f2ecSJim Ingham { 1854b842f2ecSJim Ingham return m_permissions; 1855b842f2ecSJim Ingham } 1856b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1857b842f2ecSJim Ingham }; 1858b842f2ecSJim Ingham 1859b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1860b842f2ecSJim Ingham public: 1861b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1862b842f2ecSJim Ingham : CommandObjectParsed( 1863b842f2ecSJim Ingham interpreter, "configure", "Configure the options for the breakpoint" 1864b842f2ecSJim Ingham " name provided. " 1865b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1866b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1867b842f2ecSJim Ingham "on the name.", 1868b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1869b842f2ecSJim Ingham "<breakpoint-name-list>"), 1870b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1871b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1872b842f2ecSJim Ingham // command. 1873b842f2ecSJim Ingham CommandArgumentEntry arg1; 1874b842f2ecSJim Ingham CommandArgumentData id_arg; 1875b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1876b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1877b842f2ecSJim Ingham arg1.push_back(id_arg); 1878b842f2ecSJim Ingham m_arguments.push_back(arg1); 1879b842f2ecSJim Ingham 1880b842f2ecSJim Ingham m_option_group.Append(&m_bp_opts, 1881b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1882b842f2ecSJim Ingham LLDB_OPT_SET_1); 1883b842f2ecSJim Ingham m_option_group.Append(&m_access_options, 1884b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1885b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1886e9632ebaSJim Ingham m_option_group.Append(&m_bp_id, 1887e9632ebaSJim Ingham LLDB_OPT_SET_2|LLDB_OPT_SET_4, 1888e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1889b842f2ecSJim Ingham m_option_group.Finalize(); 1890b842f2ecSJim Ingham } 1891b842f2ecSJim Ingham 1892b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1893b842f2ecSJim Ingham 1894b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1895b842f2ecSJim Ingham 1896b842f2ecSJim Ingham protected: 1897b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1898b842f2ecSJim Ingham 1899b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1900b842f2ecSJim Ingham if (argc == 0) { 1901b842f2ecSJim Ingham result.AppendError("No names provided."); 1902b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1903b842f2ecSJim Ingham return false; 1904b842f2ecSJim Ingham } 1905b842f2ecSJim Ingham 1906b842f2ecSJim Ingham Target *target = 1907b842f2ecSJim Ingham GetSelectedOrDummyTarget(false); 1908b842f2ecSJim Ingham 1909b842f2ecSJim Ingham if (target == nullptr) { 1910b842f2ecSJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 1911b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1912b842f2ecSJim Ingham return false; 1913b842f2ecSJim Ingham } 1914b842f2ecSJim Ingham 1915b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1916b842f2ecSJim Ingham target->GetBreakpointList().GetListMutex(lock); 1917b842f2ecSJim Ingham 1918b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1919b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1920b842f2ecSJim Ingham Status error; 1921b842f2ecSJim Ingham if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) 1922b842f2ecSJim Ingham { 1923b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1924b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1925b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1926b842f2ecSJim Ingham return false; 1927b842f2ecSJim Ingham } 1928b842f2ecSJim Ingham } 192905097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 193005097246SAdrian Prantl // check the error: 1931b842f2ecSJim Ingham BreakpointSP bp_sp; 1932b842f2ecSJim Ingham if (m_bp_id.m_breakpoint.OptionWasSet()) 1933b842f2ecSJim Ingham { 1934b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1935b842f2ecSJim Ingham bp_sp = target->GetBreakpointByID(bp_id); 1936b842f2ecSJim Ingham if (!bp_sp) 1937b842f2ecSJim Ingham { 1938b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1939b842f2ecSJim Ingham bp_id); 1940b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1941b842f2ecSJim Ingham return false; 1942b842f2ecSJim Ingham } 1943b842f2ecSJim Ingham } 1944b842f2ecSJim Ingham 1945b842f2ecSJim Ingham Status error; 1946b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1947b842f2ecSJim Ingham ConstString name(entry.c_str()); 1948b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(name, true, error); 1949b842f2ecSJim Ingham if (!bp_name) 1950b842f2ecSJim Ingham continue; 1951e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1952e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1953e9632ebaSJim Ingham 1954b842f2ecSJim Ingham if (bp_sp) 1955b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1956b842f2ecSJim Ingham *bp_sp->GetOptions(), 1957b842f2ecSJim Ingham m_access_options.GetPermissions()); 1958b842f2ecSJim Ingham else 1959b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1960b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1961b842f2ecSJim Ingham m_access_options.GetPermissions()); 1962b842f2ecSJim Ingham } 1963b842f2ecSJim Ingham return true; 1964b842f2ecSJim Ingham } 1965b842f2ecSJim Ingham 1966b842f2ecSJim Ingham private: 1967b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1968b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1969b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1970b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1971b842f2ecSJim Ingham }; 1972b842f2ecSJim Ingham 1973b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 19745e09c8c3SJim Ingham public: 1975b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1976b9c1b51eSKate Stone : CommandObjectParsed( 1977b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 19785e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1979b9c1b51eSKate Stone m_name_options(), m_option_group() { 1980b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1981b9c1b51eSKate Stone // command. 19825e09c8c3SJim Ingham CommandArgumentEntry arg1; 19835e09c8c3SJim Ingham CommandArgumentData id_arg; 19845e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19855e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19865e09c8c3SJim Ingham arg1.push_back(id_arg); 19875e09c8c3SJim Ingham m_arguments.push_back(arg1); 19885e09c8c3SJim Ingham 19895e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19905e09c8c3SJim Ingham m_option_group.Finalize(); 19915e09c8c3SJim Ingham } 19925e09c8c3SJim Ingham 19939e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 19945e09c8c3SJim Ingham 1995b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19965e09c8c3SJim Ingham 19975e09c8c3SJim Ingham protected: 1998b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1999b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 20005e09c8c3SJim Ingham result.SetError("No name option provided."); 20015e09c8c3SJim Ingham return false; 20025e09c8c3SJim Ingham } 20035e09c8c3SJim Ingham 2004b9c1b51eSKate Stone Target *target = 2005b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20065e09c8c3SJim Ingham 2007b9c1b51eSKate Stone if (target == nullptr) { 20085e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20095e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20105e09c8c3SJim Ingham return false; 20115e09c8c3SJim Ingham } 20125e09c8c3SJim Ingham 2013bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2014bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20155e09c8c3SJim Ingham 20165e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 20175e09c8c3SJim Ingham 20185e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 2019b9c1b51eSKate Stone if (num_breakpoints == 0) { 20205e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 20215e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20225e09c8c3SJim Ingham return false; 20235e09c8c3SJim Ingham } 20245e09c8c3SJim Ingham 20255e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 20265e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2027b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2028b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2029b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 20305e09c8c3SJim Ingham 2031b9c1b51eSKate Stone if (result.Succeeded()) { 2032b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 20335e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 20345e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20355e09c8c3SJim Ingham return false; 20365e09c8c3SJim Ingham } 20375e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2038b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 2039b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 2040b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 2041b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2042b9c1b51eSKate Stone lldb::break_id_t bp_id = 2043b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 20445e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2045b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, bp_name, error); 20465e09c8c3SJim Ingham } 20475e09c8c3SJim Ingham } 20485e09c8c3SJim Ingham 20495e09c8c3SJim Ingham return true; 20505e09c8c3SJim Ingham } 20515e09c8c3SJim Ingham 20525e09c8c3SJim Ingham private: 20535e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20545e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20555e09c8c3SJim Ingham }; 20565e09c8c3SJim Ingham 2057b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 20585e09c8c3SJim Ingham public: 2059b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 2060b9c1b51eSKate Stone : CommandObjectParsed( 2061b9c1b51eSKate Stone interpreter, "delete", 20625e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 20635e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 2064b9c1b51eSKate Stone m_name_options(), m_option_group() { 2065b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 2066b9c1b51eSKate Stone // command. 20675e09c8c3SJim Ingham CommandArgumentEntry arg1; 20685e09c8c3SJim Ingham CommandArgumentData id_arg; 20695e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 20705e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 20715e09c8c3SJim Ingham arg1.push_back(id_arg); 20725e09c8c3SJim Ingham m_arguments.push_back(arg1); 20735e09c8c3SJim Ingham 20745e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 20755e09c8c3SJim Ingham m_option_group.Finalize(); 20765e09c8c3SJim Ingham } 20775e09c8c3SJim Ingham 20789e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 20795e09c8c3SJim Ingham 2080b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20815e09c8c3SJim Ingham 20825e09c8c3SJim Ingham protected: 2083b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2084b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 20855e09c8c3SJim Ingham result.SetError("No name option provided."); 20865e09c8c3SJim Ingham return false; 20875e09c8c3SJim Ingham } 20885e09c8c3SJim Ingham 2089b9c1b51eSKate Stone Target *target = 2090b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20915e09c8c3SJim Ingham 2092b9c1b51eSKate Stone if (target == nullptr) { 20935e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20945e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20955e09c8c3SJim Ingham return false; 20965e09c8c3SJim Ingham } 20975e09c8c3SJim Ingham 2098bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2099bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 21005e09c8c3SJim Ingham 21015e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 21025e09c8c3SJim Ingham 21035e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 2104b9c1b51eSKate Stone if (num_breakpoints == 0) { 21055e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 21065e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21075e09c8c3SJim Ingham return false; 21085e09c8c3SJim Ingham } 21095e09c8c3SJim Ingham 21105e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 21115e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2112b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2113b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2114b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 21155e09c8c3SJim Ingham 2116b9c1b51eSKate Stone if (result.Succeeded()) { 2117b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 21185e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 21195e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21205e09c8c3SJim Ingham return false; 21215e09c8c3SJim Ingham } 2122b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 21235e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2124b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2125b9c1b51eSKate Stone lldb::break_id_t bp_id = 2126b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 21275e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2128b842f2ecSJim Ingham target->RemoveNameFromBreakpoint(bp_sp, bp_name); 21295e09c8c3SJim Ingham } 21305e09c8c3SJim Ingham } 21315e09c8c3SJim Ingham 21325e09c8c3SJim Ingham return true; 21335e09c8c3SJim Ingham } 21345e09c8c3SJim Ingham 21355e09c8c3SJim Ingham private: 21365e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 21375e09c8c3SJim Ingham OptionGroupOptions m_option_group; 21385e09c8c3SJim Ingham }; 21395e09c8c3SJim Ingham 2140b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 21415e09c8c3SJim Ingham public: 2142b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2143b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 2144b842f2ecSJim Ingham "List either the names for a breakpoint or info " 2145b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 2146b842f2ecSJim Ingham "names", 21475e09c8c3SJim Ingham "breakpoint name list <command-options>"), 2148b9c1b51eSKate Stone m_name_options(), m_option_group() { 2149b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 21505e09c8c3SJim Ingham m_option_group.Finalize(); 21515e09c8c3SJim Ingham } 21525e09c8c3SJim Ingham 21539e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 21545e09c8c3SJim Ingham 2155b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 21565e09c8c3SJim Ingham 21575e09c8c3SJim Ingham protected: 2158b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2159b9c1b51eSKate Stone Target *target = 2160b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 21615e09c8c3SJim Ingham 2162b9c1b51eSKate Stone if (target == nullptr) { 21635e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 21645e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21655e09c8c3SJim Ingham return false; 21665e09c8c3SJim Ingham } 21675e09c8c3SJim Ingham 2168b842f2ecSJim Ingham 2169b842f2ecSJim Ingham std::vector<std::string> name_list; 2170b842f2ecSJim Ingham if (command.empty()) { 2171b842f2ecSJim Ingham target->GetBreakpointNames(name_list); 2172b842f2ecSJim Ingham } else { 2173b842f2ecSJim Ingham for (const Args::ArgEntry &arg : command) 2174b842f2ecSJim Ingham { 2175b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 2176b842f2ecSJim Ingham } 2177b842f2ecSJim Ingham } 2178b842f2ecSJim Ingham 2179b842f2ecSJim Ingham if (name_list.empty()) { 2180b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 2181b842f2ecSJim Ingham } else { 2182b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 2183b842f2ecSJim Ingham const char *name = name_str.c_str(); 2184b842f2ecSJim Ingham // First print out the options for the name: 2185b842f2ecSJim Ingham Status error; 2186b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), 2187b842f2ecSJim Ingham false, 2188b842f2ecSJim Ingham error); 2189b842f2ecSJim Ingham if (bp_name) 2190b842f2ecSJim Ingham { 2191b842f2ecSJim Ingham StreamString s; 2192b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 2193b842f2ecSJim Ingham if (bp_name->GetDescription(&s, eDescriptionLevelFull)) 2194b842f2ecSJim Ingham { 2195b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 2196b842f2ecSJim Ingham } 2197b842f2ecSJim Ingham 2198bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2199bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 22005e09c8c3SJim Ingham 22015e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2202b842f2ecSJim Ingham bool any_set = false; 2203b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2204b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 22055e09c8c3SJim Ingham StreamString s; 2206b842f2ecSJim Ingham any_set = true; 22075e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 22085e09c8c3SJim Ingham s.EOL(); 2209c156427dSZachary Turner result.AppendMessage(s.GetString()); 22105e09c8c3SJim Ingham } 22115e09c8c3SJim Ingham } 2212b842f2ecSJim Ingham if (!any_set) 2213b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2214b9c1b51eSKate Stone } else { 2215b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 22165e09c8c3SJim Ingham } 2217b842f2ecSJim Ingham } 22185e09c8c3SJim Ingham } 22195e09c8c3SJim Ingham return true; 22205e09c8c3SJim Ingham } 22215e09c8c3SJim Ingham 22225e09c8c3SJim Ingham private: 22235e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 22245e09c8c3SJim Ingham OptionGroupOptions m_option_group; 22255e09c8c3SJim Ingham }; 22265e09c8c3SJim Ingham 2227e14dc268SJim Ingham // CommandObjectBreakpointName 2228b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 22295e09c8c3SJim Ingham public: 22307428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2231b9c1b51eSKate Stone : CommandObjectMultiword( 2232b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2233b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2234b9c1b51eSKate Stone CommandObjectSP add_command_object( 2235b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2236b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2237b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2238b9c1b51eSKate Stone CommandObjectSP list_command_object( 2239b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2240b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2241b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 22425e09c8c3SJim Ingham 22435e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 22445e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 22455e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2246b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 22475e09c8c3SJim Ingham } 22485e09c8c3SJim Ingham 22499e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 22505e09c8c3SJim Ingham }; 22515e09c8c3SJim Ingham 2252e14dc268SJim Ingham // CommandObjectBreakpointRead 22533acdf385SJim Ingham #pragma mark Read::CommandOptions 22548fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_read_options[] = { 22551f0f5b5bSZachary Turner // clang-format off 22568fe53c49STatyana Krasnukha {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 22578fe53c49STatyana Krasnukha {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, 22581f0f5b5bSZachary Turner // clang-format on 22591f0f5b5bSZachary Turner }; 22601f0f5b5bSZachary Turner 22611f0f5b5bSZachary Turner #pragma mark Read 2262e14dc268SJim Ingham 2263e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2264e14dc268SJim Ingham public: 2265e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2266e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2267e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2268e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2269e14dc268SJim Ingham nullptr), 2270e14dc268SJim Ingham m_options() { 2271e14dc268SJim Ingham CommandArgumentEntry arg; 2272e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2273e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2274e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2275e14dc268SJim Ingham // arguments vector. 2276e14dc268SJim Ingham m_arguments.push_back(arg); 2277e14dc268SJim Ingham } 2278e14dc268SJim Ingham 2279e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2280e14dc268SJim Ingham 2281e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2282e14dc268SJim Ingham 2283e14dc268SJim Ingham class CommandOptions : public Options { 2284e14dc268SJim Ingham public: 2285e14dc268SJim Ingham CommandOptions() : Options() {} 2286e14dc268SJim Ingham 2287e14dc268SJim Ingham ~CommandOptions() override = default; 2288e14dc268SJim Ingham 228997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2290e14dc268SJim Ingham ExecutionContext *execution_context) override { 229197206d57SZachary Turner Status error; 2292e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2293e14dc268SJim Ingham 2294e14dc268SJim Ingham switch (short_option) { 2295e14dc268SJim Ingham case 'f': 2296e14dc268SJim Ingham m_filename.assign(option_arg); 2297e14dc268SJim Ingham break; 22983acdf385SJim Ingham case 'N': { 229997206d57SZachary Turner Status name_error; 23003acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 23013acdf385SJim Ingham name_error)) { 23023acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 23033acdf385SJim Ingham name_error.AsCString()); 23043acdf385SJim Ingham } 23053acdf385SJim Ingham m_names.push_back(option_arg); 23063acdf385SJim Ingham break; 23073acdf385SJim Ingham } 2308e14dc268SJim Ingham default: 2309e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2310e14dc268SJim Ingham short_option); 2311e14dc268SJim Ingham break; 2312e14dc268SJim Ingham } 2313e14dc268SJim Ingham 2314e14dc268SJim Ingham return error; 2315e14dc268SJim Ingham } 2316e14dc268SJim Ingham 2317e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2318e14dc268SJim Ingham m_filename.clear(); 23193acdf385SJim Ingham m_names.clear(); 2320e14dc268SJim Ingham } 2321e14dc268SJim Ingham 23221f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 232370602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 23241f0f5b5bSZachary Turner } 2325e14dc268SJim Ingham 2326e14dc268SJim Ingham // Instance variables to hold the values for command options. 2327e14dc268SJim Ingham 2328e14dc268SJim Ingham std::string m_filename; 23293acdf385SJim Ingham std::vector<std::string> m_names; 2330e14dc268SJim Ingham }; 2331e14dc268SJim Ingham 2332e14dc268SJim Ingham protected: 2333e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2334e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2335e14dc268SJim Ingham if (target == nullptr) { 2336e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2337e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2338e14dc268SJim Ingham return false; 2339e14dc268SJim Ingham } 2340e14dc268SJim Ingham 23413acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 23423acdf385SJim Ingham target->GetBreakpointList().GetListMutex(lock); 23433acdf385SJim Ingham 23448f3be7a3SJonas Devlieghere FileSpec input_spec(m_options.m_filename); 23458f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(input_spec); 234601f16664SJim Ingham BreakpointIDList new_bps; 234797206d57SZachary Turner Status error = target->CreateBreakpointsFromFile( 234897206d57SZachary Turner input_spec, m_options.m_names, new_bps); 2349e14dc268SJim Ingham 2350e14dc268SJim Ingham if (!error.Success()) { 235101f16664SJim Ingham result.AppendError(error.AsCString()); 2352e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 235301f16664SJim Ingham return false; 2354e14dc268SJim Ingham } 23553acdf385SJim Ingham 23563acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 23573acdf385SJim Ingham 23583acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 23593acdf385SJim Ingham if (num_breakpoints == 0) { 23603acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 23613acdf385SJim Ingham } else { 23623acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 23633acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 23643acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 23653acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 23663acdf385SJim Ingham Breakpoint *bp = target->GetBreakpointList() 23673acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 23683acdf385SJim Ingham .get(); 23693acdf385SJim Ingham if (bp) 23703acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 23713acdf385SJim Ingham false); 23723acdf385SJim Ingham } 23733acdf385SJim Ingham } 2374e14dc268SJim Ingham return result.Succeeded(); 2375e14dc268SJim Ingham } 2376e14dc268SJim Ingham 2377e14dc268SJim Ingham private: 2378e14dc268SJim Ingham CommandOptions m_options; 2379e14dc268SJim Ingham }; 2380e14dc268SJim Ingham 2381e14dc268SJim Ingham // CommandObjectBreakpointWrite 23821f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 23838fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_write_options[] = { 23841f0f5b5bSZachary Turner // clang-format off 23858fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, 23868fe53c49STatyana Krasnukha { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, 23871f0f5b5bSZachary Turner // clang-format on 23881f0f5b5bSZachary Turner }; 23891f0f5b5bSZachary Turner 23901f0f5b5bSZachary Turner #pragma mark Write 2391e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2392e14dc268SJim Ingham public: 2393e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2394e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2395e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2396e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2397e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2398e14dc268SJim Ingham nullptr), 2399e14dc268SJim Ingham m_options() { 2400e14dc268SJim Ingham CommandArgumentEntry arg; 2401e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2402e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2403e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2404e14dc268SJim Ingham // arguments vector. 2405e14dc268SJim Ingham m_arguments.push_back(arg); 2406e14dc268SJim Ingham } 2407e14dc268SJim Ingham 2408e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2409e14dc268SJim Ingham 2410e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2411e14dc268SJim Ingham 2412e14dc268SJim Ingham class CommandOptions : public Options { 2413e14dc268SJim Ingham public: 2414e14dc268SJim Ingham CommandOptions() : Options() {} 2415e14dc268SJim Ingham 2416e14dc268SJim Ingham ~CommandOptions() override = default; 2417e14dc268SJim Ingham 241897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2419e14dc268SJim Ingham ExecutionContext *execution_context) override { 242097206d57SZachary Turner Status error; 2421e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2422e14dc268SJim Ingham 2423e14dc268SJim Ingham switch (short_option) { 2424e14dc268SJim Ingham case 'f': 2425e14dc268SJim Ingham m_filename.assign(option_arg); 2426e14dc268SJim Ingham break; 24272d3628e1SJim Ingham case 'a': 24282d3628e1SJim Ingham m_append = true; 24292d3628e1SJim Ingham break; 2430e14dc268SJim Ingham default: 2431e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2432e14dc268SJim Ingham short_option); 2433e14dc268SJim Ingham break; 2434e14dc268SJim Ingham } 2435e14dc268SJim Ingham 2436e14dc268SJim Ingham return error; 2437e14dc268SJim Ingham } 2438e14dc268SJim Ingham 2439e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2440e14dc268SJim Ingham m_filename.clear(); 24412d3628e1SJim Ingham m_append = false; 2442e14dc268SJim Ingham } 2443e14dc268SJim Ingham 24441f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 244570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 24461f0f5b5bSZachary Turner } 2447e14dc268SJim Ingham 2448e14dc268SJim Ingham // Instance variables to hold the values for command options. 2449e14dc268SJim Ingham 2450e14dc268SJim Ingham std::string m_filename; 24512d3628e1SJim Ingham bool m_append = false; 2452e14dc268SJim Ingham }; 2453e14dc268SJim Ingham 2454e14dc268SJim Ingham protected: 2455e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2456e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2457e14dc268SJim Ingham if (target == nullptr) { 2458e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2459e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2460e14dc268SJim Ingham return false; 2461e14dc268SJim Ingham } 2462e14dc268SJim Ingham 2463e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2464e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2465e14dc268SJim Ingham 2466e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 246711eb9c64SZachary Turner if (!command.empty()) { 2468e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2469b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2470b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2471e14dc268SJim Ingham 247201f16664SJim Ingham if (!result.Succeeded()) { 2473e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2474e14dc268SJim Ingham return false; 2475e14dc268SJim Ingham } 2476e14dc268SJim Ingham } 24778f3be7a3SJonas Devlieghere FileSpec file_spec(m_options.m_filename); 24788f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 24798f3be7a3SJonas Devlieghere Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids, 24808f3be7a3SJonas Devlieghere m_options.m_append); 248101f16664SJim Ingham if (!error.Success()) { 248201f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 248301f16664SJim Ingham error.AsCString()); 248401f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2485e14dc268SJim Ingham } 2486e14dc268SJim Ingham return result.Succeeded(); 2487e14dc268SJim Ingham } 2488e14dc268SJim Ingham 2489e14dc268SJim Ingham private: 2490e14dc268SJim Ingham CommandOptions m_options; 2491e14dc268SJim Ingham }; 2492e14dc268SJim Ingham 249330fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 2494ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 249530fdc8d8SChris Lattner 2496b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2497b9c1b51eSKate Stone CommandInterpreter &interpreter) 2498b9c1b51eSKate Stone : CommandObjectMultiword( 2499b9c1b51eSKate Stone interpreter, "breakpoint", 25007428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2501b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2502b9c1b51eSKate Stone CommandObjectSP list_command_object( 2503b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2504b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2505b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2506b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2507b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2508b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2509b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2510b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2511b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2512b9c1b51eSKate Stone CommandObjectSP set_command_object( 2513b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2514b9c1b51eSKate Stone CommandObjectSP command_command_object( 2515b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2516b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2517b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2518b9c1b51eSKate Stone CommandObjectSP name_command_object( 2519b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2520e14dc268SJim Ingham CommandObjectSP write_command_object( 2521e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2522e14dc268SJim Ingham CommandObjectSP read_command_object( 2523e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 252430fdc8d8SChris Lattner 2525b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 252630fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 252730fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2528b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2529b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2530ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2531b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2532b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 25335e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2534e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2535e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 253630fdc8d8SChris Lattner 253723f59509SGreg Clayton LoadSubCommand("list", list_command_object); 253823f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 253923f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 254023f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 254123f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 254223f59509SGreg Clayton LoadSubCommand("set", set_command_object); 254323f59509SGreg Clayton LoadSubCommand("command", command_command_object); 254423f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 25455e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2546e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2547e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 254830fdc8d8SChris Lattner } 254930fdc8d8SChris Lattner 25509e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 255130fdc8d8SChris Lattner 2552b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 25535e09c8c3SJim Ingham bool allow_locations, 25545e09c8c3SJim Ingham CommandReturnObject &result, 2555b842f2ecSJim Ingham BreakpointIDList *valid_ids, 2556b842f2ecSJim Ingham BreakpointName::Permissions 2557b842f2ecSJim Ingham ::PermissionKinds 2558b842f2ecSJim Ingham purpose) { 255930fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2560b9c1b51eSKate Stone // 2). the full breakpoint & location 2561b9c1b51eSKate Stone // canonical representation 2562b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2563b9c1b51eSKate Stone // representing a range (in which case there 2564b9c1b51eSKate Stone // had *better* be an entry both before & 2565b9c1b51eSKate Stone // after of one of the first two types. 25665e09c8c3SJim Ingham // 4). A breakpoint name 2567b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2568b9c1b51eSKate Stone // one.) 256930fdc8d8SChris Lattner 257030fdc8d8SChris Lattner Args temp_args; 257130fdc8d8SChris Lattner 257211eb9c64SZachary Turner if (args.empty()) { 2573b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2574b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2575b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 257636f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2577b9c1b51eSKate Stone } else { 2578b9c1b51eSKate Stone result.AppendError( 2579b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 258036f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 258136f3b369SJim Ingham } 258236f3b369SJim Ingham return; 258336f3b369SJim Ingham } 258436f3b369SJim Ingham 2585b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 258605097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 258705097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 258805097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 258905097246SAdrian Prantl // into TEMP_ARGS. 259030fdc8d8SChris Lattner 2591b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2592b842f2ecSJim Ingham purpose, result, temp_args); 259330fdc8d8SChris Lattner 2594b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2595b9c1b51eSKate Stone // BreakpointIDList: 259630fdc8d8SChris Lattner 259716662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 259830fdc8d8SChris Lattner 259905097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 260005097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 260130fdc8d8SChris Lattner 2602b9c1b51eSKate Stone if (result.Succeeded()) { 2603b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 260405097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 260505097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 260630fdc8d8SChris Lattner 2607c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2608b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 260930fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2610b9c1b51eSKate Stone Breakpoint *breakpoint = 2611b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2612b9c1b51eSKate Stone if (breakpoint != nullptr) { 2613c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2614b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 261530fdc8d8SChris Lattner StreamString id_str; 2616b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2617b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2618c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2619b9c1b51eSKate Stone result.AppendErrorWithFormat( 2620b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 262130fdc8d8SChris Lattner id_str.GetData()); 262230fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 262330fdc8d8SChris Lattner } 2624b9c1b51eSKate Stone } else { 2625c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2626b9c1b51eSKate Stone result.AppendErrorWithFormat( 2627b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 26287428a18cSKate Stone cur_bp_id.GetBreakpointID()); 262930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 263030fdc8d8SChris Lattner } 263130fdc8d8SChris Lattner } 263230fdc8d8SChris Lattner } 263330fdc8d8SChris Lattner } 2634