130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner // C Includes 1130fdc8d8SChris Lattner // C++ Includes 129e85e5a8SEugene Zelenko #include <vector> 139e85e5a8SEugene Zelenko 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 169e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h" 179e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h" 1830fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h" 1930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h" 2030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 213eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 22b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h" 23b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h" 24b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h" 2532abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 265e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 275e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 28b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 290e0984eeSJim Ingham #include "lldb/Target/Language.h" 30b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 31b9c1b51eSKate Stone #include "lldb/Target/Target.h" 321b54c88cSJim Ingham #include "lldb/Target/Thread.h" 331b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 34bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 35bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner using namespace lldb; 3830fdc8d8SChris Lattner using namespace lldb_private; 3930fdc8d8SChris Lattner 40b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 41b9c1b51eSKate Stone lldb::DescriptionLevel level) { 4230fdc8d8SChris Lattner s->IndentMore(); 4330fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4430fdc8d8SChris Lattner s->IndentLess(); 4530fdc8d8SChris Lattner s->EOL(); 4630fdc8d8SChris Lattner } 4730fdc8d8SChris Lattner 48b842f2ecSJim Ingham //------------------------------------------------------------------------- 49b842f2ecSJim Ingham // Modifiable Breakpoint Options 50b842f2ecSJim Ingham //------------------------------------------------------------------------- 51b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 52b842f2ecSJim Ingham static OptionDefinition g_breakpoint_modify_options[] = { 53b842f2ecSJim Ingham // clang-format off 54b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, 55b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, 56b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, 57b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, 58b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, 59b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, 60b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, 61b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, 62b842f2ecSJim Ingham { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, 63b842f2ecSJim Ingham { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, 64b842f2ecSJim Ingham { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, 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." }, 65b842f2ecSJim Ingham // clang-format on 66b842f2ecSJim Ingham }; 67b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup 68b842f2ecSJim Ingham { 69b842f2ecSJim Ingham public: 70b842f2ecSJim Ingham BreakpointOptionGroup() : 71b842f2ecSJim Ingham OptionGroup(), 72b842f2ecSJim Ingham m_bp_opts(false) {} 73b842f2ecSJim Ingham 74b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 75b842f2ecSJim Ingham 76b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 77b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 78b842f2ecSJim Ingham } 79b842f2ecSJim Ingham 80b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 81b842f2ecSJim Ingham ExecutionContext *execution_context) override { 82b842f2ecSJim Ingham Status error; 83b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 84b842f2ecSJim Ingham 85b842f2ecSJim Ingham switch (short_option) { 86b842f2ecSJim Ingham case 'c': 87b842f2ecSJim Ingham // Normally an empty breakpoint condition marks is as unset. 88b842f2ecSJim Ingham // But we need to say it was passed in. 89b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 90b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 91b842f2ecSJim Ingham break; 92b842f2ecSJim Ingham case 'C': 93b842f2ecSJim Ingham m_commands.push_back(option_arg); 94b842f2ecSJim Ingham break; 95b842f2ecSJim Ingham case 'd': 96b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 97b842f2ecSJim Ingham break; 98b842f2ecSJim Ingham case 'e': 99b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 100b842f2ecSJim Ingham break; 101b842f2ecSJim Ingham case 'G': { 102b842f2ecSJim Ingham bool value, success; 103b842f2ecSJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 104b842f2ecSJim Ingham if (success) { 105b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 106b842f2ecSJim Ingham } else 107b842f2ecSJim Ingham error.SetErrorStringWithFormat( 108b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 109b842f2ecSJim Ingham option_arg.str().c_str()); 110b842f2ecSJim Ingham } 111b842f2ecSJim Ingham break; 112b842f2ecSJim Ingham case 'i': 113b842f2ecSJim Ingham { 114b842f2ecSJim Ingham uint32_t ignore_count; 115b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 116b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 117b842f2ecSJim Ingham option_arg.str().c_str()); 118b842f2ecSJim Ingham else 119b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 120b842f2ecSJim Ingham } 121b842f2ecSJim Ingham break; 122b842f2ecSJim Ingham case 'o': { 123b842f2ecSJim Ingham bool value, success; 124b842f2ecSJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 125b842f2ecSJim Ingham if (success) { 126b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 127b842f2ecSJim Ingham } else 128b842f2ecSJim Ingham error.SetErrorStringWithFormat( 129b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 130b842f2ecSJim Ingham option_arg.str().c_str()); 131b842f2ecSJim Ingham } break; 132b842f2ecSJim Ingham case 't': 133b842f2ecSJim Ingham { 134b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 135b842f2ecSJim Ingham if (option_arg[0] != '\0') { 136b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 137b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 138b842f2ecSJim Ingham option_arg.str().c_str()); 139b842f2ecSJim Ingham } 140b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 141b842f2ecSJim Ingham } 142b842f2ecSJim Ingham break; 143b842f2ecSJim Ingham case 'T': 144b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 145b842f2ecSJim Ingham break; 146b842f2ecSJim Ingham case 'q': 147b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 148b842f2ecSJim Ingham break; 149b842f2ecSJim Ingham case 'x': 150b842f2ecSJim Ingham { 151b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 152b842f2ecSJim Ingham if (option_arg[0] != '\n') { 153b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 154b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 155b842f2ecSJim Ingham option_arg.str().c_str()); 156b842f2ecSJim Ingham } 157b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 158b842f2ecSJim Ingham } 159b842f2ecSJim Ingham break; 160b842f2ecSJim Ingham default: 161b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 162b842f2ecSJim Ingham short_option); 163b842f2ecSJim Ingham break; 164b842f2ecSJim Ingham } 165b842f2ecSJim Ingham 166b842f2ecSJim Ingham return error; 167b842f2ecSJim Ingham } 168b842f2ecSJim Ingham 169b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 170b842f2ecSJim Ingham m_bp_opts.Clear(); 171b842f2ecSJim Ingham m_commands.clear(); 172b842f2ecSJim Ingham } 173b842f2ecSJim Ingham 174b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 175b842f2ecSJim Ingham if (!m_commands.empty()) 176b842f2ecSJim Ingham { 177b842f2ecSJim Ingham if (!m_commands.empty()) 178b842f2ecSJim Ingham { 179b842f2ecSJim Ingham auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); 180b842f2ecSJim Ingham 181b842f2ecSJim Ingham for (std::string &str : m_commands) 182b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 183b842f2ecSJim Ingham 184b842f2ecSJim Ingham cmd_data->stop_on_error = true; 185b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 186b842f2ecSJim Ingham } 187b842f2ecSJim Ingham } 188b842f2ecSJim Ingham return Status(); 189b842f2ecSJim Ingham } 190b842f2ecSJim Ingham 191b842f2ecSJim Ingham const BreakpointOptions &GetBreakpointOptions() 192b842f2ecSJim Ingham { 193b842f2ecSJim Ingham return m_bp_opts; 194b842f2ecSJim Ingham } 195b842f2ecSJim Ingham 196b842f2ecSJim Ingham std::vector<std::string> m_commands; 197b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 198b842f2ecSJim Ingham 199b842f2ecSJim Ingham }; 200b842f2ecSJim Ingham static OptionDefinition g_breakpoint_dummy_options[] = { 201b842f2ecSJim Ingham // clang-format off 202b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " 203b842f2ecSJim Ingham "which prime new targets." }, 204b842f2ecSJim Ingham // clang-format on 205b842f2ecSJim Ingham }; 206b842f2ecSJim Ingham 207b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup 208b842f2ecSJim Ingham { 209b842f2ecSJim Ingham public: 210b842f2ecSJim Ingham BreakpointDummyOptionGroup() : 211b842f2ecSJim Ingham OptionGroup() {} 212b842f2ecSJim Ingham 213b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 214b842f2ecSJim Ingham 215b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 216b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 217b842f2ecSJim Ingham } 218b842f2ecSJim Ingham 219b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 220b842f2ecSJim Ingham ExecutionContext *execution_context) override { 221b842f2ecSJim Ingham Status error; 222b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 223b842f2ecSJim Ingham 224b842f2ecSJim Ingham switch (short_option) { 225b842f2ecSJim Ingham case 'D': 226b842f2ecSJim Ingham m_use_dummy = true; 227b842f2ecSJim Ingham break; 228b842f2ecSJim Ingham default: 229b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 230b842f2ecSJim Ingham short_option); 231b842f2ecSJim Ingham break; 232b842f2ecSJim Ingham } 233b842f2ecSJim Ingham 234b842f2ecSJim Ingham return error; 235b842f2ecSJim Ingham } 236b842f2ecSJim Ingham 237b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 238b842f2ecSJim Ingham m_use_dummy = false; 239b842f2ecSJim Ingham } 240b842f2ecSJim Ingham 241b842f2ecSJim Ingham bool m_use_dummy; 242b842f2ecSJim Ingham 243b842f2ecSJim Ingham }; 244b842f2ecSJim Ingham 2451f0f5b5bSZachary Turner // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 2461f0f5b5bSZachary Turner // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 2471f0f5b5bSZachary Turner #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2) 2481f0f5b5bSZachary Turner #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10) 2491f0f5b5bSZachary Turner #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 2501f0f5b5bSZachary Turner #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 2511f0f5b5bSZachary Turner #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 2521f0f5b5bSZachary Turner #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 2531f0f5b5bSZachary Turner 2541f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_set_options[] = { 2551f0f5b5bSZachary Turner // clang-format off 2561f0f5b5bSZachary Turner { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " 2571f0f5b5bSZachary Turner "multiple times to specify multiple shared libraries." }, 2581f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, 2591f0f5b5bSZachary Turner { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " 2601f0f5b5bSZachary Turner "lldb only looks for files that are #included if they use the standard include " 2611f0f5b5bSZachary Turner "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 2621f0f5b5bSZachary Turner "#included, set target.inline-breakpoint-strategy to \"always\"." }, 2631f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, 2641f0f5b5bSZachary Turner 2651f0f5b5bSZachary Turner // Comment out this option for the moment, as we don't actually use it, but will in the future. 2661f0f5b5bSZachary Turner // This way users won't see it, but the infrastructure is left in place. 2671f0f5b5bSZachary Turner // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 2681f0f5b5bSZachary Turner // "Set the breakpoint by source location at this particular column."}, 2691f0f5b5bSZachary Turner 2701f0f5b5bSZachary Turner { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " 2711f0f5b5bSZachary Turner "a particular binary, then the address will be converted to a \"file\" " 2721f0f5b5bSZachary Turner "address, so that the breakpoint will track that binary+offset no matter where " 2731f0f5b5bSZachary Turner "the binary eventually loads. Alternately, if you also specify the module - " 2741f0f5b5bSZachary Turner "with the -s option - then the address will be treated as a file address in " 2751f0f5b5bSZachary Turner "that module, and resolved accordingly. Again, this will allow lldb to track " 2761f0f5b5bSZachary Turner "that offset on subsequent reloads. The module need not have been loaded at " 2771f0f5b5bSZachary Turner "the time you specify this breakpoint, and will get resolved when the module " 2781f0f5b5bSZachary Turner "is loaded." }, 2791f0f5b5bSZachary Turner { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " 2801f0f5b5bSZachary Turner "one breakpoint for multiple names" }, 2811f0f5b5bSZachary Turner { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " 2821f0f5b5bSZachary Turner "functions. Can be repeated multiple times." }, 2831f0f5b5bSZachary Turner { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " 2841f0f5b5bSZachary Turner "namespaces and all arguments, and for Objective C this means a full function " 2851f0f5b5bSZachary Turner "prototype with class and selector. Can be repeated multiple times to make " 2861f0f5b5bSZachary Turner "one breakpoint for multiple names." }, 2871f0f5b5bSZachary Turner { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " 2881f0f5b5bSZachary Turner "make one breakpoint for multiple Selectors." }, 2891f0f5b5bSZachary Turner { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " 2901f0f5b5bSZachary Turner "make one breakpoint for multiple methods." }, 2911f0f5b5bSZachary Turner { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " 2921f0f5b5bSZachary Turner "the function name(s)." }, 2931f0f5b5bSZachary Turner { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " 2941f0f5b5bSZachary Turner "ignored). Can be repeated multiple times to make one breakpoint for multiple " 2951f0f5b5bSZachary Turner "symbols." }, 2961f0f5b5bSZachary Turner { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " 2971f0f5b5bSZachary Turner "against the source text in a source file or files specified with the -f " 2981f0f5b5bSZachary Turner "option. The -f option can be specified more than once. If no source files " 2991f0f5b5bSZachary Turner "are specified, uses the current \"default source file\". If you want to " 3001f0f5b5bSZachary Turner "match against all source files, pass the \"--all-files\" option." }, 3011f0f5b5bSZachary Turner { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." }, 3021f0f5b5bSZachary Turner { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " 3031f0f5b5bSZachary Turner "options, on throw but not catch.)" }, 3041f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, 3051f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, 3061f0f5b5bSZachary Turner 3071f0f5b5bSZachary Turner // Don't add this option till it actually does something useful... 3081f0f5b5bSZachary Turner // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 3091f0f5b5bSZachary 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" }, 3101f0f5b5bSZachary Turner 3111f0f5b5bSZachary Turner { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " 3121f0f5b5bSZachary Turner "(note: currently only implemented for setting breakpoints on identifiers). " 3131f0f5b5bSZachary Turner "If not set the target.language setting is used." }, 3141f0f5b5bSZachary Turner { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " 3151f0f5b5bSZachary Turner "If not set the target.skip-prologue setting is used." }, 3161f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, 3171f0f5b5bSZachary Turner { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " 3181f0f5b5bSZachary Turner "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, 3191f0f5b5bSZachary Turner { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " 3201f0f5b5bSZachary Turner "setting is used." }, 3211f0f5b5bSZachary Turner // clang-format on 3221f0f5b5bSZachary Turner }; 3231f0f5b5bSZachary Turner 32430fdc8d8SChris Lattner //------------------------------------------------------------------------- 3255a988416SJim Ingham // CommandObjectBreakpointSet 32630fdc8d8SChris Lattner //------------------------------------------------------------------------- 32730fdc8d8SChris Lattner 328b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 3295a988416SJim Ingham public: 330b9c1b51eSKate Stone typedef enum BreakpointSetType { 3315a988416SJim Ingham eSetTypeInvalid, 3325a988416SJim Ingham eSetTypeFileAndLine, 3335a988416SJim Ingham eSetTypeAddress, 3345a988416SJim Ingham eSetTypeFunctionName, 3355a988416SJim Ingham eSetTypeFunctionRegexp, 3365a988416SJim Ingham eSetTypeSourceRegexp, 3375a988416SJim Ingham eSetTypeException 3385a988416SJim Ingham } BreakpointSetType; 3395a988416SJim Ingham 340b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 341b9c1b51eSKate Stone : CommandObjectParsed( 342b9c1b51eSKate Stone interpreter, "breakpoint set", 3435a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 3445a988416SJim Ingham "breakpoint set <cmd-options>"), 345b842f2ecSJim Ingham m_bp_opts(), m_options() { 346b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 347b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 348b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 349b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 350b842f2ecSJim Ingham m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 351b842f2ecSJim Ingham m_all_options.Append(&m_options); 352b842f2ecSJim Ingham m_all_options.Finalize(); 353b842f2ecSJim Ingham } 3545a988416SJim Ingham 3559e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 3565a988416SJim Ingham 357b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 3585a988416SJim Ingham 359b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 3605a988416SJim Ingham public: 361b9c1b51eSKate Stone CommandOptions() 362b842f2ecSJim Ingham : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 363b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 364b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 365b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 366a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 36723b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 368b842f2ecSJim Ingham m_skip_prologue(eLazyBoolCalculate), 369b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 37030fdc8d8SChris Lattner 3719e85e5a8SEugene Zelenko ~CommandOptions() override = default; 37287df91b8SJim Ingham 37397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 374b9c1b51eSKate Stone ExecutionContext *execution_context) override { 37597206d57SZachary Turner Status error; 376b842f2ecSJim Ingham const int short_option = g_breakpoint_set_options[option_idx].short_option; 37730fdc8d8SChris Lattner 378b9c1b51eSKate Stone switch (short_option) { 379b9c1b51eSKate Stone case 'a': { 380b9c1b51eSKate Stone m_load_addr = Args::StringToAddress(execution_context, option_arg, 381e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 382b9c1b51eSKate Stone } break; 38330fdc8d8SChris Lattner 384e732052fSJim Ingham case 'A': 385e732052fSJim Ingham m_all_files = true; 386e732052fSJim Ingham break; 387e732052fSJim Ingham 388ca36cd16SJim Ingham case 'b': 389ca36cd16SJim Ingham m_func_names.push_back(option_arg); 390ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 391ca36cd16SJim Ingham break; 392ca36cd16SJim Ingham 393fe11483bSZachary Turner case 'C': 394fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 395b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 396fe11483bSZachary Turner option_arg.str().c_str()); 39730fdc8d8SChris Lattner break; 3989e85e5a8SEugene Zelenko 399b9c1b51eSKate Stone case 'E': { 400fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 401fab10e89SJim Ingham 402b9c1b51eSKate Stone switch (language) { 403fab10e89SJim Ingham case eLanguageTypeC89: 404fab10e89SJim Ingham case eLanguageTypeC: 405fab10e89SJim Ingham case eLanguageTypeC99: 4061d0089faSBruce Mitchener case eLanguageTypeC11: 407a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 408fab10e89SJim Ingham break; 409fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 4101d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 4111d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 4122ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 413a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 414fab10e89SJim Ingham break; 415fab10e89SJim Ingham case eLanguageTypeObjC: 416a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 417fab10e89SJim Ingham break; 418fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 419b9c1b51eSKate Stone error.SetErrorStringWithFormat( 420b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 421fab10e89SJim Ingham break; 422fab10e89SJim Ingham case eLanguageTypeUnknown: 423b9c1b51eSKate Stone error.SetErrorStringWithFormat( 424b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 425fe11483bSZachary Turner option_arg.str().c_str()); 426fab10e89SJim Ingham break; 427fab10e89SJim Ingham default: 428b9c1b51eSKate Stone error.SetErrorStringWithFormat( 429b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 430fe11483bSZachary Turner option_arg.str().c_str()); 431fab10e89SJim Ingham } 432b9c1b51eSKate Stone } break; 433ca36cd16SJim Ingham 434ca36cd16SJim Ingham case 'f': 435ca36cd16SJim Ingham m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 436fab10e89SJim Ingham break; 437ca36cd16SJim Ingham 438ca36cd16SJim Ingham case 'F': 439ca36cd16SJim Ingham m_func_names.push_back(option_arg); 440ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 441ca36cd16SJim Ingham break; 442ca36cd16SJim Ingham 443b9c1b51eSKate Stone case 'h': { 444fab10e89SJim Ingham bool success; 445fe11483bSZachary Turner m_catch_bp = Args::StringToBoolean(option_arg, true, &success); 446fab10e89SJim Ingham if (!success) 447b9c1b51eSKate Stone error.SetErrorStringWithFormat( 448fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 449fe11483bSZachary Turner option_arg.str().c_str()); 450b9c1b51eSKate Stone } break; 451eb023e75SGreg Clayton 452eb023e75SGreg Clayton case 'H': 453eb023e75SGreg Clayton m_hardware = true; 454eb023e75SGreg Clayton break; 455eb023e75SGreg Clayton 456b9c1b51eSKate Stone case 'K': { 457a8558b62SJim Ingham bool success; 458a8558b62SJim Ingham bool value; 459fe11483bSZachary Turner value = Args::StringToBoolean(option_arg, true, &success); 460a8558b62SJim Ingham if (value) 461a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 462a8558b62SJim Ingham else 463a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 464a8558b62SJim Ingham 465a8558b62SJim Ingham if (!success) 466b9c1b51eSKate Stone error.SetErrorStringWithFormat( 467b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 468fe11483bSZachary Turner option_arg.str().c_str()); 469b9c1b51eSKate Stone } break; 470ca36cd16SJim Ingham 471fe11483bSZachary Turner case 'l': 472fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 473b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 474fe11483bSZachary Turner option_arg.str().c_str()); 475ca36cd16SJim Ingham break; 476055ad9beSIlia K 47723b1decbSDawn Perchik case 'L': 478fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 47923b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 480b9c1b51eSKate Stone error.SetErrorStringWithFormat( 481fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 482fe11483bSZachary Turner option_arg.str().c_str()); 48323b1decbSDawn Perchik break; 48423b1decbSDawn Perchik 485b9c1b51eSKate Stone case 'm': { 486055ad9beSIlia K bool success; 487055ad9beSIlia K bool value; 488fe11483bSZachary Turner value = Args::StringToBoolean(option_arg, true, &success); 489055ad9beSIlia K if (value) 490055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 491055ad9beSIlia K else 492055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 493055ad9beSIlia K 494055ad9beSIlia K if (!success) 495b9c1b51eSKate Stone error.SetErrorStringWithFormat( 496b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 497fe11483bSZachary Turner option_arg.str().c_str()); 498055ad9beSIlia K break; 499055ad9beSIlia K } 500055ad9beSIlia K 501ca36cd16SJim Ingham case 'M': 502ca36cd16SJim Ingham m_func_names.push_back(option_arg); 503ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 504ca36cd16SJim Ingham break; 505ca36cd16SJim Ingham 506ca36cd16SJim Ingham case 'n': 507ca36cd16SJim Ingham m_func_names.push_back(option_arg); 508ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 509ca36cd16SJim Ingham break; 510ca36cd16SJim Ingham 5116fa7681bSZachary Turner case 'N': { 512fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 5135e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 514ff9a91eaSJim Ingham else 515ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 516fe11483bSZachary Turner option_arg.str().c_str()); 5175e09c8c3SJim Ingham break; 5186fa7681bSZachary Turner } 5195e09c8c3SJim Ingham 520b9c1b51eSKate Stone case 'R': { 5212411167fSJim Ingham lldb::addr_t tmp_offset_addr; 522e1cfbc79STodd Fiala tmp_offset_addr = 523b9c1b51eSKate Stone Args::StringToAddress(execution_context, option_arg, 0, &error); 5242411167fSJim Ingham if (error.Success()) 5252411167fSJim Ingham m_offset_addr = tmp_offset_addr; 526b9c1b51eSKate Stone } break; 5272411167fSJim Ingham 528a72b31c7SJim Ingham case 'O': 529fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 530fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 531a72b31c7SJim Ingham break; 532a72b31c7SJim Ingham 533ca36cd16SJim Ingham case 'p': 534ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 535ca36cd16SJim Ingham break; 536ca36cd16SJim Ingham 537ca36cd16SJim Ingham case 'r': 538ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 539ca36cd16SJim Ingham break; 540ca36cd16SJim Ingham 541ca36cd16SJim Ingham case 's': 542ca36cd16SJim Ingham m_modules.AppendIfUnique(FileSpec(option_arg, false)); 543ca36cd16SJim Ingham break; 544ca36cd16SJim Ingham 545ca36cd16SJim Ingham case 'S': 546ca36cd16SJim Ingham m_func_names.push_back(option_arg); 547ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 548ca36cd16SJim Ingham break; 549ca36cd16SJim Ingham 550b9c1b51eSKate Stone case 'w': { 551ca36cd16SJim Ingham bool success; 552fe11483bSZachary Turner m_throw_bp = Args::StringToBoolean(option_arg, true, &success); 553ca36cd16SJim Ingham if (!success) 554b9c1b51eSKate Stone error.SetErrorStringWithFormat( 555fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 556fe11483bSZachary Turner option_arg.str().c_str()); 557b9c1b51eSKate Stone } break; 558ca36cd16SJim Ingham 55976bb8d67SJim Ingham case 'X': 56076bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 56176bb8d67SJim Ingham break; 56276bb8d67SJim Ingham 56330fdc8d8SChris Lattner default: 564b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 565b9c1b51eSKate Stone short_option); 56630fdc8d8SChris Lattner break; 56730fdc8d8SChris Lattner } 56830fdc8d8SChris Lattner 56930fdc8d8SChris Lattner return error; 57030fdc8d8SChris Lattner } 5719e85e5a8SEugene Zelenko 572b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 57387df91b8SJim Ingham m_filenames.Clear(); 57430fdc8d8SChris Lattner m_line_num = 0; 57530fdc8d8SChris Lattner m_column = 0; 576fab10e89SJim Ingham m_func_names.clear(); 5771f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 57830fdc8d8SChris Lattner m_func_regexp.clear(); 5791f746071SGreg Clayton m_source_text_regexp.clear(); 58087df91b8SJim Ingham m_modules.Clear(); 5811f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 5822411167fSJim Ingham m_offset_addr = 0; 583fab10e89SJim Ingham m_catch_bp = false; 584fab10e89SJim Ingham m_throw_bp = true; 585eb023e75SGreg Clayton m_hardware = false; 586a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 58723b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 588a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 5895e09c8c3SJim Ingham m_breakpoint_names.clear(); 590e732052fSJim Ingham m_all_files = false; 591a72b31c7SJim Ingham m_exception_extra_args.Clear(); 592055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 59376bb8d67SJim Ingham m_source_regex_func_names.clear(); 59430fdc8d8SChris Lattner } 59530fdc8d8SChris Lattner 5961f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 59770602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 5981f0f5b5bSZachary Turner } 59930fdc8d8SChris Lattner 6005a988416SJim Ingham // Instance variables to hold the values for command options. 601969795f1SJim Ingham 6025a988416SJim Ingham std::string m_condition; 6035a988416SJim Ingham FileSpecList m_filenames; 6045a988416SJim Ingham uint32_t m_line_num; 6055a988416SJim Ingham uint32_t m_column; 6065a988416SJim Ingham std::vector<std::string> m_func_names; 6075e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 6085a988416SJim Ingham uint32_t m_func_name_type_mask; 6095a988416SJim Ingham std::string m_func_regexp; 6105a988416SJim Ingham std::string m_source_text_regexp; 6115a988416SJim Ingham FileSpecList m_modules; 6125a988416SJim Ingham lldb::addr_t m_load_addr; 6132411167fSJim Ingham lldb::addr_t m_offset_addr; 6145a988416SJim Ingham bool m_catch_bp; 6155a988416SJim Ingham bool m_throw_bp; 616eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 617a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 61823b1decbSDawn Perchik lldb::LanguageType m_language; 6195a988416SJim Ingham LazyBool m_skip_prologue; 620e732052fSJim Ingham bool m_all_files; 621a72b31c7SJim Ingham Args m_exception_extra_args; 622055ad9beSIlia K LazyBool m_move_to_nearest_code; 62376bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 6245a988416SJim Ingham }; 6255a988416SJim Ingham 6265a988416SJim Ingham protected: 627b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 628b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 62933df7cd3SJim Ingham 630b9c1b51eSKate Stone if (target == nullptr) { 631b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 632b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 63330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 63430fdc8d8SChris Lattner return false; 63530fdc8d8SChris Lattner } 63630fdc8d8SChris Lattner 63730fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 63830fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 63930fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 64030fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 641b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 642b9c1b51eSKate Stone // expression) 643b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 644b9c1b51eSKate Stone // to source text) 645b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 646b9c1b51eSKate Stone // given language.) 64730fdc8d8SChris Lattner 64830fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 64930fdc8d8SChris Lattner 65030fdc8d8SChris Lattner if (m_options.m_line_num != 0) 65130fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 65230fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 65330fdc8d8SChris Lattner break_type = eSetTypeAddress; 654fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 65530fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 65630fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 65730fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 658969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 659969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 660a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 661fab10e89SJim Ingham break_type = eSetTypeException; 66230fdc8d8SChris Lattner 663b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 664274060b6SGreg Clayton FileSpec module_spec; 665a8558b62SJim Ingham const bool internal = false; 666a8558b62SJim Ingham 667b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 668b9c1b51eSKate Stone // that off. 669b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 670b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 6712411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 6722411167fSJim Ingham 673b9c1b51eSKate Stone switch (break_type) { 67430fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 67530fdc8d8SChris Lattner { 67630fdc8d8SChris Lattner FileSpec file; 677c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 678b9c1b51eSKate Stone if (num_files == 0) { 679b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 68087df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 68187df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 68287df91b8SJim Ingham return false; 68387df91b8SJim Ingham } 684b9c1b51eSKate Stone } else if (num_files > 1) { 685b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 686b9c1b51eSKate Stone "line breakpoints."); 68787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 68887df91b8SJim Ingham return false; 689b9c1b51eSKate Stone } else 69087df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 69130fdc8d8SChris Lattner 6921f746071SGreg Clayton // Only check for inline functions if 6931f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 6941f746071SGreg Clayton 695b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 696b842f2ecSJim Ingham file, 697b842f2ecSJim Ingham m_options.m_line_num, 698b842f2ecSJim Ingham m_options.m_offset_addr, 699b842f2ecSJim Ingham check_inlines, 700b842f2ecSJim Ingham m_options.m_skip_prologue, 701b842f2ecSJim Ingham internal, 702b842f2ecSJim Ingham m_options.m_hardware, 703b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 704b9c1b51eSKate Stone } break; 7056eee5aa0SGreg Clayton 70630fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 707055a08a4SJim Ingham { 708b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 709b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 710b842f2ecSJim Ingham // will track the load location of the library. 711055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 712b9c1b51eSKate Stone if (num_modules_specified == 1) { 713b9c1b51eSKate Stone const FileSpec *file_spec = 714b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 715b842f2ecSJim Ingham bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 716b9c1b51eSKate Stone internal, file_spec, 717b842f2ecSJim Ingham m_options.m_hardware); 718b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 719b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, 720b842f2ecSJim Ingham m_options.m_hardware); 721b9c1b51eSKate Stone } else { 722b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 723b9c1b51eSKate Stone "address breakpoints."); 724055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 725055a08a4SJim Ingham return false; 726055a08a4SJim Ingham } 72730fdc8d8SChris Lattner break; 728055a08a4SJim Ingham } 72930fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 7300c5cd90dSGreg Clayton { 7310c5cd90dSGreg Clayton uint32_t name_type_mask = m_options.m_func_name_type_mask; 7320c5cd90dSGreg Clayton 7330c5cd90dSGreg Clayton if (name_type_mask == 0) 734e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 7350c5cd90dSGreg Clayton 736b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 737b842f2ecSJim Ingham &(m_options.m_filenames), 738b842f2ecSJim Ingham m_options.m_func_names, 739b842f2ecSJim Ingham name_type_mask, 740b842f2ecSJim Ingham m_options.m_language, 741b842f2ecSJim Ingham m_options.m_offset_addr, 742b842f2ecSJim Ingham m_options.m_skip_prologue, 743b842f2ecSJim Ingham internal, 744b842f2ecSJim Ingham m_options.m_hardware); 745b9c1b51eSKate Stone } break; 7460c5cd90dSGreg Clayton 747b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 748b9c1b51eSKate Stone // name 74930fdc8d8SChris Lattner { 75095eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 751b9c1b51eSKate Stone if (!regexp.IsValid()) { 752969795f1SJim Ingham char err_str[1024]; 753969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 754b9c1b51eSKate Stone result.AppendErrorWithFormat( 755b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 756969795f1SJim Ingham err_str); 75730fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 758969795f1SJim Ingham return false; 75930fdc8d8SChris Lattner } 76087df91b8SJim Ingham 761b842f2ecSJim Ingham bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), 762b842f2ecSJim Ingham &(m_options.m_filenames), 763b842f2ecSJim Ingham regexp, 764b842f2ecSJim Ingham m_options.m_language, 765b842f2ecSJim Ingham m_options.m_skip_prologue, 766b842f2ecSJim Ingham internal, 767b842f2ecSJim Ingham m_options.m_hardware); 768e14dc268SJim Ingham } 769e14dc268SJim Ingham break; 770969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 771969795f1SJim Ingham { 772c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 77387df91b8SJim Ingham 774b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 775969795f1SJim Ingham FileSpec file; 776b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 777b9c1b51eSKate Stone result.AppendError( 778b9c1b51eSKate Stone "No files provided and could not find default file."); 77987df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 78087df91b8SJim Ingham return false; 781b9c1b51eSKate Stone } else { 78287df91b8SJim Ingham m_options.m_filenames.Append(file); 78387df91b8SJim Ingham } 78487df91b8SJim Ingham } 7850c5cd90dSGreg Clayton 78695eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 787b9c1b51eSKate Stone if (!regexp.IsValid()) { 788969795f1SJim Ingham char err_str[1024]; 789969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 790b9c1b51eSKate Stone result.AppendErrorWithFormat( 791b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 792969795f1SJim Ingham err_str); 793969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 794969795f1SJim Ingham return false; 795969795f1SJim Ingham } 796b842f2ecSJim Ingham bp_sp = 797b842f2ecSJim Ingham target->CreateSourceRegexBreakpoint(&(m_options.m_modules), 798b842f2ecSJim Ingham &(m_options.m_filenames), 799b842f2ecSJim Ingham m_options 800b842f2ecSJim Ingham .m_source_regex_func_names, 801b842f2ecSJim Ingham regexp, 802b842f2ecSJim Ingham internal, 803b842f2ecSJim Ingham m_options.m_hardware, 804b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 805b9c1b51eSKate Stone } break; 806b9c1b51eSKate Stone case eSetTypeException: { 80797206d57SZachary Turner Status precond_error; 808b842f2ecSJim Ingham bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, 809b842f2ecSJim Ingham m_options.m_catch_bp, 810b842f2ecSJim Ingham m_options.m_throw_bp, 811b842f2ecSJim Ingham internal, 812b842f2ecSJim Ingham &m_options 813b842f2ecSJim Ingham .m_exception_extra_args, 814b842f2ecSJim Ingham &precond_error); 815b9c1b51eSKate Stone if (precond_error.Fail()) { 816b9c1b51eSKate Stone result.AppendErrorWithFormat( 817b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 818a72b31c7SJim Ingham precond_error.AsCString()); 819b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 820a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 821a72b31c7SJim Ingham return false; 822a72b31c7SJim Ingham } 823b9c1b51eSKate Stone } break; 82430fdc8d8SChris Lattner default: 82530fdc8d8SChris Lattner break; 82630fdc8d8SChris Lattner } 82730fdc8d8SChris Lattner 8281b54c88cSJim Ingham // Now set the various options that were passed in: 829b842f2ecSJim Ingham if (bp_sp) { 830b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 831ca36cd16SJim Ingham 832b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 83397206d57SZachary Turner Status name_error; 834ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 835b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 836ff9a91eaSJim Ingham if (name_error.Fail()) { 837ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 838ff9a91eaSJim Ingham name.c_str()); 839b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 840ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 841ff9a91eaSJim Ingham return false; 842ff9a91eaSJim Ingham } 843ff9a91eaSJim Ingham } 8445e09c8c3SJim Ingham } 8451b54c88cSJim Ingham } 8461b54c88cSJim Ingham 847b842f2ecSJim Ingham if (bp_sp) { 84885e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 8491391cc7dSJim Ingham const bool show_locations = false; 850b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 851b9c1b51eSKate Stone show_locations); 8524aeb1989SJim Ingham if (target == m_interpreter.GetDebugger().GetDummyTarget()) 853b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 854b9c1b51eSKate Stone "into future targets.\n"); 855b9c1b51eSKate Stone else { 856b9c1b51eSKate Stone // Don't print out this warning for exception breakpoints. They can get 857b842f2ecSJim Ingham // set before the target is set, but we won't know how to actually set 858b842f2ecSJim Ingham // the breakpoint till we run. 859b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 860b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 861b9c1b51eSKate Stone "actual locations.\n"); 8624aeb1989SJim Ingham } 8634aeb1989SJim Ingham } 86430fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 865b842f2ecSJim Ingham } else if (!bp_sp) { 86630fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 86730fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 86830fdc8d8SChris Lattner } 86930fdc8d8SChris Lattner 87030fdc8d8SChris Lattner return result.Succeeded(); 87130fdc8d8SChris Lattner } 87230fdc8d8SChris Lattner 8735a988416SJim Ingham private: 874b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 875b9c1b51eSKate Stone CommandReturnObject &result) { 8765a988416SJim Ingham uint32_t default_line; 8775a988416SJim Ingham // First use the Source Manager's default file. 8785a988416SJim Ingham // Then use the current stack frame's file. 879b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 880b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 881b9c1b51eSKate Stone if (cur_frame == nullptr) { 882b9c1b51eSKate Stone result.AppendError( 883b9c1b51eSKate Stone "No selected frame to use to find the default file."); 8845a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 8855a988416SJim Ingham return false; 886b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 887b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 888b9c1b51eSKate Stone "file, it has no debug info."); 8895a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 8905a988416SJim Ingham return false; 891b9c1b51eSKate Stone } else { 892b9c1b51eSKate Stone const SymbolContext &sc = 893b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 894b9c1b51eSKate Stone if (sc.line_entry.file) { 8955a988416SJim Ingham file = sc.line_entry.file; 896b9c1b51eSKate Stone } else { 897b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 898b9c1b51eSKate Stone "use as the default file."); 8995a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9005a988416SJim Ingham return false; 9015a988416SJim Ingham } 9025a988416SJim Ingham } 9035a988416SJim Ingham } 9045a988416SJim Ingham return true; 9055a988416SJim Ingham } 9065a988416SJim Ingham 907b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 908b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 9095a988416SJim Ingham CommandOptions m_options; 910b842f2ecSJim Ingham OptionGroupOptions m_all_options; 9115a988416SJim Ingham }; 9129e85e5a8SEugene Zelenko 9135a988416SJim Ingham //------------------------------------------------------------------------- 9145a988416SJim Ingham // CommandObjectBreakpointModify 9155a988416SJim Ingham //------------------------------------------------------------------------- 9165a988416SJim Ingham #pragma mark Modify 9175a988416SJim Ingham 918b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 9195a988416SJim Ingham public: 920b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 921b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 922b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 923b9c1b51eSKate Stone "breakpoints in the executable. " 924b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 925b9c1b51eSKate Stone "created breakpoint. " 926b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 927b9c1b51eSKate Stone "empty argument clears the modification.", 9289e85e5a8SEugene Zelenko nullptr), 929b9c1b51eSKate Stone m_options() { 9305a988416SJim Ingham CommandArgumentEntry arg; 931b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 932b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 933b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 934b9c1b51eSKate Stone // arguments vector. 9355a988416SJim Ingham m_arguments.push_back(arg); 936b842f2ecSJim Ingham 937b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 938b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 939b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 940b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 941b842f2ecSJim Ingham m_options.Finalize(); 9425a988416SJim Ingham } 9435a988416SJim Ingham 9449e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 9455a988416SJim Ingham 946b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 9475a988416SJim Ingham 9485a988416SJim Ingham protected: 949b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 950b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 951b9c1b51eSKate Stone if (target == nullptr) { 9525a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 9535a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9545a988416SJim Ingham return false; 9555a988416SJim Ingham } 9565a988416SJim Ingham 957bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 958bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 9595a988416SJim Ingham 9605a988416SJim Ingham BreakpointIDList valid_bp_ids; 9615a988416SJim Ingham 962b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 963b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 964b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 9655a988416SJim Ingham 966b9c1b51eSKate Stone if (result.Succeeded()) { 9675a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 968b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 9695a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 9705a988416SJim Ingham 971b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 972b9c1b51eSKate Stone Breakpoint *bp = 973b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 974b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 975b9c1b51eSKate Stone BreakpointLocation *location = 976b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 977b842f2ecSJim Ingham if (location) 978b842f2ecSJim Ingham location->GetLocationOptions() 979b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 980b9c1b51eSKate Stone } else { 981b842f2ecSJim Ingham bp->GetOptions() 982b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 9835a988416SJim Ingham } 9845a988416SJim Ingham } 9855a988416SJim Ingham } 9865a988416SJim Ingham } 9875a988416SJim Ingham 9885a988416SJim Ingham return result.Succeeded(); 9895a988416SJim Ingham } 9905a988416SJim Ingham 9915a988416SJim Ingham private: 992b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 993b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 994b842f2ecSJim Ingham OptionGroupOptions m_options; 9955a988416SJim Ingham }; 9965a988416SJim Ingham 9975a988416SJim Ingham //------------------------------------------------------------------------- 9985a988416SJim Ingham // CommandObjectBreakpointEnable 9995a988416SJim Ingham //------------------------------------------------------------------------- 10005a988416SJim Ingham #pragma mark Enable 10015a988416SJim Ingham 1002b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10035a988416SJim Ingham public: 1004b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1005b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1006b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1007b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1008b9c1b51eSKate Stone nullptr) { 10095a988416SJim Ingham CommandArgumentEntry arg; 1010b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1011b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1012b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1013b9c1b51eSKate Stone // arguments vector. 10145a988416SJim Ingham m_arguments.push_back(arg); 10155a988416SJim Ingham } 10165a988416SJim Ingham 10179e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10185a988416SJim Ingham 10195a988416SJim Ingham protected: 1020b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1021893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1022b9c1b51eSKate Stone if (target == nullptr) { 10235a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10245a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10255a988416SJim Ingham return false; 10265a988416SJim Ingham } 10275a988416SJim Ingham 1028bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1029bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10305a988416SJim Ingham 10315a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 10325a988416SJim Ingham 10335a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10345a988416SJim Ingham 1035b9c1b51eSKate Stone if (num_breakpoints == 0) { 10365a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 10375a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10385a988416SJim Ingham return false; 10395a988416SJim Ingham } 10405a988416SJim Ingham 104111eb9c64SZachary Turner if (command.empty()) { 10425a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 1043b842f2ecSJim Ingham target->EnableAllowedBreakpoints(); 1044b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1045b9c1b51eSKate Stone " breakpoints)\n", 1046b9c1b51eSKate Stone (uint64_t)num_breakpoints); 10475a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1048b9c1b51eSKate Stone } else { 10495a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 10505a988416SJim Ingham BreakpointIDList valid_bp_ids; 1051b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1052b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1053b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10545a988416SJim Ingham 1055b9c1b51eSKate Stone if (result.Succeeded()) { 10565a988416SJim Ingham int enable_count = 0; 10575a988416SJim Ingham int loc_count = 0; 10585a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1059b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10605a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10615a988416SJim Ingham 1062b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1063b9c1b51eSKate Stone Breakpoint *breakpoint = 1064b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1065b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1066b9c1b51eSKate Stone BreakpointLocation *location = 1067b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1068b9c1b51eSKate Stone if (location) { 10695a988416SJim Ingham location->SetEnabled(true); 10705a988416SJim Ingham ++loc_count; 10715a988416SJim Ingham } 1072b9c1b51eSKate Stone } else { 10735a988416SJim Ingham breakpoint->SetEnabled(true); 10745a988416SJim Ingham ++enable_count; 10755a988416SJim Ingham } 10765a988416SJim Ingham } 10775a988416SJim Ingham } 1078b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1079b9c1b51eSKate Stone enable_count + loc_count); 10805a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 10815a988416SJim Ingham } 10825a988416SJim Ingham } 10835a988416SJim Ingham 10845a988416SJim Ingham return result.Succeeded(); 10855a988416SJim Ingham } 10865a988416SJim Ingham }; 10875a988416SJim Ingham 10885a988416SJim Ingham //------------------------------------------------------------------------- 10895a988416SJim Ingham // CommandObjectBreakpointDisable 10905a988416SJim Ingham //------------------------------------------------------------------------- 10915a988416SJim Ingham #pragma mark Disable 10925a988416SJim Ingham 1093b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 10945a988416SJim Ingham public: 10957428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1096b9c1b51eSKate Stone : CommandObjectParsed( 1097b9c1b51eSKate Stone interpreter, "breakpoint disable", 1098b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 10997428a18cSKate Stone "them. If none are specified, disable all " 11007428a18cSKate Stone "breakpoints.", 1101b9c1b51eSKate Stone nullptr) { 1102b9c1b51eSKate Stone SetHelpLong( 1103b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11047428a18cSKate Stone If none are specified, disable all breakpoints." 11057428a18cSKate Stone R"( 1106ea671fbdSKate Stone 11077428a18cSKate Stone )" 11087428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11097428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11107428a18cSKate Stone R"( 1111ea671fbdSKate Stone 1112ea671fbdSKate Stone (lldb) break disable 1 1113ea671fbdSKate Stone (lldb) break enable 1.1 1114ea671fbdSKate Stone 1115ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1116ea671fbdSKate Stone 1117ea671fbdSKate Stone (lldb) break disable 1.* 1118ea671fbdSKate Stone (lldb) break enable 1.1 1119ea671fbdSKate Stone 11207428a18cSKate Stone )" 11217428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 11227428a18cSKate Stone the second re-enables the first location."); 1123b0fac509SJim Ingham 11245a988416SJim Ingham CommandArgumentEntry arg; 1125b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1126b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1127b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1128b9c1b51eSKate Stone // arguments vector. 11295a988416SJim Ingham m_arguments.push_back(arg); 11305a988416SJim Ingham } 11315a988416SJim Ingham 11329e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 11335a988416SJim Ingham 11345a988416SJim Ingham protected: 1135b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1136893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1137b9c1b51eSKate Stone if (target == nullptr) { 11385a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 11395a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11405a988416SJim Ingham return false; 11415a988416SJim Ingham } 11425a988416SJim Ingham 1143bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1144bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 11455a988416SJim Ingham 11465a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 11475a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 11485a988416SJim Ingham 1149b9c1b51eSKate Stone if (num_breakpoints == 0) { 11505a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 11515a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11525a988416SJim Ingham return false; 11535a988416SJim Ingham } 11545a988416SJim Ingham 115511eb9c64SZachary Turner if (command.empty()) { 11565a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1157b842f2ecSJim Ingham target->DisableAllowedBreakpoints(); 1158b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1159b9c1b51eSKate Stone " breakpoints)\n", 1160b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11615a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1162b9c1b51eSKate Stone } else { 11635a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 11645a988416SJim Ingham BreakpointIDList valid_bp_ids; 11655a988416SJim Ingham 1166b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1167b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1168b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 11695a988416SJim Ingham 1170b9c1b51eSKate Stone if (result.Succeeded()) { 11715a988416SJim Ingham int disable_count = 0; 11725a988416SJim Ingham int loc_count = 0; 11735a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1174b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11755a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11765a988416SJim Ingham 1177b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1178b9c1b51eSKate Stone Breakpoint *breakpoint = 1179b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1180b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1181b9c1b51eSKate Stone BreakpointLocation *location = 1182b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1183b9c1b51eSKate Stone if (location) { 11845a988416SJim Ingham location->SetEnabled(false); 11855a988416SJim Ingham ++loc_count; 11865a988416SJim Ingham } 1187b9c1b51eSKate Stone } else { 11885a988416SJim Ingham breakpoint->SetEnabled(false); 11895a988416SJim Ingham ++disable_count; 11905a988416SJim Ingham } 11915a988416SJim Ingham } 11925a988416SJim Ingham } 1193b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1194b9c1b51eSKate Stone disable_count + loc_count); 11955a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11965a988416SJim Ingham } 11975a988416SJim Ingham } 11985a988416SJim Ingham 11995a988416SJim Ingham return result.Succeeded(); 12005a988416SJim Ingham } 12015a988416SJim Ingham }; 12025a988416SJim Ingham 12035a988416SJim Ingham //------------------------------------------------------------------------- 12045a988416SJim Ingham // CommandObjectBreakpointList 12055a988416SJim Ingham //------------------------------------------------------------------------- 12061f0f5b5bSZachary Turner 12071f0f5b5bSZachary Turner #pragma mark List::CommandOptions 12081f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_list_options[] = { 12091f0f5b5bSZachary Turner // clang-format off 12101f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 12111f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, 12121f0f5b5bSZachary Turner // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 12131f0f5b5bSZachary Turner // But I need to see it for now, and don't want to wait. 12141f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, 12151f0f5b5bSZachary Turner { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 12161f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, 12171f0f5b5bSZachary Turner // clang-format on 12181f0f5b5bSZachary Turner }; 12191f0f5b5bSZachary Turner 12205a988416SJim Ingham #pragma mark List 12215a988416SJim Ingham 1222b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12235a988416SJim Ingham public: 1224b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1225b9c1b51eSKate Stone : CommandObjectParsed( 1226b9c1b51eSKate Stone interpreter, "breakpoint list", 12275a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 12289e85e5a8SEugene Zelenko nullptr), 1229b9c1b51eSKate Stone m_options() { 12305a988416SJim Ingham CommandArgumentEntry arg; 12315a988416SJim Ingham CommandArgumentData bp_id_arg; 12325a988416SJim Ingham 12335a988416SJim Ingham // Define the first (and only) variant of this arg. 12345a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 12355a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 12365a988416SJim Ingham 1237b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1238b9c1b51eSKate Stone // argument entry. 12395a988416SJim Ingham arg.push_back(bp_id_arg); 12405a988416SJim Ingham 12415a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12425a988416SJim Ingham m_arguments.push_back(arg); 12435a988416SJim Ingham } 12445a988416SJim Ingham 12459e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 12465a988416SJim Ingham 1247b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12485a988416SJim Ingham 1249b9c1b51eSKate Stone class CommandOptions : public Options { 12505a988416SJim Ingham public: 1251b9c1b51eSKate Stone CommandOptions() 1252b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 12535a988416SJim Ingham } 12545a988416SJim Ingham 12559e85e5a8SEugene Zelenko ~CommandOptions() override = default; 12565a988416SJim Ingham 125797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1258b9c1b51eSKate Stone ExecutionContext *execution_context) override { 125997206d57SZachary Turner Status error; 12603bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12615a988416SJim Ingham 1262b9c1b51eSKate Stone switch (short_option) { 12635a988416SJim Ingham case 'b': 12645a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 12655a988416SJim Ingham break; 126633df7cd3SJim Ingham case 'D': 126733df7cd3SJim Ingham m_use_dummy = true; 126833df7cd3SJim Ingham break; 12695a988416SJim Ingham case 'f': 12705a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 12715a988416SJim Ingham break; 12725a988416SJim Ingham case 'v': 12735a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 12745a988416SJim Ingham break; 12755a988416SJim Ingham case 'i': 12765a988416SJim Ingham m_internal = true; 12775a988416SJim Ingham break; 12785a988416SJim Ingham default: 1279b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1280b9c1b51eSKate Stone short_option); 12815a988416SJim Ingham break; 12825a988416SJim Ingham } 12835a988416SJim Ingham 12845a988416SJim Ingham return error; 12855a988416SJim Ingham } 12865a988416SJim Ingham 1287b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 12885a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 12895a988416SJim Ingham m_internal = false; 129033df7cd3SJim Ingham m_use_dummy = false; 12915a988416SJim Ingham } 12925a988416SJim Ingham 12931f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 129470602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 12951f0f5b5bSZachary Turner } 12965a988416SJim Ingham 12975a988416SJim Ingham // Instance variables to hold the values for command options. 12985a988416SJim Ingham 12995a988416SJim Ingham lldb::DescriptionLevel m_level; 13005a988416SJim Ingham 13015a988416SJim Ingham bool m_internal; 130233df7cd3SJim Ingham bool m_use_dummy; 13035a988416SJim Ingham }; 13045a988416SJim Ingham 13055a988416SJim Ingham protected: 1306b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 130733df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 130833df7cd3SJim Ingham 1309b9c1b51eSKate Stone if (target == nullptr) { 13105a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13115a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13125a988416SJim Ingham return true; 13135a988416SJim Ingham } 13145a988416SJim Ingham 1315b9c1b51eSKate Stone const BreakpointList &breakpoints = 1316b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1317bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1318bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13195a988416SJim Ingham 13205a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13215a988416SJim Ingham 1322b9c1b51eSKate Stone if (num_breakpoints == 0) { 13235a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13245a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13255a988416SJim Ingham return true; 13265a988416SJim Ingham } 13275a988416SJim Ingham 13285a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13295a988416SJim Ingham 133011eb9c64SZachary Turner if (command.empty()) { 13315a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 13325a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1333b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13345a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1335b842f2ecSJim Ingham if (breakpoint->AllowList()) 1336b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1337b842f2ecSJim Ingham m_options.m_level); 13385a988416SJim Ingham } 13395a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1340b9c1b51eSKate Stone } else { 13415a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 13425a988416SJim Ingham BreakpointIDList valid_bp_ids; 1343b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1344b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1345b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 13465a988416SJim Ingham 1347b9c1b51eSKate Stone if (result.Succeeded()) { 1348b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 13495a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1350b9c1b51eSKate Stone Breakpoint *breakpoint = 1351b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1352b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1353b9c1b51eSKate Stone m_options.m_level); 13545a988416SJim Ingham } 13555a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1356b9c1b51eSKate Stone } else { 13577428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 13585a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 13595a988416SJim Ingham } 13605a988416SJim Ingham } 13615a988416SJim Ingham 13625a988416SJim Ingham return result.Succeeded(); 13635a988416SJim Ingham } 13645a988416SJim Ingham 13655a988416SJim Ingham private: 13665a988416SJim Ingham CommandOptions m_options; 13675a988416SJim Ingham }; 13685a988416SJim Ingham 13695a988416SJim Ingham //------------------------------------------------------------------------- 13705a988416SJim Ingham // CommandObjectBreakpointClear 13715a988416SJim Ingham //------------------------------------------------------------------------- 13721f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 13731f0f5b5bSZachary Turner 13741f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_clear_options[] = { 13751f0f5b5bSZachary Turner // clang-format off 13761f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, 13771f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } 13781f0f5b5bSZachary Turner // clang-format on 13791f0f5b5bSZachary Turner }; 13801f0f5b5bSZachary Turner 13815a988416SJim Ingham #pragma mark Clear 13825a988416SJim Ingham 1383b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 13845a988416SJim Ingham public: 1385b9c1b51eSKate Stone typedef enum BreakpointClearType { 13865a988416SJim Ingham eClearTypeInvalid, 13875a988416SJim Ingham eClearTypeFileAndLine 13885a988416SJim Ingham } BreakpointClearType; 13895a988416SJim Ingham 13907428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 13917428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1392b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1393b9c1b51eSKate Stone "specified source file and line.", 13945a988416SJim Ingham "breakpoint clear <cmd-options>"), 1395b9c1b51eSKate Stone m_options() {} 13965a988416SJim Ingham 13979e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 13985a988416SJim Ingham 1399b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14005a988416SJim Ingham 1401b9c1b51eSKate Stone class CommandOptions : public Options { 14025a988416SJim Ingham public: 1403b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 14045a988416SJim Ingham 14059e85e5a8SEugene Zelenko ~CommandOptions() override = default; 14065a988416SJim Ingham 140797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1408b9c1b51eSKate Stone ExecutionContext *execution_context) override { 140997206d57SZachary Turner Status error; 14103bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14115a988416SJim Ingham 1412b9c1b51eSKate Stone switch (short_option) { 14135a988416SJim Ingham case 'f': 14145a988416SJim Ingham m_filename.assign(option_arg); 14155a988416SJim Ingham break; 14165a988416SJim Ingham 14175a988416SJim Ingham case 'l': 1418fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 14195a988416SJim Ingham break; 14205a988416SJim Ingham 14215a988416SJim Ingham default: 1422b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1423b9c1b51eSKate Stone short_option); 14245a988416SJim Ingham break; 14255a988416SJim Ingham } 14265a988416SJim Ingham 14275a988416SJim Ingham return error; 14285a988416SJim Ingham } 14295a988416SJim Ingham 1430b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14315a988416SJim Ingham m_filename.clear(); 14325a988416SJim Ingham m_line_num = 0; 14335a988416SJim Ingham } 14345a988416SJim Ingham 14351f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 143670602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 14371f0f5b5bSZachary Turner } 14385a988416SJim Ingham 14395a988416SJim Ingham // Instance variables to hold the values for command options. 14405a988416SJim Ingham 14415a988416SJim Ingham std::string m_filename; 14425a988416SJim Ingham uint32_t m_line_num; 14435a988416SJim Ingham }; 14445a988416SJim Ingham 14455a988416SJim Ingham protected: 1446b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1447893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1448b9c1b51eSKate Stone if (target == nullptr) { 14495a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 14505a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14515a988416SJim Ingham return false; 14525a988416SJim Ingham } 14535a988416SJim Ingham 14545a988416SJim Ingham // The following are the various types of breakpoints that could be cleared: 14555a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 14565a988416SJim Ingham 14575a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 14585a988416SJim Ingham 14595a988416SJim Ingham if (m_options.m_line_num != 0) 14605a988416SJim Ingham break_type = eClearTypeFileAndLine; 14615a988416SJim Ingham 1462bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1463bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 14645a988416SJim Ingham 14655a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 14665a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 14675a988416SJim Ingham 14685a988416SJim Ingham // Early return if there's no breakpoint at all. 1469b9c1b51eSKate Stone if (num_breakpoints == 0) { 14705a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 14715a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14725a988416SJim Ingham return result.Succeeded(); 14735a988416SJim Ingham } 14745a988416SJim Ingham 14755a988416SJim Ingham // Find matching breakpoints and delete them. 14765a988416SJim Ingham 14775a988416SJim Ingham // First create a copy of all the IDs. 14785a988416SJim Ingham std::vector<break_id_t> BreakIDs; 14795a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 14809e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 14815a988416SJim Ingham 14825a988416SJim Ingham int num_cleared = 0; 14835a988416SJim Ingham StreamString ss; 1484b9c1b51eSKate Stone switch (break_type) { 14855a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 14865a988416SJim Ingham { 14875a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 14885a988416SJim Ingham BreakpointLocationCollection loc_coll; 14895a988416SJim Ingham 1490b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 14915a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 14925a988416SJim Ingham 1493b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1494b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1495b9c1b51eSKate Stone // remove the breakpoint. 1496b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 14975a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 14985a988416SJim Ingham ss.EOL(); 14995a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15005a988416SJim Ingham ++num_cleared; 15015a988416SJim Ingham } 15025a988416SJim Ingham } 15035a988416SJim Ingham } 1504b9c1b51eSKate Stone } break; 15055a988416SJim Ingham 15065a988416SJim Ingham default: 15075a988416SJim Ingham break; 15085a988416SJim Ingham } 15095a988416SJim Ingham 1510b9c1b51eSKate Stone if (num_cleared > 0) { 15115a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15125a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1513c156427dSZachary Turner output_stream << ss.GetString(); 15145a988416SJim Ingham output_stream.EOL(); 15155a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1516b9c1b51eSKate Stone } else { 15175a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15185a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15195a988416SJim Ingham } 15205a988416SJim Ingham 15215a988416SJim Ingham return result.Succeeded(); 15225a988416SJim Ingham } 15235a988416SJim Ingham 15245a988416SJim Ingham private: 15255a988416SJim Ingham CommandOptions m_options; 15265a988416SJim Ingham }; 15275a988416SJim Ingham 15285a988416SJim Ingham //------------------------------------------------------------------------- 15295a988416SJim Ingham // CommandObjectBreakpointDelete 15305a988416SJim Ingham //------------------------------------------------------------------------- 15311f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_delete_options[] = { 15321f0f5b5bSZachary Turner // clang-format off 15331f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, 15341f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, 15351f0f5b5bSZachary Turner // clang-format on 15361f0f5b5bSZachary Turner }; 15371f0f5b5bSZachary Turner 15385a988416SJim Ingham #pragma mark Delete 15395a988416SJim Ingham 1540b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 15415a988416SJim Ingham public: 1542b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1543b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1544b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1545b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 15469e85e5a8SEugene Zelenko nullptr), 1547b9c1b51eSKate Stone m_options() { 15485a988416SJim Ingham CommandArgumentEntry arg; 1549b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1550b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1551b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1552b9c1b51eSKate Stone // arguments vector. 15535a988416SJim Ingham m_arguments.push_back(arg); 15545a988416SJim Ingham } 15555a988416SJim Ingham 15569e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 15575a988416SJim Ingham 1558b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 155933df7cd3SJim Ingham 1560b9c1b51eSKate Stone class CommandOptions : public Options { 156133df7cd3SJim Ingham public: 1562b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 156333df7cd3SJim Ingham 15649e85e5a8SEugene Zelenko ~CommandOptions() override = default; 156533df7cd3SJim Ingham 156697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1567b9c1b51eSKate Stone ExecutionContext *execution_context) override { 156897206d57SZachary Turner Status error; 156933df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 157033df7cd3SJim Ingham 1571b9c1b51eSKate Stone switch (short_option) { 157233df7cd3SJim Ingham case 'f': 157333df7cd3SJim Ingham m_force = true; 157433df7cd3SJim Ingham break; 157533df7cd3SJim Ingham 157633df7cd3SJim Ingham case 'D': 157733df7cd3SJim Ingham m_use_dummy = true; 157833df7cd3SJim Ingham break; 157933df7cd3SJim Ingham 158033df7cd3SJim Ingham default: 1581b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1582b9c1b51eSKate Stone short_option); 158333df7cd3SJim Ingham break; 158433df7cd3SJim Ingham } 158533df7cd3SJim Ingham 158633df7cd3SJim Ingham return error; 158733df7cd3SJim Ingham } 158833df7cd3SJim Ingham 1589b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 159033df7cd3SJim Ingham m_use_dummy = false; 159133df7cd3SJim Ingham m_force = false; 159233df7cd3SJim Ingham } 159333df7cd3SJim Ingham 15941f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 159570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 15961f0f5b5bSZachary Turner } 159733df7cd3SJim Ingham 159833df7cd3SJim Ingham // Instance variables to hold the values for command options. 159933df7cd3SJim Ingham bool m_use_dummy; 160033df7cd3SJim Ingham bool m_force; 160133df7cd3SJim Ingham }; 160233df7cd3SJim Ingham 16035a988416SJim Ingham protected: 1604b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 160533df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 160633df7cd3SJim Ingham 1607b9c1b51eSKate Stone if (target == nullptr) { 16085a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16095a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16105a988416SJim Ingham return false; 16115a988416SJim Ingham } 16125a988416SJim Ingham 1613bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1614bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16155a988416SJim Ingham 16165a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16175a988416SJim Ingham 16185a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16195a988416SJim Ingham 1620b9c1b51eSKate Stone if (num_breakpoints == 0) { 16215a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 16225a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16235a988416SJim Ingham return false; 16245a988416SJim Ingham } 16255a988416SJim Ingham 162611eb9c64SZachary Turner if (command.empty()) { 1627b9c1b51eSKate Stone if (!m_options.m_force && 1628b9c1b51eSKate Stone !m_interpreter.Confirm( 1629b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1630b9c1b51eSKate Stone true)) { 16315a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1632b9c1b51eSKate Stone } else { 1633b842f2ecSJim Ingham target->RemoveAllowedBreakpoints(); 1634b9c1b51eSKate Stone result.AppendMessageWithFormat( 1635b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1636b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 16375a988416SJim Ingham } 16385a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1639b9c1b51eSKate Stone } else { 16405a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 16415a988416SJim Ingham BreakpointIDList valid_bp_ids; 1642b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1643b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1644b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 16455a988416SJim Ingham 1646b9c1b51eSKate Stone if (result.Succeeded()) { 16475a988416SJim Ingham int delete_count = 0; 16485a988416SJim Ingham int disable_count = 0; 16495a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1650b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 16515a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 16525a988416SJim Ingham 1653b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1654b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1655b9c1b51eSKate Stone Breakpoint *breakpoint = 1656b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1657b9c1b51eSKate Stone BreakpointLocation *location = 1658b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1659b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1660b9c1b51eSKate Stone // disable them instead. 1661b9c1b51eSKate Stone if (location) { 16625a988416SJim Ingham location->SetEnabled(false); 16635a988416SJim Ingham ++disable_count; 16645a988416SJim Ingham } 1665b9c1b51eSKate Stone } else { 16665a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 16675a988416SJim Ingham ++delete_count; 16685a988416SJim Ingham } 16695a988416SJim Ingham } 16705a988416SJim Ingham } 1671b9c1b51eSKate Stone result.AppendMessageWithFormat( 1672b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 16735a988416SJim Ingham delete_count, disable_count); 16745a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 16755a988416SJim Ingham } 16765a988416SJim Ingham } 16775a988416SJim Ingham return result.Succeeded(); 16785a988416SJim Ingham } 16799e85e5a8SEugene Zelenko 168033df7cd3SJim Ingham private: 168133df7cd3SJim Ingham CommandOptions m_options; 168233df7cd3SJim Ingham }; 168333df7cd3SJim Ingham 168430fdc8d8SChris Lattner //------------------------------------------------------------------------- 16855e09c8c3SJim Ingham // CommandObjectBreakpointName 16865e09c8c3SJim Ingham //------------------------------------------------------------------------- 16875e09c8c3SJim Ingham 16887428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = { 1689ac9c3a62SKate Stone // clang-format off 1690ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1691ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1692b842f2ecSJim Ingham {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 1693*e9632ebaSJim Ingham {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."}, 1694ac9c3a62SKate Stone // clang-format on 16955e09c8c3SJim Ingham }; 1696b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 16975e09c8c3SJim Ingham public: 1698b9c1b51eSKate Stone BreakpointNameOptionGroup() 1699b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17005e09c8c3SJim Ingham } 17015e09c8c3SJim Ingham 17029e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17035e09c8c3SJim Ingham 17041f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 170570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 17065e09c8c3SJim Ingham } 17075e09c8c3SJim Ingham 170897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1709b9c1b51eSKate Stone ExecutionContext *execution_context) override { 171097206d57SZachary Turner Status error; 17115e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 17125e09c8c3SJim Ingham 1713b9c1b51eSKate Stone switch (short_option) { 17145e09c8c3SJim Ingham case 'N': 1715fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1716b9c1b51eSKate Stone error.Success()) 1717fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 17185e09c8c3SJim Ingham break; 17195e09c8c3SJim Ingham case 'B': 1720fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1721b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17228cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1723fe11483bSZachary Turner option_arg.str().c_str()); 17245e09c8c3SJim Ingham break; 17255e09c8c3SJim Ingham case 'D': 1726fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1727b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17288cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1729fe11483bSZachary Turner option_arg.str().c_str()); 17305e09c8c3SJim Ingham break; 1731*e9632ebaSJim Ingham case 'H': 1732*e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1733*e9632ebaSJim Ingham break; 17345e09c8c3SJim Ingham 17355e09c8c3SJim Ingham default: 1736b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1737b9c1b51eSKate Stone short_option); 17385e09c8c3SJim Ingham break; 17395e09c8c3SJim Ingham } 17405e09c8c3SJim Ingham return error; 17415e09c8c3SJim Ingham } 17425e09c8c3SJim Ingham 1743b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 17445e09c8c3SJim Ingham m_name.Clear(); 17455e09c8c3SJim Ingham m_breakpoint.Clear(); 17465e09c8c3SJim Ingham m_use_dummy.Clear(); 17475e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1748*e9632ebaSJim Ingham m_help_string.Clear(); 17495e09c8c3SJim Ingham } 17505e09c8c3SJim Ingham 17515e09c8c3SJim Ingham OptionValueString m_name; 17525e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 17535e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1754*e9632ebaSJim Ingham OptionValueString m_help_string; 17555e09c8c3SJim Ingham }; 17565e09c8c3SJim Ingham 1757b842f2ecSJim Ingham static OptionDefinition g_breakpoint_access_options[] = { 1758b842f2ecSJim Ingham // clang-format off 1759b842f2ecSJim Ingham {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, 1760b842f2ecSJim Ingham {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, 1761b842f2ecSJim Ingham {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, 1762b842f2ecSJim Ingham // clang-format on 1763b842f2ecSJim Ingham }; 1764b842f2ecSJim Ingham 1765b842f2ecSJim Ingham class BreakpointAccessOptionGroup : public OptionGroup 1766b842f2ecSJim Ingham { 1767b842f2ecSJim Ingham public: 1768b842f2ecSJim Ingham BreakpointAccessOptionGroup() : 1769b842f2ecSJim Ingham OptionGroup() 1770b842f2ecSJim Ingham {} 1771b842f2ecSJim Ingham 1772b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1773b842f2ecSJim Ingham 1774b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1775b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1776b842f2ecSJim Ingham } 1777b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1778b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1779b842f2ecSJim Ingham Status error; 1780b842f2ecSJim Ingham const int short_option 1781b842f2ecSJim Ingham = g_breakpoint_access_options[option_idx].short_option; 1782b842f2ecSJim Ingham 1783b842f2ecSJim Ingham switch (short_option) { 1784b842f2ecSJim Ingham case 'L': { 1785b842f2ecSJim Ingham bool value, success; 1786b842f2ecSJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 1787b842f2ecSJim Ingham if (success) { 1788b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1789b842f2ecSJim Ingham } else 1790b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1791b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1792b842f2ecSJim Ingham option_arg.str().c_str()); 1793b842f2ecSJim Ingham } break; 1794b842f2ecSJim Ingham case 'A': { 1795b842f2ecSJim Ingham bool value, success; 1796b842f2ecSJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 1797b842f2ecSJim Ingham if (success) { 1798b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1799b842f2ecSJim Ingham } else 1800b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1801b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1802b842f2ecSJim Ingham option_arg.str().c_str()); 1803b842f2ecSJim Ingham } break; 1804b842f2ecSJim Ingham case 'D': { 1805b842f2ecSJim Ingham bool value, success; 1806b842f2ecSJim Ingham value = Args::StringToBoolean(option_arg, false, &success); 1807b842f2ecSJim Ingham if (success) { 1808b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1809b842f2ecSJim Ingham } else 1810b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1811b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1812b842f2ecSJim Ingham option_arg.str().c_str()); 1813b842f2ecSJim Ingham } break; 1814b842f2ecSJim Ingham 1815b842f2ecSJim Ingham } 1816b842f2ecSJim Ingham 1817b842f2ecSJim Ingham return error; 1818b842f2ecSJim Ingham } 1819b842f2ecSJim Ingham 1820b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 1821b842f2ecSJim Ingham } 1822b842f2ecSJim Ingham 1823b842f2ecSJim Ingham const BreakpointName::Permissions &GetPermissions() const 1824b842f2ecSJim Ingham { 1825b842f2ecSJim Ingham return m_permissions; 1826b842f2ecSJim Ingham } 1827b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1828b842f2ecSJim Ingham }; 1829b842f2ecSJim Ingham 1830b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1831b842f2ecSJim Ingham public: 1832b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1833b842f2ecSJim Ingham : CommandObjectParsed( 1834b842f2ecSJim Ingham interpreter, "configure", "Configure the options for the breakpoint" 1835b842f2ecSJim Ingham " name provided. " 1836b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1837b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1838b842f2ecSJim Ingham "on the name.", 1839b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1840b842f2ecSJim Ingham "<breakpoint-name-list>"), 1841b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1842b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1843b842f2ecSJim Ingham // command. 1844b842f2ecSJim Ingham CommandArgumentEntry arg1; 1845b842f2ecSJim Ingham CommandArgumentData id_arg; 1846b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1847b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1848b842f2ecSJim Ingham arg1.push_back(id_arg); 1849b842f2ecSJim Ingham m_arguments.push_back(arg1); 1850b842f2ecSJim Ingham 1851b842f2ecSJim Ingham m_option_group.Append(&m_bp_opts, 1852b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1853b842f2ecSJim Ingham LLDB_OPT_SET_1); 1854b842f2ecSJim Ingham m_option_group.Append(&m_access_options, 1855b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1856b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1857*e9632ebaSJim Ingham m_option_group.Append(&m_bp_id, 1858*e9632ebaSJim Ingham LLDB_OPT_SET_2|LLDB_OPT_SET_4, 1859*e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1860b842f2ecSJim Ingham m_option_group.Finalize(); 1861b842f2ecSJim Ingham } 1862b842f2ecSJim Ingham 1863b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1864b842f2ecSJim Ingham 1865b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1866b842f2ecSJim Ingham 1867b842f2ecSJim Ingham protected: 1868b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1869b842f2ecSJim Ingham 1870b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1871b842f2ecSJim Ingham if (argc == 0) { 1872b842f2ecSJim Ingham result.AppendError("No names provided."); 1873b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1874b842f2ecSJim Ingham return false; 1875b842f2ecSJim Ingham } 1876b842f2ecSJim Ingham 1877b842f2ecSJim Ingham Target *target = 1878b842f2ecSJim Ingham GetSelectedOrDummyTarget(false); 1879b842f2ecSJim Ingham 1880b842f2ecSJim Ingham if (target == nullptr) { 1881b842f2ecSJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 1882b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1883b842f2ecSJim Ingham return false; 1884b842f2ecSJim Ingham } 1885b842f2ecSJim Ingham 1886b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1887b842f2ecSJim Ingham target->GetBreakpointList().GetListMutex(lock); 1888b842f2ecSJim Ingham 1889b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1890b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1891b842f2ecSJim Ingham Status error; 1892b842f2ecSJim Ingham if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) 1893b842f2ecSJim Ingham { 1894b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1895b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1896b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1897b842f2ecSJim Ingham return false; 1898b842f2ecSJim Ingham } 1899b842f2ecSJim Ingham } 1900b842f2ecSJim Ingham // Now configure them, we already pre-checked the names so we don't need 1901b842f2ecSJim Ingham // to check the error: 1902b842f2ecSJim Ingham BreakpointSP bp_sp; 1903b842f2ecSJim Ingham if (m_bp_id.m_breakpoint.OptionWasSet()) 1904b842f2ecSJim Ingham { 1905b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1906b842f2ecSJim Ingham bp_sp = target->GetBreakpointByID(bp_id); 1907b842f2ecSJim Ingham if (!bp_sp) 1908b842f2ecSJim Ingham { 1909b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1910b842f2ecSJim Ingham bp_id); 1911b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1912b842f2ecSJim Ingham return false; 1913b842f2ecSJim Ingham } 1914b842f2ecSJim Ingham } 1915b842f2ecSJim Ingham 1916b842f2ecSJim Ingham Status error; 1917b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1918b842f2ecSJim Ingham ConstString name(entry.c_str()); 1919b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(name, true, error); 1920b842f2ecSJim Ingham if (!bp_name) 1921b842f2ecSJim Ingham continue; 1922*e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1923*e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1924*e9632ebaSJim Ingham 1925b842f2ecSJim Ingham if (bp_sp) 1926b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1927b842f2ecSJim Ingham *bp_sp->GetOptions(), 1928b842f2ecSJim Ingham m_access_options.GetPermissions()); 1929b842f2ecSJim Ingham else 1930b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1931b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1932b842f2ecSJim Ingham m_access_options.GetPermissions()); 1933b842f2ecSJim Ingham } 1934b842f2ecSJim Ingham return true; 1935b842f2ecSJim Ingham } 1936b842f2ecSJim Ingham 1937b842f2ecSJim Ingham private: 1938b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1939b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1940b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1941b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1942b842f2ecSJim Ingham }; 1943b842f2ecSJim Ingham 1944b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 19455e09c8c3SJim Ingham public: 1946b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1947b9c1b51eSKate Stone : CommandObjectParsed( 1948b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 19495e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 1950b9c1b51eSKate Stone m_name_options(), m_option_group() { 1951b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 1952b9c1b51eSKate Stone // command. 19535e09c8c3SJim Ingham CommandArgumentEntry arg1; 19545e09c8c3SJim Ingham CommandArgumentData id_arg; 19555e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 19565e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 19575e09c8c3SJim Ingham arg1.push_back(id_arg); 19585e09c8c3SJim Ingham m_arguments.push_back(arg1); 19595e09c8c3SJim Ingham 19605e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 19615e09c8c3SJim Ingham m_option_group.Finalize(); 19625e09c8c3SJim Ingham } 19635e09c8c3SJim Ingham 19649e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 19655e09c8c3SJim Ingham 1966b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 19675e09c8c3SJim Ingham 19685e09c8c3SJim Ingham protected: 1969b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1970b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 19715e09c8c3SJim Ingham result.SetError("No name option provided."); 19725e09c8c3SJim Ingham return false; 19735e09c8c3SJim Ingham } 19745e09c8c3SJim Ingham 1975b9c1b51eSKate Stone Target *target = 1976b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 19775e09c8c3SJim Ingham 1978b9c1b51eSKate Stone if (target == nullptr) { 19795e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 19805e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19815e09c8c3SJim Ingham return false; 19825e09c8c3SJim Ingham } 19835e09c8c3SJim Ingham 1984bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1985bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 19865e09c8c3SJim Ingham 19875e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 19885e09c8c3SJim Ingham 19895e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 1990b9c1b51eSKate Stone if (num_breakpoints == 0) { 19915e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 19925e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 19935e09c8c3SJim Ingham return false; 19945e09c8c3SJim Ingham } 19955e09c8c3SJim Ingham 19965e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 19975e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 1998b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1999b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2000b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 20015e09c8c3SJim Ingham 2002b9c1b51eSKate Stone if (result.Succeeded()) { 2003b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 20045e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 20055e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20065e09c8c3SJim Ingham return false; 20075e09c8c3SJim Ingham } 20085e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2009b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 2010b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 2011b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 2012b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2013b9c1b51eSKate Stone lldb::break_id_t bp_id = 2014b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 20155e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2016b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, bp_name, error); 20175e09c8c3SJim Ingham } 20185e09c8c3SJim Ingham } 20195e09c8c3SJim Ingham 20205e09c8c3SJim Ingham return true; 20215e09c8c3SJim Ingham } 20225e09c8c3SJim Ingham 20235e09c8c3SJim Ingham private: 20245e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20255e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20265e09c8c3SJim Ingham }; 20275e09c8c3SJim Ingham 2028b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 20295e09c8c3SJim Ingham public: 2030b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 2031b9c1b51eSKate Stone : CommandObjectParsed( 2032b9c1b51eSKate Stone interpreter, "delete", 20335e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 20345e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 2035b9c1b51eSKate Stone m_name_options(), m_option_group() { 2036b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 2037b9c1b51eSKate Stone // command. 20385e09c8c3SJim Ingham CommandArgumentEntry arg1; 20395e09c8c3SJim Ingham CommandArgumentData id_arg; 20405e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 20415e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 20425e09c8c3SJim Ingham arg1.push_back(id_arg); 20435e09c8c3SJim Ingham m_arguments.push_back(arg1); 20445e09c8c3SJim Ingham 20455e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 20465e09c8c3SJim Ingham m_option_group.Finalize(); 20475e09c8c3SJim Ingham } 20485e09c8c3SJim Ingham 20499e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 20505e09c8c3SJim Ingham 2051b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20525e09c8c3SJim Ingham 20535e09c8c3SJim Ingham protected: 2054b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2055b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 20565e09c8c3SJim Ingham result.SetError("No name option provided."); 20575e09c8c3SJim Ingham return false; 20585e09c8c3SJim Ingham } 20595e09c8c3SJim Ingham 2060b9c1b51eSKate Stone Target *target = 2061b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20625e09c8c3SJim Ingham 2063b9c1b51eSKate Stone if (target == nullptr) { 20645e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20655e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20665e09c8c3SJim Ingham return false; 20675e09c8c3SJim Ingham } 20685e09c8c3SJim Ingham 2069bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2070bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20715e09c8c3SJim Ingham 20725e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 20735e09c8c3SJim Ingham 20745e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 2075b9c1b51eSKate Stone if (num_breakpoints == 0) { 20765e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 20775e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20785e09c8c3SJim Ingham return false; 20795e09c8c3SJim Ingham } 20805e09c8c3SJim Ingham 20815e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 20825e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2083b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2084b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2085b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 20865e09c8c3SJim Ingham 2087b9c1b51eSKate Stone if (result.Succeeded()) { 2088b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 20895e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 20905e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20915e09c8c3SJim Ingham return false; 20925e09c8c3SJim Ingham } 2093b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 20945e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2095b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2096b9c1b51eSKate Stone lldb::break_id_t bp_id = 2097b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 20985e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2099b842f2ecSJim Ingham target->RemoveNameFromBreakpoint(bp_sp, bp_name); 21005e09c8c3SJim Ingham } 21015e09c8c3SJim Ingham } 21025e09c8c3SJim Ingham 21035e09c8c3SJim Ingham return true; 21045e09c8c3SJim Ingham } 21055e09c8c3SJim Ingham 21065e09c8c3SJim Ingham private: 21075e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 21085e09c8c3SJim Ingham OptionGroupOptions m_option_group; 21095e09c8c3SJim Ingham }; 21105e09c8c3SJim Ingham 2111b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 21125e09c8c3SJim Ingham public: 2113b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2114b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 2115b842f2ecSJim Ingham "List either the names for a breakpoint or info " 2116b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 2117b842f2ecSJim Ingham "names", 21185e09c8c3SJim Ingham "breakpoint name list <command-options>"), 2119b9c1b51eSKate Stone m_name_options(), m_option_group() { 2120b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 21215e09c8c3SJim Ingham m_option_group.Finalize(); 21225e09c8c3SJim Ingham } 21235e09c8c3SJim Ingham 21249e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 21255e09c8c3SJim Ingham 2126b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 21275e09c8c3SJim Ingham 21285e09c8c3SJim Ingham protected: 2129b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2130b9c1b51eSKate Stone Target *target = 2131b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 21325e09c8c3SJim Ingham 2133b9c1b51eSKate Stone if (target == nullptr) { 21345e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 21355e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21365e09c8c3SJim Ingham return false; 21375e09c8c3SJim Ingham } 21385e09c8c3SJim Ingham 2139b842f2ecSJim Ingham 2140b842f2ecSJim Ingham std::vector<std::string> name_list; 2141b842f2ecSJim Ingham if (command.empty()) { 2142b842f2ecSJim Ingham target->GetBreakpointNames(name_list); 2143b842f2ecSJim Ingham } else { 2144b842f2ecSJim Ingham for (const Args::ArgEntry &arg : command) 2145b842f2ecSJim Ingham { 2146b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 2147b842f2ecSJim Ingham } 2148b842f2ecSJim Ingham } 2149b842f2ecSJim Ingham 2150b842f2ecSJim Ingham if (name_list.empty()) { 2151b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 2152b842f2ecSJim Ingham } else { 2153b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 2154b842f2ecSJim Ingham const char *name = name_str.c_str(); 2155b842f2ecSJim Ingham // First print out the options for the name: 2156b842f2ecSJim Ingham Status error; 2157b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), 2158b842f2ecSJim Ingham false, 2159b842f2ecSJim Ingham error); 2160b842f2ecSJim Ingham if (bp_name) 2161b842f2ecSJim Ingham { 2162b842f2ecSJim Ingham StreamString s; 2163b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 2164b842f2ecSJim Ingham if (bp_name->GetDescription(&s, eDescriptionLevelFull)) 2165b842f2ecSJim Ingham { 2166b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 2167b842f2ecSJim Ingham } 2168b842f2ecSJim Ingham 2169bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2170bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 21715e09c8c3SJim Ingham 21725e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2173b842f2ecSJim Ingham bool any_set = false; 2174b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2175b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 21765e09c8c3SJim Ingham StreamString s; 2177b842f2ecSJim Ingham any_set = true; 21785e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 21795e09c8c3SJim Ingham s.EOL(); 2180c156427dSZachary Turner result.AppendMessage(s.GetString()); 21815e09c8c3SJim Ingham } 21825e09c8c3SJim Ingham } 2183b842f2ecSJim Ingham if (!any_set) 2184b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2185b9c1b51eSKate Stone } else { 2186b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 21875e09c8c3SJim Ingham } 2188b842f2ecSJim Ingham } 21895e09c8c3SJim Ingham } 21905e09c8c3SJim Ingham return true; 21915e09c8c3SJim Ingham } 21925e09c8c3SJim Ingham 21935e09c8c3SJim Ingham private: 21945e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 21955e09c8c3SJim Ingham OptionGroupOptions m_option_group; 21965e09c8c3SJim Ingham }; 21975e09c8c3SJim Ingham 21985e09c8c3SJim Ingham //------------------------------------------------------------------------- 2199e14dc268SJim Ingham // CommandObjectBreakpointName 22005e09c8c3SJim Ingham //------------------------------------------------------------------------- 2201b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 22025e09c8c3SJim Ingham public: 22037428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2204b9c1b51eSKate Stone : CommandObjectMultiword( 2205b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2206b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2207b9c1b51eSKate Stone CommandObjectSP add_command_object( 2208b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2209b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2210b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2211b9c1b51eSKate Stone CommandObjectSP list_command_object( 2212b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2213b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2214b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 22155e09c8c3SJim Ingham 22165e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 22175e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 22185e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2219b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 22205e09c8c3SJim Ingham } 22215e09c8c3SJim Ingham 22229e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 22235e09c8c3SJim Ingham }; 22245e09c8c3SJim Ingham 22255e09c8c3SJim Ingham //------------------------------------------------------------------------- 2226e14dc268SJim Ingham // CommandObjectBreakpointRead 2227e14dc268SJim Ingham //------------------------------------------------------------------------- 22283acdf385SJim Ingham #pragma mark Read::CommandOptions 22291f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_read_options[] = { 22301f0f5b5bSZachary Turner // clang-format off 22311f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 22323acdf385SJim Ingham {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, 22331f0f5b5bSZachary Turner // clang-format on 22341f0f5b5bSZachary Turner }; 22351f0f5b5bSZachary Turner 22361f0f5b5bSZachary Turner #pragma mark Read 2237e14dc268SJim Ingham 2238e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2239e14dc268SJim Ingham public: 2240e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2241e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2242e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2243e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2244e14dc268SJim Ingham nullptr), 2245e14dc268SJim Ingham m_options() { 2246e14dc268SJim Ingham CommandArgumentEntry arg; 2247e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2248e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2249e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2250e14dc268SJim Ingham // arguments vector. 2251e14dc268SJim Ingham m_arguments.push_back(arg); 2252e14dc268SJim Ingham } 2253e14dc268SJim Ingham 2254e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2255e14dc268SJim Ingham 2256e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2257e14dc268SJim Ingham 2258e14dc268SJim Ingham class CommandOptions : public Options { 2259e14dc268SJim Ingham public: 2260e14dc268SJim Ingham CommandOptions() : Options() {} 2261e14dc268SJim Ingham 2262e14dc268SJim Ingham ~CommandOptions() override = default; 2263e14dc268SJim Ingham 226497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2265e14dc268SJim Ingham ExecutionContext *execution_context) override { 226697206d57SZachary Turner Status error; 2267e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2268e14dc268SJim Ingham 2269e14dc268SJim Ingham switch (short_option) { 2270e14dc268SJim Ingham case 'f': 2271e14dc268SJim Ingham m_filename.assign(option_arg); 2272e14dc268SJim Ingham break; 22733acdf385SJim Ingham case 'N': { 227497206d57SZachary Turner Status name_error; 22753acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 22763acdf385SJim Ingham name_error)) { 22773acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 22783acdf385SJim Ingham name_error.AsCString()); 22793acdf385SJim Ingham } 22803acdf385SJim Ingham m_names.push_back(option_arg); 22813acdf385SJim Ingham break; 22823acdf385SJim Ingham } 2283e14dc268SJim Ingham default: 2284e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2285e14dc268SJim Ingham short_option); 2286e14dc268SJim Ingham break; 2287e14dc268SJim Ingham } 2288e14dc268SJim Ingham 2289e14dc268SJim Ingham return error; 2290e14dc268SJim Ingham } 2291e14dc268SJim Ingham 2292e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2293e14dc268SJim Ingham m_filename.clear(); 22943acdf385SJim Ingham m_names.clear(); 2295e14dc268SJim Ingham } 2296e14dc268SJim Ingham 22971f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 229870602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 22991f0f5b5bSZachary Turner } 2300e14dc268SJim Ingham 2301e14dc268SJim Ingham // Instance variables to hold the values for command options. 2302e14dc268SJim Ingham 2303e14dc268SJim Ingham std::string m_filename; 23043acdf385SJim Ingham std::vector<std::string> m_names; 2305e14dc268SJim Ingham }; 2306e14dc268SJim Ingham 2307e14dc268SJim Ingham protected: 2308e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2309e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2310e14dc268SJim Ingham if (target == nullptr) { 2311e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2312e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2313e14dc268SJim Ingham return false; 2314e14dc268SJim Ingham } 2315e14dc268SJim Ingham 23163acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 23173acdf385SJim Ingham target->GetBreakpointList().GetListMutex(lock); 23183acdf385SJim Ingham 2319e14dc268SJim Ingham FileSpec input_spec(m_options.m_filename, true); 232001f16664SJim Ingham BreakpointIDList new_bps; 232197206d57SZachary Turner Status error = target->CreateBreakpointsFromFile( 232297206d57SZachary Turner input_spec, m_options.m_names, new_bps); 2323e14dc268SJim Ingham 2324e14dc268SJim Ingham if (!error.Success()) { 232501f16664SJim Ingham result.AppendError(error.AsCString()); 2326e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 232701f16664SJim Ingham return false; 2328e14dc268SJim Ingham } 23293acdf385SJim Ingham 23303acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 23313acdf385SJim Ingham 23323acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 23333acdf385SJim Ingham if (num_breakpoints == 0) { 23343acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 23353acdf385SJim Ingham } else { 23363acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 23373acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 23383acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 23393acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 23403acdf385SJim Ingham Breakpoint *bp = target->GetBreakpointList() 23413acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 23423acdf385SJim Ingham .get(); 23433acdf385SJim Ingham if (bp) 23443acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 23453acdf385SJim Ingham false); 23463acdf385SJim Ingham } 23473acdf385SJim Ingham } 2348e14dc268SJim Ingham return result.Succeeded(); 2349e14dc268SJim Ingham } 2350e14dc268SJim Ingham 2351e14dc268SJim Ingham private: 2352e14dc268SJim Ingham CommandOptions m_options; 2353e14dc268SJim Ingham }; 2354e14dc268SJim Ingham 2355e14dc268SJim Ingham //------------------------------------------------------------------------- 2356e14dc268SJim Ingham // CommandObjectBreakpointWrite 2357e14dc268SJim Ingham //------------------------------------------------------------------------- 23581f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 23591f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_write_options[] = { 23601f0f5b5bSZachary Turner // clang-format off 23611f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, 23622d3628e1SJim Ingham { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, 23631f0f5b5bSZachary Turner // clang-format on 23641f0f5b5bSZachary Turner }; 23651f0f5b5bSZachary Turner 23661f0f5b5bSZachary Turner #pragma mark Write 2367e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2368e14dc268SJim Ingham public: 2369e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2370e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2371e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2372e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2373e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2374e14dc268SJim Ingham nullptr), 2375e14dc268SJim Ingham m_options() { 2376e14dc268SJim Ingham CommandArgumentEntry arg; 2377e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2378e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2379e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2380e14dc268SJim Ingham // arguments vector. 2381e14dc268SJim Ingham m_arguments.push_back(arg); 2382e14dc268SJim Ingham } 2383e14dc268SJim Ingham 2384e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2385e14dc268SJim Ingham 2386e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2387e14dc268SJim Ingham 2388e14dc268SJim Ingham class CommandOptions : public Options { 2389e14dc268SJim Ingham public: 2390e14dc268SJim Ingham CommandOptions() : Options() {} 2391e14dc268SJim Ingham 2392e14dc268SJim Ingham ~CommandOptions() override = default; 2393e14dc268SJim Ingham 239497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2395e14dc268SJim Ingham ExecutionContext *execution_context) override { 239697206d57SZachary Turner Status error; 2397e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2398e14dc268SJim Ingham 2399e14dc268SJim Ingham switch (short_option) { 2400e14dc268SJim Ingham case 'f': 2401e14dc268SJim Ingham m_filename.assign(option_arg); 2402e14dc268SJim Ingham break; 24032d3628e1SJim Ingham case 'a': 24042d3628e1SJim Ingham m_append = true; 24052d3628e1SJim Ingham break; 2406e14dc268SJim Ingham default: 2407e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2408e14dc268SJim Ingham short_option); 2409e14dc268SJim Ingham break; 2410e14dc268SJim Ingham } 2411e14dc268SJim Ingham 2412e14dc268SJim Ingham return error; 2413e14dc268SJim Ingham } 2414e14dc268SJim Ingham 2415e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2416e14dc268SJim Ingham m_filename.clear(); 24172d3628e1SJim Ingham m_append = false; 2418e14dc268SJim Ingham } 2419e14dc268SJim Ingham 24201f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 242170602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 24221f0f5b5bSZachary Turner } 2423e14dc268SJim Ingham 2424e14dc268SJim Ingham // Instance variables to hold the values for command options. 2425e14dc268SJim Ingham 2426e14dc268SJim Ingham std::string m_filename; 24272d3628e1SJim Ingham bool m_append = false; 2428e14dc268SJim Ingham }; 2429e14dc268SJim Ingham 2430e14dc268SJim Ingham protected: 2431e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2432e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2433e14dc268SJim Ingham if (target == nullptr) { 2434e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2435e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2436e14dc268SJim Ingham return false; 2437e14dc268SJim Ingham } 2438e14dc268SJim Ingham 2439e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2440e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2441e14dc268SJim Ingham 2442e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 244311eb9c64SZachary Turner if (!command.empty()) { 2444e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2445b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2446b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2447e14dc268SJim Ingham 244801f16664SJim Ingham if (!result.Succeeded()) { 2449e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2450e14dc268SJim Ingham return false; 2451e14dc268SJim Ingham } 2452e14dc268SJim Ingham } 245397206d57SZachary Turner Status error = target->SerializeBreakpointsToFile( 2454771ef6d4SMalcolm Parsons FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append); 245501f16664SJim Ingham if (!error.Success()) { 245601f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 245701f16664SJim Ingham error.AsCString()); 245801f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2459e14dc268SJim Ingham } 2460e14dc268SJim Ingham return result.Succeeded(); 2461e14dc268SJim Ingham } 2462e14dc268SJim Ingham 2463e14dc268SJim Ingham private: 2464e14dc268SJim Ingham CommandOptions m_options; 2465e14dc268SJim Ingham }; 2466e14dc268SJim Ingham 2467e14dc268SJim Ingham //------------------------------------------------------------------------- 246830fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 246930fdc8d8SChris Lattner //------------------------------------------------------------------------- 2470ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 247130fdc8d8SChris Lattner 2472b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2473b9c1b51eSKate Stone CommandInterpreter &interpreter) 2474b9c1b51eSKate Stone : CommandObjectMultiword( 2475b9c1b51eSKate Stone interpreter, "breakpoint", 24767428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2477b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2478b9c1b51eSKate Stone CommandObjectSP list_command_object( 2479b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2480b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2481b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2482b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2483b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2484b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2485b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2486b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2487b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2488b9c1b51eSKate Stone CommandObjectSP set_command_object( 2489b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2490b9c1b51eSKate Stone CommandObjectSP command_command_object( 2491b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2492b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2493b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2494b9c1b51eSKate Stone CommandObjectSP name_command_object( 2495b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2496e14dc268SJim Ingham CommandObjectSP write_command_object( 2497e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2498e14dc268SJim Ingham CommandObjectSP read_command_object( 2499e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 250030fdc8d8SChris Lattner 2501b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 250230fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 250330fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2504b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2505b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2506ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2507b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2508b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 25095e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2510e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2511e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 251230fdc8d8SChris Lattner 251323f59509SGreg Clayton LoadSubCommand("list", list_command_object); 251423f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 251523f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 251623f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 251723f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 251823f59509SGreg Clayton LoadSubCommand("set", set_command_object); 251923f59509SGreg Clayton LoadSubCommand("command", command_command_object); 252023f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 25215e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2522e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2523e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 252430fdc8d8SChris Lattner } 252530fdc8d8SChris Lattner 25269e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 252730fdc8d8SChris Lattner 2528b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 25295e09c8c3SJim Ingham bool allow_locations, 25305e09c8c3SJim Ingham CommandReturnObject &result, 2531b842f2ecSJim Ingham BreakpointIDList *valid_ids, 2532b842f2ecSJim Ingham BreakpointName::Permissions 2533b842f2ecSJim Ingham ::PermissionKinds 2534b842f2ecSJim Ingham purpose) { 253530fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2536b9c1b51eSKate Stone // 2). the full breakpoint & location 2537b9c1b51eSKate Stone // canonical representation 2538b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2539b9c1b51eSKate Stone // representing a range (in which case there 2540b9c1b51eSKate Stone // had *better* be an entry both before & 2541b9c1b51eSKate Stone // after of one of the first two types. 25425e09c8c3SJim Ingham // 4). A breakpoint name 2543b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2544b9c1b51eSKate Stone // one.) 254530fdc8d8SChris Lattner 254630fdc8d8SChris Lattner Args temp_args; 254730fdc8d8SChris Lattner 254811eb9c64SZachary Turner if (args.empty()) { 2549b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2550b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2551b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 255236f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2553b9c1b51eSKate Stone } else { 2554b9c1b51eSKate Stone result.AppendError( 2555b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 255636f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 255736f3b369SJim Ingham } 255836f3b369SJim Ingham return; 255936f3b369SJim Ingham } 256036f3b369SJim Ingham 2561b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2562b9c1b51eSKate Stone // directly from the old ARGS to 2563b9c1b51eSKate Stone // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead 2564b9c1b51eSKate Stone // generate a list of strings for 2565b9c1b51eSKate Stone // all the breakpoint ids in the range, and shove all of those breakpoint id 2566b9c1b51eSKate Stone // strings into TEMP_ARGS. 256730fdc8d8SChris Lattner 2568b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2569b842f2ecSJim Ingham purpose, result, temp_args); 257030fdc8d8SChris Lattner 2571b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2572b9c1b51eSKate Stone // BreakpointIDList: 257330fdc8d8SChris Lattner 2574b9c1b51eSKate Stone valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), 2575b9c1b51eSKate Stone temp_args.GetArgumentCount(), result); 257630fdc8d8SChris Lattner 2577b9c1b51eSKate Stone // At this point, all of the breakpoint ids that the user passed in have been 2578b9c1b51eSKate Stone // converted to breakpoint IDs 257930fdc8d8SChris Lattner // and put into valid_ids. 258030fdc8d8SChris Lattner 2581b9c1b51eSKate Stone if (result.Succeeded()) { 2582b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 2583b9c1b51eSKate Stone // ids, go through our tentative list 2584b9c1b51eSKate Stone // of breakpoint id's and verify that they correspond to valid/currently set 2585b9c1b51eSKate Stone // breakpoints. 258630fdc8d8SChris Lattner 2587c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2588b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 258930fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2590b9c1b51eSKate Stone Breakpoint *breakpoint = 2591b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2592b9c1b51eSKate Stone if (breakpoint != nullptr) { 2593c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2594b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 259530fdc8d8SChris Lattner StreamString id_str; 2596b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2597b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2598c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2599b9c1b51eSKate Stone result.AppendErrorWithFormat( 2600b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 260130fdc8d8SChris Lattner id_str.GetData()); 260230fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 260330fdc8d8SChris Lattner } 2604b9c1b51eSKate Stone } else { 2605c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2606b9c1b51eSKate Stone result.AppendErrorWithFormat( 2607b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 26087428a18cSKate Stone cur_bp_id.GetBreakpointID()); 260930fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 261030fdc8d8SChris Lattner } 261130fdc8d8SChris Lattner } 261230fdc8d8SChris Lattner } 261330fdc8d8SChris Lattner } 2614