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" 2547cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 2632abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h" 275e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h" 285e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h" 29b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h" 300e0984eeSJim Ingham #include "lldb/Target/Language.h" 31b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h" 32b9c1b51eSKate Stone #include "lldb/Target/Target.h" 331b54c88cSJim Ingham #include "lldb/Target/Thread.h" 341b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h" 35bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 36bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 3730fdc8d8SChris Lattner 3830fdc8d8SChris Lattner using namespace lldb; 3930fdc8d8SChris Lattner using namespace lldb_private; 4030fdc8d8SChris Lattner 41b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp, 42b9c1b51eSKate Stone lldb::DescriptionLevel level) { 4330fdc8d8SChris Lattner s->IndentMore(); 4430fdc8d8SChris Lattner bp->GetDescription(s, level, true); 4530fdc8d8SChris Lattner s->IndentLess(); 4630fdc8d8SChris Lattner s->EOL(); 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 49b842f2ecSJim Ingham //------------------------------------------------------------------------- 50b842f2ecSJim Ingham // Modifiable Breakpoint Options 51b842f2ecSJim Ingham //------------------------------------------------------------------------- 52b842f2ecSJim Ingham #pragma mark Modify::CommandOptions 53b842f2ecSJim Ingham static OptionDefinition g_breakpoint_modify_options[] = { 54b842f2ecSJim Ingham // clang-format off 55b842f2ecSJim 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." }, 56b842f2ecSJim 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." }, 57b842f2ecSJim 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." }, 58b842f2ecSJim 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." }, 59b842f2ecSJim 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." }, 60b842f2ecSJim 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." }, 61b842f2ecSJim 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." }, 62b842f2ecSJim Ingham { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, 63b842f2ecSJim Ingham { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." }, 64b842f2ecSJim Ingham { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." }, 65b842f2ecSJim 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." }, 66b842f2ecSJim Ingham // clang-format on 67b842f2ecSJim Ingham }; 68b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup 69b842f2ecSJim Ingham { 70b842f2ecSJim Ingham public: 71b842f2ecSJim Ingham BreakpointOptionGroup() : 72b842f2ecSJim Ingham OptionGroup(), 73b842f2ecSJim Ingham m_bp_opts(false) {} 74b842f2ecSJim Ingham 75b842f2ecSJim Ingham ~BreakpointOptionGroup() override = default; 76b842f2ecSJim Ingham 77b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 78b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_modify_options); 79b842f2ecSJim Ingham } 80b842f2ecSJim Ingham 81b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 82b842f2ecSJim Ingham ExecutionContext *execution_context) override { 83b842f2ecSJim Ingham Status error; 84b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 85b842f2ecSJim Ingham 86b842f2ecSJim Ingham switch (short_option) { 87b842f2ecSJim Ingham case 'c': 8805097246SAdrian Prantl // Normally an empty breakpoint condition marks is as unset. But we need 8905097246SAdrian Prantl // to say it was passed in. 90b842f2ecSJim Ingham m_bp_opts.SetCondition(option_arg.str().c_str()); 91b842f2ecSJim Ingham m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition); 92b842f2ecSJim Ingham break; 93b842f2ecSJim Ingham case 'C': 94b842f2ecSJim Ingham m_commands.push_back(option_arg); 95b842f2ecSJim Ingham break; 96b842f2ecSJim Ingham case 'd': 97b842f2ecSJim Ingham m_bp_opts.SetEnabled(false); 98b842f2ecSJim Ingham break; 99b842f2ecSJim Ingham case 'e': 100b842f2ecSJim Ingham m_bp_opts.SetEnabled(true); 101b842f2ecSJim Ingham break; 102b842f2ecSJim Ingham case 'G': { 103b842f2ecSJim Ingham bool value, success; 10447cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 105b842f2ecSJim Ingham if (success) { 106b842f2ecSJim Ingham m_bp_opts.SetAutoContinue(value); 107b842f2ecSJim Ingham } else 108b842f2ecSJim Ingham error.SetErrorStringWithFormat( 109b842f2ecSJim Ingham "invalid boolean value '%s' passed for -G option", 110b842f2ecSJim Ingham option_arg.str().c_str()); 111b842f2ecSJim Ingham } 112b842f2ecSJim Ingham break; 113b842f2ecSJim Ingham case 'i': 114b842f2ecSJim Ingham { 115b842f2ecSJim Ingham uint32_t ignore_count; 116b842f2ecSJim Ingham if (option_arg.getAsInteger(0, ignore_count)) 117b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid ignore count '%s'", 118b842f2ecSJim Ingham option_arg.str().c_str()); 119b842f2ecSJim Ingham else 120b842f2ecSJim Ingham m_bp_opts.SetIgnoreCount(ignore_count); 121b842f2ecSJim Ingham } 122b842f2ecSJim Ingham break; 123b842f2ecSJim Ingham case 'o': { 124b842f2ecSJim Ingham bool value, success; 12547cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 126b842f2ecSJim Ingham if (success) { 127b842f2ecSJim Ingham m_bp_opts.SetOneShot(value); 128b842f2ecSJim Ingham } else 129b842f2ecSJim Ingham error.SetErrorStringWithFormat( 130b842f2ecSJim Ingham "invalid boolean value '%s' passed for -o option", 131b842f2ecSJim Ingham option_arg.str().c_str()); 132b842f2ecSJim Ingham } break; 133b842f2ecSJim Ingham case 't': 134b842f2ecSJim Ingham { 135b842f2ecSJim Ingham lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID; 136b842f2ecSJim Ingham if (option_arg[0] != '\0') { 137b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_id)) 138b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread id string '%s'", 139b842f2ecSJim Ingham option_arg.str().c_str()); 140b842f2ecSJim Ingham } 141b842f2ecSJim Ingham m_bp_opts.SetThreadID(thread_id); 142b842f2ecSJim Ingham } 143b842f2ecSJim Ingham break; 144b842f2ecSJim Ingham case 'T': 145b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str()); 146b842f2ecSJim Ingham break; 147b842f2ecSJim Ingham case 'q': 148b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str()); 149b842f2ecSJim Ingham break; 150b842f2ecSJim Ingham case 'x': 151b842f2ecSJim Ingham { 152b842f2ecSJim Ingham uint32_t thread_index = UINT32_MAX; 153b842f2ecSJim Ingham if (option_arg[0] != '\n') { 154b842f2ecSJim Ingham if (option_arg.getAsInteger(0, thread_index)) 155b842f2ecSJim Ingham error.SetErrorStringWithFormat("invalid thread index string '%s'", 156b842f2ecSJim Ingham option_arg.str().c_str()); 157b842f2ecSJim Ingham } 158b842f2ecSJim Ingham m_bp_opts.GetThreadSpec()->SetIndex(thread_index); 159b842f2ecSJim Ingham } 160b842f2ecSJim Ingham break; 161b842f2ecSJim Ingham default: 162b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 163b842f2ecSJim Ingham short_option); 164b842f2ecSJim Ingham break; 165b842f2ecSJim Ingham } 166b842f2ecSJim Ingham 167b842f2ecSJim Ingham return error; 168b842f2ecSJim Ingham } 169b842f2ecSJim Ingham 170b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 171b842f2ecSJim Ingham m_bp_opts.Clear(); 172b842f2ecSJim Ingham m_commands.clear(); 173b842f2ecSJim Ingham } 174b842f2ecSJim Ingham 175b842f2ecSJim Ingham Status OptionParsingFinished(ExecutionContext *execution_context) override { 176b842f2ecSJim Ingham if (!m_commands.empty()) 177b842f2ecSJim Ingham { 178b842f2ecSJim Ingham if (!m_commands.empty()) 179b842f2ecSJim Ingham { 180b842f2ecSJim Ingham auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); 181b842f2ecSJim Ingham 182b842f2ecSJim Ingham for (std::string &str : m_commands) 183b842f2ecSJim Ingham cmd_data->user_source.AppendString(str); 184b842f2ecSJim Ingham 185b842f2ecSJim Ingham cmd_data->stop_on_error = true; 186b842f2ecSJim Ingham m_bp_opts.SetCommandDataCallback(cmd_data); 187b842f2ecSJim Ingham } 188b842f2ecSJim Ingham } 189b842f2ecSJim Ingham return Status(); 190b842f2ecSJim Ingham } 191b842f2ecSJim Ingham 192b842f2ecSJim Ingham const BreakpointOptions &GetBreakpointOptions() 193b842f2ecSJim Ingham { 194b842f2ecSJim Ingham return m_bp_opts; 195b842f2ecSJim Ingham } 196b842f2ecSJim Ingham 197b842f2ecSJim Ingham std::vector<std::string> m_commands; 198b842f2ecSJim Ingham BreakpointOptions m_bp_opts; 199b842f2ecSJim Ingham 200b842f2ecSJim Ingham }; 201b842f2ecSJim Ingham static OptionDefinition g_breakpoint_dummy_options[] = { 202b842f2ecSJim Ingham // clang-format off 203b842f2ecSJim 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, " 204b842f2ecSJim Ingham "which prime new targets." }, 205b842f2ecSJim Ingham // clang-format on 206b842f2ecSJim Ingham }; 207b842f2ecSJim Ingham 208b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup 209b842f2ecSJim Ingham { 210b842f2ecSJim Ingham public: 211b842f2ecSJim Ingham BreakpointDummyOptionGroup() : 212b842f2ecSJim Ingham OptionGroup() {} 213b842f2ecSJim Ingham 214b842f2ecSJim Ingham ~BreakpointDummyOptionGroup() override = default; 215b842f2ecSJim Ingham 216b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 217b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_dummy_options); 218b842f2ecSJim Ingham } 219b842f2ecSJim Ingham 220b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 221b842f2ecSJim Ingham ExecutionContext *execution_context) override { 222b842f2ecSJim Ingham Status error; 223b842f2ecSJim Ingham const int short_option = g_breakpoint_modify_options[option_idx].short_option; 224b842f2ecSJim Ingham 225b842f2ecSJim Ingham switch (short_option) { 226b842f2ecSJim Ingham case 'D': 227b842f2ecSJim Ingham m_use_dummy = true; 228b842f2ecSJim Ingham break; 229b842f2ecSJim Ingham default: 230b842f2ecSJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 231b842f2ecSJim Ingham short_option); 232b842f2ecSJim Ingham break; 233b842f2ecSJim Ingham } 234b842f2ecSJim Ingham 235b842f2ecSJim Ingham return error; 236b842f2ecSJim Ingham } 237b842f2ecSJim Ingham 238b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 239b842f2ecSJim Ingham m_use_dummy = false; 240b842f2ecSJim Ingham } 241b842f2ecSJim Ingham 242b842f2ecSJim Ingham bool m_use_dummy; 243b842f2ecSJim Ingham 244b842f2ecSJim Ingham }; 245b842f2ecSJim Ingham 2461f0f5b5bSZachary Turner // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 2471f0f5b5bSZachary Turner // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 248*3815e702SJim Ingham #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10) 2491f0f5b5bSZachary Turner #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) 250*3815e702SJim Ingham #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10) 251*3815e702SJim Ingham #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2) 2521f0f5b5bSZachary Turner #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) 2531f0f5b5bSZachary Turner #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) 2541f0f5b5bSZachary Turner 2551f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_set_options[] = { 2561f0f5b5bSZachary Turner // clang-format off 2571f0f5b5bSZachary 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 " 2581f0f5b5bSZachary Turner "multiple times to specify multiple shared libraries." }, 2591f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, 2601f0f5b5bSZachary 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 " 2611f0f5b5bSZachary Turner "lldb only looks for files that are #included if they use the standard include " 2621f0f5b5bSZachary Turner "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " 2631f0f5b5bSZachary Turner "#included, set target.inline-breakpoint-strategy to \"always\"." }, 2641f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, 2651f0f5b5bSZachary Turner 26605097246SAdrian Prantl // Comment out this option for the moment, as we don't actually use it, but 26705097246SAdrian Prantl // will in the future. This way users won't see it, but the infrastructure is 26805097246SAdrian Prantl // left in place. 2691f0f5b5bSZachary Turner // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 2701f0f5b5bSZachary Turner // "Set the breakpoint by source location at this particular column."}, 2711f0f5b5bSZachary Turner 2721f0f5b5bSZachary 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 " 2731f0f5b5bSZachary Turner "a particular binary, then the address will be converted to a \"file\" " 2741f0f5b5bSZachary Turner "address, so that the breakpoint will track that binary+offset no matter where " 2751f0f5b5bSZachary Turner "the binary eventually loads. Alternately, if you also specify the module - " 2761f0f5b5bSZachary Turner "with the -s option - then the address will be treated as a file address in " 2771f0f5b5bSZachary Turner "that module, and resolved accordingly. Again, this will allow lldb to track " 2781f0f5b5bSZachary Turner "that offset on subsequent reloads. The module need not have been loaded at " 2791f0f5b5bSZachary Turner "the time you specify this breakpoint, and will get resolved when the module " 2801f0f5b5bSZachary Turner "is loaded." }, 2811f0f5b5bSZachary 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 " 2821f0f5b5bSZachary Turner "one breakpoint for multiple names" }, 2831f0f5b5bSZachary 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 " 2841f0f5b5bSZachary Turner "functions. Can be repeated multiple times." }, 2851f0f5b5bSZachary 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 " 2864e8be2c9SAdrian Prantl "namespaces and all arguments, and for Objective-C this means a full function " 2871f0f5b5bSZachary Turner "prototype with class and selector. Can be repeated multiple times to make " 2881f0f5b5bSZachary Turner "one breakpoint for multiple names." }, 2891f0f5b5bSZachary 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 " 2901f0f5b5bSZachary Turner "make one breakpoint for multiple Selectors." }, 2911f0f5b5bSZachary 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 " 2921f0f5b5bSZachary Turner "make one breakpoint for multiple methods." }, 2931f0f5b5bSZachary 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 " 2941f0f5b5bSZachary Turner "the function name(s)." }, 2951f0f5b5bSZachary 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 " 2961f0f5b5bSZachary Turner "ignored). Can be repeated multiple times to make one breakpoint for multiple " 2971f0f5b5bSZachary Turner "symbols." }, 2981f0f5b5bSZachary 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 " 2991f0f5b5bSZachary Turner "against the source text in a source file or files specified with the -f " 3001f0f5b5bSZachary Turner "option. The -f option can be specified more than once. If no source files " 3011f0f5b5bSZachary Turner "are specified, uses the current \"default source file\". If you want to " 3021f0f5b5bSZachary Turner "match against all source files, pass the \"--all-files\" option." }, 3031f0f5b5bSZachary Turner { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." }, 304*3815e702SJim Ingham { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, 305*3815e702SJim Ingham { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, 306*3815e702SJim Ingham { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, 3071f0f5b5bSZachary 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 " 3081f0f5b5bSZachary Turner "options, on throw but not catch.)" }, 3091f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, 3101f0f5b5bSZachary Turner { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, 3111f0f5b5bSZachary Turner 3121f0f5b5bSZachary Turner // Don't add this option till it actually does something useful... 3131f0f5b5bSZachary Turner // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 3141f0f5b5bSZachary 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" }, 3151f0f5b5bSZachary Turner 3161f0f5b5bSZachary 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 " 3171f0f5b5bSZachary Turner "(note: currently only implemented for setting breakpoints on identifiers). " 3181f0f5b5bSZachary Turner "If not set the target.language setting is used." }, 3191f0f5b5bSZachary 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. " 3201f0f5b5bSZachary Turner "If not set the target.skip-prologue setting is used." }, 3211f0f5b5bSZachary 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." }, 3221f0f5b5bSZachary 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. " 3231f0f5b5bSZachary Turner "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, 3241f0f5b5bSZachary 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 " 3251f0f5b5bSZachary Turner "setting is used." }, 3261f0f5b5bSZachary Turner // clang-format on 3271f0f5b5bSZachary Turner }; 3281f0f5b5bSZachary Turner 32930fdc8d8SChris Lattner //------------------------------------------------------------------------- 3305a988416SJim Ingham // CommandObjectBreakpointSet 33130fdc8d8SChris Lattner //------------------------------------------------------------------------- 33230fdc8d8SChris Lattner 333b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed { 3345a988416SJim Ingham public: 335b9c1b51eSKate Stone typedef enum BreakpointSetType { 3365a988416SJim Ingham eSetTypeInvalid, 3375a988416SJim Ingham eSetTypeFileAndLine, 3385a988416SJim Ingham eSetTypeAddress, 3395a988416SJim Ingham eSetTypeFunctionName, 3405a988416SJim Ingham eSetTypeFunctionRegexp, 3415a988416SJim Ingham eSetTypeSourceRegexp, 342*3815e702SJim Ingham eSetTypeException, 343*3815e702SJim Ingham eSetTypeScripted, 3445a988416SJim Ingham } BreakpointSetType; 3455a988416SJim Ingham 346b9c1b51eSKate Stone CommandObjectBreakpointSet(CommandInterpreter &interpreter) 347b9c1b51eSKate Stone : CommandObjectParsed( 348b9c1b51eSKate Stone interpreter, "breakpoint set", 3495a988416SJim Ingham "Sets a breakpoint or set of breakpoints in the executable.", 3505a988416SJim Ingham "breakpoint set <cmd-options>"), 351b842f2ecSJim Ingham m_bp_opts(), m_options() { 352b842f2ecSJim Ingham // We're picking up all the normal options, commands and disable. 353b842f2ecSJim Ingham m_all_options.Append(&m_bp_opts, 354b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, 355b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 356b842f2ecSJim Ingham m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 357b842f2ecSJim Ingham m_all_options.Append(&m_options); 358b842f2ecSJim Ingham m_all_options.Finalize(); 359b842f2ecSJim Ingham } 3605a988416SJim Ingham 3619e85e5a8SEugene Zelenko ~CommandObjectBreakpointSet() override = default; 3625a988416SJim Ingham 363b842f2ecSJim Ingham Options *GetOptions() override { return &m_all_options; } 3645a988416SJim Ingham 365b842f2ecSJim Ingham class CommandOptions : public OptionGroup { 3665a988416SJim Ingham public: 367b9c1b51eSKate Stone CommandOptions() 368b842f2ecSJim Ingham : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0), 369b9c1b51eSKate Stone m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone), 370b9c1b51eSKate Stone m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(), 371b9c1b51eSKate Stone m_catch_bp(false), m_throw_bp(true), m_hardware(false), 372a72b31c7SJim Ingham m_exception_language(eLanguageTypeUnknown), 37323b1decbSDawn Perchik m_language(lldb::eLanguageTypeUnknown), 374b842f2ecSJim Ingham m_skip_prologue(eLazyBoolCalculate), 375b9c1b51eSKate Stone m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {} 37630fdc8d8SChris Lattner 3779e85e5a8SEugene Zelenko ~CommandOptions() override = default; 37887df91b8SJim Ingham 37997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 380b9c1b51eSKate Stone ExecutionContext *execution_context) override { 38197206d57SZachary Turner Status error; 382b842f2ecSJim Ingham const int short_option = g_breakpoint_set_options[option_idx].short_option; 38330fdc8d8SChris Lattner 384b9c1b51eSKate Stone switch (short_option) { 385b9c1b51eSKate Stone case 'a': { 38647cbf4a0SPavel Labath m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg, 387e1cfbc79STodd Fiala LLDB_INVALID_ADDRESS, &error); 388b9c1b51eSKate Stone } break; 38930fdc8d8SChris Lattner 390e732052fSJim Ingham case 'A': 391e732052fSJim Ingham m_all_files = true; 392e732052fSJim Ingham break; 393e732052fSJim Ingham 394ca36cd16SJim Ingham case 'b': 395ca36cd16SJim Ingham m_func_names.push_back(option_arg); 396ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeBase; 397ca36cd16SJim Ingham break; 398ca36cd16SJim Ingham 399fe11483bSZachary Turner case 'C': 400fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_column)) 401b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid column number: %s", 402fe11483bSZachary Turner option_arg.str().c_str()); 40330fdc8d8SChris Lattner break; 4049e85e5a8SEugene Zelenko 405b9c1b51eSKate Stone case 'E': { 406fe11483bSZachary Turner LanguageType language = Language::GetLanguageTypeFromString(option_arg); 407fab10e89SJim Ingham 408b9c1b51eSKate Stone switch (language) { 409fab10e89SJim Ingham case eLanguageTypeC89: 410fab10e89SJim Ingham case eLanguageTypeC: 411fab10e89SJim Ingham case eLanguageTypeC99: 4121d0089faSBruce Mitchener case eLanguageTypeC11: 413a72b31c7SJim Ingham m_exception_language = eLanguageTypeC; 414fab10e89SJim Ingham break; 415fab10e89SJim Ingham case eLanguageTypeC_plus_plus: 4161d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_03: 4171d0089faSBruce Mitchener case eLanguageTypeC_plus_plus_11: 4182ba84a6aSBruce Mitchener case eLanguageTypeC_plus_plus_14: 419a72b31c7SJim Ingham m_exception_language = eLanguageTypeC_plus_plus; 420fab10e89SJim Ingham break; 421fab10e89SJim Ingham case eLanguageTypeObjC: 422a72b31c7SJim Ingham m_exception_language = eLanguageTypeObjC; 423fab10e89SJim Ingham break; 424fab10e89SJim Ingham case eLanguageTypeObjC_plus_plus: 425b9c1b51eSKate Stone error.SetErrorStringWithFormat( 426b9c1b51eSKate Stone "Set exception breakpoints separately for c++ and objective-c"); 427fab10e89SJim Ingham break; 428fab10e89SJim Ingham case eLanguageTypeUnknown: 429b9c1b51eSKate Stone error.SetErrorStringWithFormat( 430b9c1b51eSKate Stone "Unknown language type: '%s' for exception breakpoint", 431fe11483bSZachary Turner option_arg.str().c_str()); 432fab10e89SJim Ingham break; 433fab10e89SJim Ingham default: 434b9c1b51eSKate Stone error.SetErrorStringWithFormat( 435b9c1b51eSKate Stone "Unsupported language type: '%s' for exception breakpoint", 436fe11483bSZachary Turner option_arg.str().c_str()); 437fab10e89SJim Ingham } 438b9c1b51eSKate Stone } break; 439ca36cd16SJim Ingham 440ca36cd16SJim Ingham case 'f': 441ca36cd16SJim Ingham m_filenames.AppendIfUnique(FileSpec(option_arg, false)); 442fab10e89SJim Ingham break; 443ca36cd16SJim Ingham 444ca36cd16SJim Ingham case 'F': 445ca36cd16SJim Ingham m_func_names.push_back(option_arg); 446ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeFull; 447ca36cd16SJim Ingham break; 448ca36cd16SJim Ingham 449b9c1b51eSKate Stone case 'h': { 450fab10e89SJim Ingham bool success; 45147cbf4a0SPavel Labath m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 452fab10e89SJim Ingham if (!success) 453b9c1b51eSKate Stone error.SetErrorStringWithFormat( 454fe11483bSZachary Turner "Invalid boolean value for on-catch option: '%s'", 455fe11483bSZachary Turner option_arg.str().c_str()); 456b9c1b51eSKate Stone } break; 457eb023e75SGreg Clayton 458eb023e75SGreg Clayton case 'H': 459eb023e75SGreg Clayton m_hardware = true; 460eb023e75SGreg Clayton break; 461eb023e75SGreg Clayton 462*3815e702SJim Ingham case 'k': { 463*3815e702SJim Ingham if (m_current_key.empty()) 464*3815e702SJim Ingham m_current_key.assign(option_arg); 465*3815e702SJim Ingham else 466*3815e702SJim Ingham error.SetErrorStringWithFormat("Key: %s missing value.", 467*3815e702SJim Ingham m_current_key.c_str()); 468*3815e702SJim Ingham 469*3815e702SJim Ingham } break; 470b9c1b51eSKate Stone case 'K': { 471a8558b62SJim Ingham bool success; 472a8558b62SJim Ingham bool value; 47347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 474a8558b62SJim Ingham if (value) 475a8558b62SJim Ingham m_skip_prologue = eLazyBoolYes; 476a8558b62SJim Ingham else 477a8558b62SJim Ingham m_skip_prologue = eLazyBoolNo; 478a8558b62SJim Ingham 479a8558b62SJim Ingham if (!success) 480b9c1b51eSKate Stone error.SetErrorStringWithFormat( 481b9c1b51eSKate Stone "Invalid boolean value for skip prologue option: '%s'", 482fe11483bSZachary Turner option_arg.str().c_str()); 483b9c1b51eSKate Stone } break; 484ca36cd16SJim Ingham 485fe11483bSZachary Turner case 'l': 486fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_line_num)) 487b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid line number: %s.", 488fe11483bSZachary Turner option_arg.str().c_str()); 489ca36cd16SJim Ingham break; 490055ad9beSIlia K 49123b1decbSDawn Perchik case 'L': 492fe11483bSZachary Turner m_language = Language::GetLanguageTypeFromString(option_arg); 49323b1decbSDawn Perchik if (m_language == eLanguageTypeUnknown) 494b9c1b51eSKate Stone error.SetErrorStringWithFormat( 495fe11483bSZachary Turner "Unknown language type: '%s' for breakpoint", 496fe11483bSZachary Turner option_arg.str().c_str()); 49723b1decbSDawn Perchik break; 49823b1decbSDawn Perchik 499b9c1b51eSKate Stone case 'm': { 500055ad9beSIlia K bool success; 501055ad9beSIlia K bool value; 50247cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, true, &success); 503055ad9beSIlia K if (value) 504055ad9beSIlia K m_move_to_nearest_code = eLazyBoolYes; 505055ad9beSIlia K else 506055ad9beSIlia K m_move_to_nearest_code = eLazyBoolNo; 507055ad9beSIlia K 508055ad9beSIlia K if (!success) 509b9c1b51eSKate Stone error.SetErrorStringWithFormat( 510b9c1b51eSKate Stone "Invalid boolean value for move-to-nearest-code option: '%s'", 511fe11483bSZachary Turner option_arg.str().c_str()); 512055ad9beSIlia K break; 513055ad9beSIlia K } 514055ad9beSIlia K 515ca36cd16SJim Ingham case 'M': 516ca36cd16SJim Ingham m_func_names.push_back(option_arg); 517ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeMethod; 518ca36cd16SJim Ingham break; 519ca36cd16SJim Ingham 520ca36cd16SJim Ingham case 'n': 521ca36cd16SJim Ingham m_func_names.push_back(option_arg); 522ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeAuto; 523ca36cd16SJim Ingham break; 524ca36cd16SJim Ingham 5256fa7681bSZachary Turner case 'N': { 526fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error)) 5275e09c8c3SJim Ingham m_breakpoint_names.push_back(option_arg); 528ff9a91eaSJim Ingham else 529ff9a91eaSJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 530fe11483bSZachary Turner option_arg.str().c_str()); 5315e09c8c3SJim Ingham break; 5326fa7681bSZachary Turner } 5335e09c8c3SJim Ingham 534b9c1b51eSKate Stone case 'R': { 5352411167fSJim Ingham lldb::addr_t tmp_offset_addr; 53647cbf4a0SPavel Labath tmp_offset_addr = OptionArgParser::ToAddress(execution_context, 53747cbf4a0SPavel Labath option_arg, 0, &error); 5382411167fSJim Ingham if (error.Success()) 5392411167fSJim Ingham m_offset_addr = tmp_offset_addr; 540b9c1b51eSKate Stone } break; 5412411167fSJim Ingham 542a72b31c7SJim Ingham case 'O': 543fe11483bSZachary Turner m_exception_extra_args.AppendArgument("-O"); 544fe11483bSZachary Turner m_exception_extra_args.AppendArgument(option_arg); 545a72b31c7SJim Ingham break; 546a72b31c7SJim Ingham 547ca36cd16SJim Ingham case 'p': 548ca36cd16SJim Ingham m_source_text_regexp.assign(option_arg); 549ca36cd16SJim Ingham break; 550ca36cd16SJim Ingham 551*3815e702SJim Ingham case 'P': 552*3815e702SJim Ingham m_python_class.assign(option_arg); 553*3815e702SJim Ingham break; 554*3815e702SJim Ingham 555ca36cd16SJim Ingham case 'r': 556ca36cd16SJim Ingham m_func_regexp.assign(option_arg); 557ca36cd16SJim Ingham break; 558ca36cd16SJim Ingham 559ca36cd16SJim Ingham case 's': 560ca36cd16SJim Ingham m_modules.AppendIfUnique(FileSpec(option_arg, false)); 561ca36cd16SJim Ingham break; 562ca36cd16SJim Ingham 563ca36cd16SJim Ingham case 'S': 564ca36cd16SJim Ingham m_func_names.push_back(option_arg); 565ca36cd16SJim Ingham m_func_name_type_mask |= eFunctionNameTypeSelector; 566ca36cd16SJim Ingham break; 567ca36cd16SJim Ingham 568*3815e702SJim Ingham case 'v': { 569*3815e702SJim Ingham if (!m_current_key.empty()) { 570*3815e702SJim Ingham m_extra_args_sp->AddStringItem(m_current_key, option_arg); 571*3815e702SJim Ingham m_current_key.clear(); 572*3815e702SJim Ingham } 573*3815e702SJim Ingham else 574*3815e702SJim Ingham error.SetErrorStringWithFormat("Value \"%s\" missing matching key.", 575*3815e702SJim Ingham option_arg.str().c_str()); 576*3815e702SJim Ingham } break; 577*3815e702SJim Ingham 578b9c1b51eSKate Stone case 'w': { 579ca36cd16SJim Ingham bool success; 58047cbf4a0SPavel Labath m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); 581ca36cd16SJim Ingham if (!success) 582b9c1b51eSKate Stone error.SetErrorStringWithFormat( 583fe11483bSZachary Turner "Invalid boolean value for on-throw option: '%s'", 584fe11483bSZachary Turner option_arg.str().c_str()); 585b9c1b51eSKate Stone } break; 586ca36cd16SJim Ingham 58776bb8d67SJim Ingham case 'X': 58876bb8d67SJim Ingham m_source_regex_func_names.insert(option_arg); 58976bb8d67SJim Ingham break; 59076bb8d67SJim Ingham 59130fdc8d8SChris Lattner default: 592b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 593b9c1b51eSKate Stone short_option); 59430fdc8d8SChris Lattner break; 59530fdc8d8SChris Lattner } 59630fdc8d8SChris Lattner 59730fdc8d8SChris Lattner return error; 59830fdc8d8SChris Lattner } 5999e85e5a8SEugene Zelenko 600b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 60187df91b8SJim Ingham m_filenames.Clear(); 60230fdc8d8SChris Lattner m_line_num = 0; 60330fdc8d8SChris Lattner m_column = 0; 604fab10e89SJim Ingham m_func_names.clear(); 6051f746071SGreg Clayton m_func_name_type_mask = eFunctionNameTypeNone; 60630fdc8d8SChris Lattner m_func_regexp.clear(); 6071f746071SGreg Clayton m_source_text_regexp.clear(); 60887df91b8SJim Ingham m_modules.Clear(); 6091f746071SGreg Clayton m_load_addr = LLDB_INVALID_ADDRESS; 6102411167fSJim Ingham m_offset_addr = 0; 611fab10e89SJim Ingham m_catch_bp = false; 612fab10e89SJim Ingham m_throw_bp = true; 613eb023e75SGreg Clayton m_hardware = false; 614a72b31c7SJim Ingham m_exception_language = eLanguageTypeUnknown; 61523b1decbSDawn Perchik m_language = lldb::eLanguageTypeUnknown; 616a8558b62SJim Ingham m_skip_prologue = eLazyBoolCalculate; 6175e09c8c3SJim Ingham m_breakpoint_names.clear(); 618e732052fSJim Ingham m_all_files = false; 619a72b31c7SJim Ingham m_exception_extra_args.Clear(); 620055ad9beSIlia K m_move_to_nearest_code = eLazyBoolCalculate; 62176bb8d67SJim Ingham m_source_regex_func_names.clear(); 622*3815e702SJim Ingham m_python_class.clear(); 623*3815e702SJim Ingham m_extra_args_sp.reset(new StructuredData::Dictionary()); 624*3815e702SJim Ingham m_current_key.clear(); 62530fdc8d8SChris Lattner } 62630fdc8d8SChris Lattner 6271f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 62870602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_set_options); 6291f0f5b5bSZachary Turner } 63030fdc8d8SChris Lattner 6315a988416SJim Ingham // Instance variables to hold the values for command options. 632969795f1SJim Ingham 6335a988416SJim Ingham std::string m_condition; 6345a988416SJim Ingham FileSpecList m_filenames; 6355a988416SJim Ingham uint32_t m_line_num; 6365a988416SJim Ingham uint32_t m_column; 6375a988416SJim Ingham std::vector<std::string> m_func_names; 6385e09c8c3SJim Ingham std::vector<std::string> m_breakpoint_names; 6395a988416SJim Ingham uint32_t m_func_name_type_mask; 6405a988416SJim Ingham std::string m_func_regexp; 6415a988416SJim Ingham std::string m_source_text_regexp; 6425a988416SJim Ingham FileSpecList m_modules; 6435a988416SJim Ingham lldb::addr_t m_load_addr; 6442411167fSJim Ingham lldb::addr_t m_offset_addr; 6455a988416SJim Ingham bool m_catch_bp; 6465a988416SJim Ingham bool m_throw_bp; 647eb023e75SGreg Clayton bool m_hardware; // Request to use hardware breakpoints 648a72b31c7SJim Ingham lldb::LanguageType m_exception_language; 64923b1decbSDawn Perchik lldb::LanguageType m_language; 6505a988416SJim Ingham LazyBool m_skip_prologue; 651e732052fSJim Ingham bool m_all_files; 652a72b31c7SJim Ingham Args m_exception_extra_args; 653055ad9beSIlia K LazyBool m_move_to_nearest_code; 65476bb8d67SJim Ingham std::unordered_set<std::string> m_source_regex_func_names; 655*3815e702SJim Ingham std::string m_python_class; 656*3815e702SJim Ingham StructuredData::DictionarySP m_extra_args_sp; 657*3815e702SJim Ingham std::string m_current_key; 6585a988416SJim Ingham }; 6595a988416SJim Ingham 6605a988416SJim Ingham protected: 661b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 662b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); 66333df7cd3SJim Ingham 664b9c1b51eSKate Stone if (target == nullptr) { 665b9c1b51eSKate Stone result.AppendError("Invalid target. Must set target before setting " 666b9c1b51eSKate Stone "breakpoints (see 'target create' command)."); 66730fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 66830fdc8d8SChris Lattner return false; 66930fdc8d8SChris Lattner } 67030fdc8d8SChris Lattner 67130fdc8d8SChris Lattner // The following are the various types of breakpoints that could be set: 67230fdc8d8SChris Lattner // 1). -f -l -p [-s -g] (setting breakpoint by source location) 67330fdc8d8SChris Lattner // 2). -a [-s -g] (setting breakpoint by address) 67430fdc8d8SChris Lattner // 3). -n [-s -g] (setting breakpoint by function name) 675b9c1b51eSKate Stone // 4). -r [-s -g] (setting breakpoint by function name regular 676b9c1b51eSKate Stone // expression) 677b9c1b51eSKate Stone // 5). -p -f (setting a breakpoint by comparing a reg-exp 678b9c1b51eSKate Stone // to source text) 679b9c1b51eSKate Stone // 6). -E [-w -h] (setting a breakpoint for exceptions for a 680b9c1b51eSKate Stone // given language.) 68130fdc8d8SChris Lattner 68230fdc8d8SChris Lattner BreakpointSetType break_type = eSetTypeInvalid; 68330fdc8d8SChris Lattner 684*3815e702SJim Ingham if (!m_options.m_python_class.empty()) 685*3815e702SJim Ingham break_type = eSetTypeScripted; 686*3815e702SJim Ingham else if (m_options.m_line_num != 0) 68730fdc8d8SChris Lattner break_type = eSetTypeFileAndLine; 68830fdc8d8SChris Lattner else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 68930fdc8d8SChris Lattner break_type = eSetTypeAddress; 690fab10e89SJim Ingham else if (!m_options.m_func_names.empty()) 69130fdc8d8SChris Lattner break_type = eSetTypeFunctionName; 69230fdc8d8SChris Lattner else if (!m_options.m_func_regexp.empty()) 69330fdc8d8SChris Lattner break_type = eSetTypeFunctionRegexp; 694969795f1SJim Ingham else if (!m_options.m_source_text_regexp.empty()) 695969795f1SJim Ingham break_type = eSetTypeSourceRegexp; 696a72b31c7SJim Ingham else if (m_options.m_exception_language != eLanguageTypeUnknown) 697fab10e89SJim Ingham break_type = eSetTypeException; 69830fdc8d8SChris Lattner 699b842f2ecSJim Ingham BreakpointSP bp_sp = nullptr; 700274060b6SGreg Clayton FileSpec module_spec; 701a8558b62SJim Ingham const bool internal = false; 702a8558b62SJim Ingham 703b9c1b51eSKate Stone // If the user didn't specify skip-prologue, having an offset should turn 704b9c1b51eSKate Stone // that off. 705b9c1b51eSKate Stone if (m_options.m_offset_addr != 0 && 706b9c1b51eSKate Stone m_options.m_skip_prologue == eLazyBoolCalculate) 7072411167fSJim Ingham m_options.m_skip_prologue = eLazyBoolNo; 7082411167fSJim Ingham 709b9c1b51eSKate Stone switch (break_type) { 71030fdc8d8SChris Lattner case eSetTypeFileAndLine: // Breakpoint by source position 71130fdc8d8SChris Lattner { 71230fdc8d8SChris Lattner FileSpec file; 713c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 714b9c1b51eSKate Stone if (num_files == 0) { 715b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 71687df91b8SJim Ingham result.AppendError("No file supplied and no default file available."); 71787df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 71887df91b8SJim Ingham return false; 71987df91b8SJim Ingham } 720b9c1b51eSKate Stone } else if (num_files > 1) { 721b9c1b51eSKate Stone result.AppendError("Only one file at a time is allowed for file and " 722b9c1b51eSKate Stone "line breakpoints."); 72387df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 72487df91b8SJim Ingham return false; 725b9c1b51eSKate Stone } else 72687df91b8SJim Ingham file = m_options.m_filenames.GetFileSpecAtIndex(0); 72730fdc8d8SChris Lattner 7281f746071SGreg Clayton // Only check for inline functions if 7291f746071SGreg Clayton LazyBool check_inlines = eLazyBoolCalculate; 7301f746071SGreg Clayton 731b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 732b842f2ecSJim Ingham file, 733b842f2ecSJim Ingham m_options.m_line_num, 734431b1584SAdrian Prantl m_options.m_column, 735b842f2ecSJim Ingham m_options.m_offset_addr, 736b842f2ecSJim Ingham check_inlines, 737b842f2ecSJim Ingham m_options.m_skip_prologue, 738b842f2ecSJim Ingham internal, 739b842f2ecSJim Ingham m_options.m_hardware, 740b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 741b9c1b51eSKate Stone } break; 7426eee5aa0SGreg Clayton 74330fdc8d8SChris Lattner case eSetTypeAddress: // Breakpoint by address 744055a08a4SJim Ingham { 745b9c1b51eSKate Stone // If a shared library has been specified, make an lldb_private::Address 746b842f2ecSJim Ingham // with the library, and use that. That way the address breakpoint 747b842f2ecSJim Ingham // will track the load location of the library. 748055a08a4SJim Ingham size_t num_modules_specified = m_options.m_modules.GetSize(); 749b9c1b51eSKate Stone if (num_modules_specified == 1) { 750b9c1b51eSKate Stone const FileSpec *file_spec = 751b9c1b51eSKate Stone m_options.m_modules.GetFileSpecPointerAtIndex(0); 752b842f2ecSJim Ingham bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, 753b9c1b51eSKate Stone internal, file_spec, 754b842f2ecSJim Ingham m_options.m_hardware); 755b9c1b51eSKate Stone } else if (num_modules_specified == 0) { 756b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, 757b842f2ecSJim Ingham m_options.m_hardware); 758b9c1b51eSKate Stone } else { 759b9c1b51eSKate Stone result.AppendError("Only one shared library can be specified for " 760b9c1b51eSKate Stone "address breakpoints."); 761055a08a4SJim Ingham result.SetStatus(eReturnStatusFailed); 762055a08a4SJim Ingham return false; 763055a08a4SJim Ingham } 76430fdc8d8SChris Lattner break; 765055a08a4SJim Ingham } 76630fdc8d8SChris Lattner case eSetTypeFunctionName: // Breakpoint by function name 7670c5cd90dSGreg Clayton { 7680c5cd90dSGreg Clayton uint32_t name_type_mask = m_options.m_func_name_type_mask; 7690c5cd90dSGreg Clayton 7700c5cd90dSGreg Clayton if (name_type_mask == 0) 771e02b8504SGreg Clayton name_type_mask = eFunctionNameTypeAuto; 7720c5cd90dSGreg Clayton 773b842f2ecSJim Ingham bp_sp = target->CreateBreakpoint(&(m_options.m_modules), 774b842f2ecSJim Ingham &(m_options.m_filenames), 775b842f2ecSJim Ingham m_options.m_func_names, 776b842f2ecSJim Ingham name_type_mask, 777b842f2ecSJim Ingham m_options.m_language, 778b842f2ecSJim Ingham m_options.m_offset_addr, 779b842f2ecSJim Ingham m_options.m_skip_prologue, 780b842f2ecSJim Ingham internal, 781b842f2ecSJim Ingham m_options.m_hardware); 782b9c1b51eSKate Stone } break; 7830c5cd90dSGreg Clayton 784b9c1b51eSKate Stone case eSetTypeFunctionRegexp: // Breakpoint by regular expression function 785b9c1b51eSKate Stone // name 78630fdc8d8SChris Lattner { 78795eae423SZachary Turner RegularExpression regexp(m_options.m_func_regexp); 788b9c1b51eSKate Stone if (!regexp.IsValid()) { 789969795f1SJim Ingham char err_str[1024]; 790969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 791b9c1b51eSKate Stone result.AppendErrorWithFormat( 792b9c1b51eSKate Stone "Function name regular expression could not be compiled: \"%s\"", 793969795f1SJim Ingham err_str); 79430fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 795969795f1SJim Ingham return false; 79630fdc8d8SChris Lattner } 79787df91b8SJim Ingham 798b842f2ecSJim Ingham bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), 799b842f2ecSJim Ingham &(m_options.m_filenames), 800b842f2ecSJim Ingham regexp, 801b842f2ecSJim Ingham m_options.m_language, 802b842f2ecSJim Ingham m_options.m_skip_prologue, 803b842f2ecSJim Ingham internal, 804b842f2ecSJim Ingham m_options.m_hardware); 805e14dc268SJim Ingham } 806e14dc268SJim Ingham break; 807969795f1SJim Ingham case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 808969795f1SJim Ingham { 809c7bece56SGreg Clayton const size_t num_files = m_options.m_filenames.GetSize(); 81087df91b8SJim Ingham 811b9c1b51eSKate Stone if (num_files == 0 && !m_options.m_all_files) { 812969795f1SJim Ingham FileSpec file; 813b9c1b51eSKate Stone if (!GetDefaultFile(target, file, result)) { 814b9c1b51eSKate Stone result.AppendError( 815b9c1b51eSKate Stone "No files provided and could not find default file."); 81687df91b8SJim Ingham result.SetStatus(eReturnStatusFailed); 81787df91b8SJim Ingham return false; 818b9c1b51eSKate Stone } else { 81987df91b8SJim Ingham m_options.m_filenames.Append(file); 82087df91b8SJim Ingham } 82187df91b8SJim Ingham } 8220c5cd90dSGreg Clayton 82395eae423SZachary Turner RegularExpression regexp(m_options.m_source_text_regexp); 824b9c1b51eSKate Stone if (!regexp.IsValid()) { 825969795f1SJim Ingham char err_str[1024]; 826969795f1SJim Ingham regexp.GetErrorAsCString(err_str, sizeof(err_str)); 827b9c1b51eSKate Stone result.AppendErrorWithFormat( 828b9c1b51eSKate Stone "Source text regular expression could not be compiled: \"%s\"", 829969795f1SJim Ingham err_str); 830969795f1SJim Ingham result.SetStatus(eReturnStatusFailed); 831969795f1SJim Ingham return false; 832969795f1SJim Ingham } 833b842f2ecSJim Ingham bp_sp = 834b842f2ecSJim Ingham target->CreateSourceRegexBreakpoint(&(m_options.m_modules), 835b842f2ecSJim Ingham &(m_options.m_filenames), 836b842f2ecSJim Ingham m_options 837b842f2ecSJim Ingham .m_source_regex_func_names, 838b842f2ecSJim Ingham regexp, 839b842f2ecSJim Ingham internal, 840b842f2ecSJim Ingham m_options.m_hardware, 841b842f2ecSJim Ingham m_options.m_move_to_nearest_code); 842b9c1b51eSKate Stone } break; 843b9c1b51eSKate Stone case eSetTypeException: { 84497206d57SZachary Turner Status precond_error; 845b842f2ecSJim Ingham bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, 846b842f2ecSJim Ingham m_options.m_catch_bp, 847b842f2ecSJim Ingham m_options.m_throw_bp, 848b842f2ecSJim Ingham internal, 849b842f2ecSJim Ingham &m_options 850b842f2ecSJim Ingham .m_exception_extra_args, 851b842f2ecSJim Ingham &precond_error); 852b9c1b51eSKate Stone if (precond_error.Fail()) { 853b9c1b51eSKate Stone result.AppendErrorWithFormat( 854b9c1b51eSKate Stone "Error setting extra exception arguments: %s", 855a72b31c7SJim Ingham precond_error.AsCString()); 856b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 857a72b31c7SJim Ingham result.SetStatus(eReturnStatusFailed); 858a72b31c7SJim Ingham return false; 859a72b31c7SJim Ingham } 860b9c1b51eSKate Stone } break; 861*3815e702SJim Ingham case eSetTypeScripted: { 862*3815e702SJim Ingham 863*3815e702SJim Ingham Status error; 864*3815e702SJim Ingham bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, 865*3815e702SJim Ingham &(m_options.m_modules), 866*3815e702SJim Ingham &(m_options.m_filenames), 867*3815e702SJim Ingham false, 868*3815e702SJim Ingham m_options.m_hardware, 869*3815e702SJim Ingham m_options.m_extra_args_sp, 870*3815e702SJim Ingham &error); 871*3815e702SJim Ingham if (error.Fail()) { 872*3815e702SJim Ingham result.AppendErrorWithFormat( 873*3815e702SJim Ingham "Error setting extra exception arguments: %s", 874*3815e702SJim Ingham error.AsCString()); 875*3815e702SJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 876*3815e702SJim Ingham result.SetStatus(eReturnStatusFailed); 877*3815e702SJim Ingham return false; 878*3815e702SJim Ingham } 879*3815e702SJim Ingham } break; 88030fdc8d8SChris Lattner default: 88130fdc8d8SChris Lattner break; 88230fdc8d8SChris Lattner } 88330fdc8d8SChris Lattner 8841b54c88cSJim Ingham // Now set the various options that were passed in: 885b842f2ecSJim Ingham if (bp_sp) { 886b842f2ecSJim Ingham bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 887ca36cd16SJim Ingham 888b9c1b51eSKate Stone if (!m_options.m_breakpoint_names.empty()) { 88997206d57SZachary Turner Status name_error; 890ff9a91eaSJim Ingham for (auto name : m_options.m_breakpoint_names) { 891b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 892ff9a91eaSJim Ingham if (name_error.Fail()) { 893ff9a91eaSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s", 894ff9a91eaSJim Ingham name.c_str()); 895b842f2ecSJim Ingham target->RemoveBreakpointByID(bp_sp->GetID()); 896ff9a91eaSJim Ingham result.SetStatus(eReturnStatusFailed); 897ff9a91eaSJim Ingham return false; 898ff9a91eaSJim Ingham } 899ff9a91eaSJim Ingham } 9005e09c8c3SJim Ingham } 9011b54c88cSJim Ingham } 9021b54c88cSJim Ingham 903b842f2ecSJim Ingham if (bp_sp) { 90485e8b814SJim Ingham Stream &output_stream = result.GetOutputStream(); 9051391cc7dSJim Ingham const bool show_locations = false; 906b842f2ecSJim Ingham bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 907b9c1b51eSKate Stone show_locations); 9084aeb1989SJim Ingham if (target == m_interpreter.GetDebugger().GetDummyTarget()) 909b9c1b51eSKate Stone output_stream.Printf("Breakpoint set in dummy target, will get copied " 910b9c1b51eSKate Stone "into future targets.\n"); 911b9c1b51eSKate Stone else { 91205097246SAdrian Prantl // Don't print out this warning for exception breakpoints. They can 91305097246SAdrian Prantl // get set before the target is set, but we won't know how to actually 91405097246SAdrian Prantl // set the breakpoint till we run. 915b842f2ecSJim Ingham if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 916b9c1b51eSKate Stone output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 917b9c1b51eSKate Stone "actual locations.\n"); 9184aeb1989SJim Ingham } 9194aeb1989SJim Ingham } 92030fdc8d8SChris Lattner result.SetStatus(eReturnStatusSuccessFinishResult); 921b842f2ecSJim Ingham } else if (!bp_sp) { 92230fdc8d8SChris Lattner result.AppendError("Breakpoint creation failed: No breakpoint created."); 92330fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 92430fdc8d8SChris Lattner } 92530fdc8d8SChris Lattner 92630fdc8d8SChris Lattner return result.Succeeded(); 92730fdc8d8SChris Lattner } 92830fdc8d8SChris Lattner 9295a988416SJim Ingham private: 930b9c1b51eSKate Stone bool GetDefaultFile(Target *target, FileSpec &file, 931b9c1b51eSKate Stone CommandReturnObject &result) { 9325a988416SJim Ingham uint32_t default_line; 93305097246SAdrian Prantl // First use the Source Manager's default file. Then use the current stack 93405097246SAdrian Prantl // frame's file. 935b9c1b51eSKate Stone if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 936b57e4a1bSJason Molenda StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 937b9c1b51eSKate Stone if (cur_frame == nullptr) { 938b9c1b51eSKate Stone result.AppendError( 939b9c1b51eSKate Stone "No selected frame to use to find the default file."); 9405a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9415a988416SJim Ingham return false; 942b9c1b51eSKate Stone } else if (!cur_frame->HasDebugInformation()) { 943b9c1b51eSKate Stone result.AppendError("Cannot use the selected frame to find the default " 944b9c1b51eSKate Stone "file, it has no debug info."); 9455a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9465a988416SJim Ingham return false; 947b9c1b51eSKate Stone } else { 948b9c1b51eSKate Stone const SymbolContext &sc = 949b9c1b51eSKate Stone cur_frame->GetSymbolContext(eSymbolContextLineEntry); 950b9c1b51eSKate Stone if (sc.line_entry.file) { 9515a988416SJim Ingham file = sc.line_entry.file; 952b9c1b51eSKate Stone } else { 953b9c1b51eSKate Stone result.AppendError("Can't find the file for the selected frame to " 954b9c1b51eSKate Stone "use as the default file."); 9555a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 9565a988416SJim Ingham return false; 9575a988416SJim Ingham } 9585a988416SJim Ingham } 9595a988416SJim Ingham } 9605a988416SJim Ingham return true; 9615a988416SJim Ingham } 9625a988416SJim Ingham 963b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 964b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_options; 9655a988416SJim Ingham CommandOptions m_options; 966b842f2ecSJim Ingham OptionGroupOptions m_all_options; 9675a988416SJim Ingham }; 9689e85e5a8SEugene Zelenko 9695a988416SJim Ingham //------------------------------------------------------------------------- 9705a988416SJim Ingham // CommandObjectBreakpointModify 9715a988416SJim Ingham //------------------------------------------------------------------------- 9725a988416SJim Ingham #pragma mark Modify 9735a988416SJim Ingham 974b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed { 9755a988416SJim Ingham public: 976b9c1b51eSKate Stone CommandObjectBreakpointModify(CommandInterpreter &interpreter) 977b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint modify", 978b9c1b51eSKate Stone "Modify the options on a breakpoint or set of " 979b9c1b51eSKate Stone "breakpoints in the executable. " 980b9c1b51eSKate Stone "If no breakpoint is specified, acts on the last " 981b9c1b51eSKate Stone "created breakpoint. " 982b9c1b51eSKate Stone "With the exception of -e, -d and -i, passing an " 983b9c1b51eSKate Stone "empty argument clears the modification.", 9849e85e5a8SEugene Zelenko nullptr), 985b9c1b51eSKate Stone m_options() { 9865a988416SJim Ingham CommandArgumentEntry arg; 987b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 988b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 989b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 990b9c1b51eSKate Stone // arguments vector. 9915a988416SJim Ingham m_arguments.push_back(arg); 992b842f2ecSJim Ingham 993b842f2ecSJim Ingham m_options.Append(&m_bp_opts, 994b842f2ecSJim Ingham LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 995b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 996b842f2ecSJim Ingham m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 997b842f2ecSJim Ingham m_options.Finalize(); 9985a988416SJim Ingham } 9995a988416SJim Ingham 10009e85e5a8SEugene Zelenko ~CommandObjectBreakpointModify() override = default; 10015a988416SJim Ingham 1002b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 10035a988416SJim Ingham 10045a988416SJim Ingham protected: 1005b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1006b842f2ecSJim Ingham Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 1007b9c1b51eSKate Stone if (target == nullptr) { 10085a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10095a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10105a988416SJim Ingham return false; 10115a988416SJim Ingham } 10125a988416SJim Ingham 1013bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1014bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10155a988416SJim Ingham 10165a988416SJim Ingham BreakpointIDList valid_bp_ids; 10175a988416SJim Ingham 1018b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1019b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1020b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 10215a988416SJim Ingham 1022b9c1b51eSKate Stone if (result.Succeeded()) { 10235a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1024b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 10255a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 10265a988416SJim Ingham 1027b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1028b9c1b51eSKate Stone Breakpoint *bp = 1029b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1030b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1031b9c1b51eSKate Stone BreakpointLocation *location = 1032b9c1b51eSKate Stone bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1033b842f2ecSJim Ingham if (location) 1034b842f2ecSJim Ingham location->GetLocationOptions() 1035b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 1036b9c1b51eSKate Stone } else { 1037b842f2ecSJim Ingham bp->GetOptions() 1038b842f2ecSJim Ingham ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 10395a988416SJim Ingham } 10405a988416SJim Ingham } 10415a988416SJim Ingham } 10425a988416SJim Ingham } 10435a988416SJim Ingham 10445a988416SJim Ingham return result.Succeeded(); 10455a988416SJim Ingham } 10465a988416SJim Ingham 10475a988416SJim Ingham private: 1048b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1049b842f2ecSJim Ingham BreakpointDummyOptionGroup m_dummy_opts; 1050b842f2ecSJim Ingham OptionGroupOptions m_options; 10515a988416SJim Ingham }; 10525a988416SJim Ingham 10535a988416SJim Ingham //------------------------------------------------------------------------- 10545a988416SJim Ingham // CommandObjectBreakpointEnable 10555a988416SJim Ingham //------------------------------------------------------------------------- 10565a988416SJim Ingham #pragma mark Enable 10575a988416SJim Ingham 1058b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed { 10595a988416SJim Ingham public: 1060b9c1b51eSKate Stone CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 1061b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "enable", 1062b9c1b51eSKate Stone "Enable the specified disabled breakpoint(s). If " 1063b9c1b51eSKate Stone "no breakpoints are specified, enable all of them.", 1064b9c1b51eSKate Stone nullptr) { 10655a988416SJim Ingham CommandArgumentEntry arg; 1066b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1067b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1068b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1069b9c1b51eSKate Stone // arguments vector. 10705a988416SJim Ingham m_arguments.push_back(arg); 10715a988416SJim Ingham } 10725a988416SJim Ingham 10739e85e5a8SEugene Zelenko ~CommandObjectBreakpointEnable() override = default; 10745a988416SJim Ingham 10755a988416SJim Ingham protected: 1076b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1077893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1078b9c1b51eSKate Stone if (target == nullptr) { 10795a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 10805a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10815a988416SJim Ingham return false; 10825a988416SJim Ingham } 10835a988416SJim Ingham 1084bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1085bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 10865a988416SJim Ingham 10875a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 10885a988416SJim Ingham 10895a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 10905a988416SJim Ingham 1091b9c1b51eSKate Stone if (num_breakpoints == 0) { 10925a988416SJim Ingham result.AppendError("No breakpoints exist to be enabled."); 10935a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 10945a988416SJim Ingham return false; 10955a988416SJim Ingham } 10965a988416SJim Ingham 109711eb9c64SZachary Turner if (command.empty()) { 10985a988416SJim Ingham // No breakpoint selected; enable all currently set breakpoints. 1099b842f2ecSJim Ingham target->EnableAllowedBreakpoints(); 1100b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 1101b9c1b51eSKate Stone " breakpoints)\n", 1102b9c1b51eSKate Stone (uint64_t)num_breakpoints); 11035a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1104b9c1b51eSKate Stone } else { 11055a988416SJim Ingham // Particular breakpoint selected; enable that breakpoint. 11065a988416SJim Ingham BreakpointIDList valid_bp_ids; 1107b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1108b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1109b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 11105a988416SJim Ingham 1111b9c1b51eSKate Stone if (result.Succeeded()) { 11125a988416SJim Ingham int enable_count = 0; 11135a988416SJim Ingham int loc_count = 0; 11145a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1115b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 11165a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 11175a988416SJim Ingham 1118b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1119b9c1b51eSKate Stone Breakpoint *breakpoint = 1120b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1121b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1122b9c1b51eSKate Stone BreakpointLocation *location = 1123b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1124b9c1b51eSKate Stone if (location) { 11255a988416SJim Ingham location->SetEnabled(true); 11265a988416SJim Ingham ++loc_count; 11275a988416SJim Ingham } 1128b9c1b51eSKate Stone } else { 11295a988416SJim Ingham breakpoint->SetEnabled(true); 11305a988416SJim Ingham ++enable_count; 11315a988416SJim Ingham } 11325a988416SJim Ingham } 11335a988416SJim Ingham } 1134b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1135b9c1b51eSKate Stone enable_count + loc_count); 11365a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 11375a988416SJim Ingham } 11385a988416SJim Ingham } 11395a988416SJim Ingham 11405a988416SJim Ingham return result.Succeeded(); 11415a988416SJim Ingham } 11425a988416SJim Ingham }; 11435a988416SJim Ingham 11445a988416SJim Ingham //------------------------------------------------------------------------- 11455a988416SJim Ingham // CommandObjectBreakpointDisable 11465a988416SJim Ingham //------------------------------------------------------------------------- 11475a988416SJim Ingham #pragma mark Disable 11485a988416SJim Ingham 1149b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed { 11505a988416SJim Ingham public: 11517428a18cSKate Stone CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1152b9c1b51eSKate Stone : CommandObjectParsed( 1153b9c1b51eSKate Stone interpreter, "breakpoint disable", 1154b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting " 11557428a18cSKate Stone "them. If none are specified, disable all " 11567428a18cSKate Stone "breakpoints.", 1157b9c1b51eSKate Stone nullptr) { 1158b9c1b51eSKate Stone SetHelpLong( 1159b9c1b51eSKate Stone "Disable the specified breakpoint(s) without deleting them. \ 11607428a18cSKate Stone If none are specified, disable all breakpoints." 11617428a18cSKate Stone R"( 1162ea671fbdSKate Stone 11637428a18cSKate Stone )" 11647428a18cSKate Stone "Note: disabling a breakpoint will cause none of its locations to be hit \ 11657428a18cSKate Stone regardless of whether individual locations are enabled or disabled. After the sequence:" 11667428a18cSKate Stone R"( 1167ea671fbdSKate Stone 1168ea671fbdSKate Stone (lldb) break disable 1 1169ea671fbdSKate Stone (lldb) break enable 1.1 1170ea671fbdSKate Stone 1171ea671fbdSKate Stone execution will NOT stop at location 1.1. To achieve that, type: 1172ea671fbdSKate Stone 1173ea671fbdSKate Stone (lldb) break disable 1.* 1174ea671fbdSKate Stone (lldb) break enable 1.1 1175ea671fbdSKate Stone 11767428a18cSKate Stone )" 11777428a18cSKate Stone "The first command disables all locations for breakpoint 1, \ 11787428a18cSKate Stone the second re-enables the first location."); 1179b0fac509SJim Ingham 11805a988416SJim Ingham CommandArgumentEntry arg; 1181b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1182b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1183b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1184b9c1b51eSKate Stone // arguments vector. 11855a988416SJim Ingham m_arguments.push_back(arg); 11865a988416SJim Ingham } 11875a988416SJim Ingham 11889e85e5a8SEugene Zelenko ~CommandObjectBreakpointDisable() override = default; 11895a988416SJim Ingham 11905a988416SJim Ingham protected: 1191b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1192893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1193b9c1b51eSKate Stone if (target == nullptr) { 11945a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 11955a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 11965a988416SJim Ingham return false; 11975a988416SJim Ingham } 11985a988416SJim Ingham 1199bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1200bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 12015a988416SJim Ingham 12025a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 12035a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 12045a988416SJim Ingham 1205b9c1b51eSKate Stone if (num_breakpoints == 0) { 12065a988416SJim Ingham result.AppendError("No breakpoints exist to be disabled."); 12075a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 12085a988416SJim Ingham return false; 12095a988416SJim Ingham } 12105a988416SJim Ingham 121111eb9c64SZachary Turner if (command.empty()) { 12125a988416SJim Ingham // No breakpoint selected; disable all currently set breakpoints. 1213b842f2ecSJim Ingham target->DisableAllowedBreakpoints(); 1214b9c1b51eSKate Stone result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1215b9c1b51eSKate Stone " breakpoints)\n", 1216b9c1b51eSKate Stone (uint64_t)num_breakpoints); 12175a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1218b9c1b51eSKate Stone } else { 12195a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 12205a988416SJim Ingham BreakpointIDList valid_bp_ids; 12215a988416SJim Ingham 1222b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1223b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1224b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::disablePerm); 12255a988416SJim Ingham 1226b9c1b51eSKate Stone if (result.Succeeded()) { 12275a988416SJim Ingham int disable_count = 0; 12285a988416SJim Ingham int loc_count = 0; 12295a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1230b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 12315a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 12325a988416SJim Ingham 1233b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1234b9c1b51eSKate Stone Breakpoint *breakpoint = 1235b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1236b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1237b9c1b51eSKate Stone BreakpointLocation *location = 1238b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1239b9c1b51eSKate Stone if (location) { 12405a988416SJim Ingham location->SetEnabled(false); 12415a988416SJim Ingham ++loc_count; 12425a988416SJim Ingham } 1243b9c1b51eSKate Stone } else { 12445a988416SJim Ingham breakpoint->SetEnabled(false); 12455a988416SJim Ingham ++disable_count; 12465a988416SJim Ingham } 12475a988416SJim Ingham } 12485a988416SJim Ingham } 1249b9c1b51eSKate Stone result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1250b9c1b51eSKate Stone disable_count + loc_count); 12515a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 12525a988416SJim Ingham } 12535a988416SJim Ingham } 12545a988416SJim Ingham 12555a988416SJim Ingham return result.Succeeded(); 12565a988416SJim Ingham } 12575a988416SJim Ingham }; 12585a988416SJim Ingham 12595a988416SJim Ingham //------------------------------------------------------------------------- 12605a988416SJim Ingham // CommandObjectBreakpointList 12615a988416SJim Ingham //------------------------------------------------------------------------- 12621f0f5b5bSZachary Turner 12631f0f5b5bSZachary Turner #pragma mark List::CommandOptions 12641f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_list_options[] = { 12651f0f5b5bSZachary Turner // clang-format off 12661f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" }, 12671f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." }, 12681f0f5b5bSZachary Turner // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 12691f0f5b5bSZachary Turner // But I need to see it for now, and don't want to wait. 12701f0f5b5bSZachary Turner { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." }, 12711f0f5b5bSZachary 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)." }, 12721f0f5b5bSZachary 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." }, 12731f0f5b5bSZachary Turner // clang-format on 12741f0f5b5bSZachary Turner }; 12751f0f5b5bSZachary Turner 12765a988416SJim Ingham #pragma mark List 12775a988416SJim Ingham 1278b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed { 12795a988416SJim Ingham public: 1280b9c1b51eSKate Stone CommandObjectBreakpointList(CommandInterpreter &interpreter) 1281b9c1b51eSKate Stone : CommandObjectParsed( 1282b9c1b51eSKate Stone interpreter, "breakpoint list", 12835a988416SJim Ingham "List some or all breakpoints at configurable levels of detail.", 12849e85e5a8SEugene Zelenko nullptr), 1285b9c1b51eSKate Stone m_options() { 12865a988416SJim Ingham CommandArgumentEntry arg; 12875a988416SJim Ingham CommandArgumentData bp_id_arg; 12885a988416SJim Ingham 12895a988416SJim Ingham // Define the first (and only) variant of this arg. 12905a988416SJim Ingham bp_id_arg.arg_type = eArgTypeBreakpointID; 12915a988416SJim Ingham bp_id_arg.arg_repetition = eArgRepeatOptional; 12925a988416SJim Ingham 1293b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1294b9c1b51eSKate Stone // argument entry. 12955a988416SJim Ingham arg.push_back(bp_id_arg); 12965a988416SJim Ingham 12975a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12985a988416SJim Ingham m_arguments.push_back(arg); 12995a988416SJim Ingham } 13005a988416SJim Ingham 13019e85e5a8SEugene Zelenko ~CommandObjectBreakpointList() override = default; 13025a988416SJim Ingham 1303b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13045a988416SJim Ingham 1305b9c1b51eSKate Stone class CommandOptions : public Options { 13065a988416SJim Ingham public: 1307b9c1b51eSKate Stone CommandOptions() 1308b9c1b51eSKate Stone : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 13095a988416SJim Ingham } 13105a988416SJim Ingham 13119e85e5a8SEugene Zelenko ~CommandOptions() override = default; 13125a988416SJim Ingham 131397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1314b9c1b51eSKate Stone ExecutionContext *execution_context) override { 131597206d57SZachary Turner Status error; 13163bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 13175a988416SJim Ingham 1318b9c1b51eSKate Stone switch (short_option) { 13195a988416SJim Ingham case 'b': 13205a988416SJim Ingham m_level = lldb::eDescriptionLevelBrief; 13215a988416SJim Ingham break; 132233df7cd3SJim Ingham case 'D': 132333df7cd3SJim Ingham m_use_dummy = true; 132433df7cd3SJim Ingham break; 13255a988416SJim Ingham case 'f': 13265a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13275a988416SJim Ingham break; 13285a988416SJim Ingham case 'v': 13295a988416SJim Ingham m_level = lldb::eDescriptionLevelVerbose; 13305a988416SJim Ingham break; 13315a988416SJim Ingham case 'i': 13325a988416SJim Ingham m_internal = true; 13335a988416SJim Ingham break; 13345a988416SJim Ingham default: 1335b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1336b9c1b51eSKate Stone short_option); 13375a988416SJim Ingham break; 13385a988416SJim Ingham } 13395a988416SJim Ingham 13405a988416SJim Ingham return error; 13415a988416SJim Ingham } 13425a988416SJim Ingham 1343b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 13445a988416SJim Ingham m_level = lldb::eDescriptionLevelFull; 13455a988416SJim Ingham m_internal = false; 134633df7cd3SJim Ingham m_use_dummy = false; 13475a988416SJim Ingham } 13485a988416SJim Ingham 13491f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 135070602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_list_options); 13511f0f5b5bSZachary Turner } 13525a988416SJim Ingham 13535a988416SJim Ingham // Instance variables to hold the values for command options. 13545a988416SJim Ingham 13555a988416SJim Ingham lldb::DescriptionLevel m_level; 13565a988416SJim Ingham 13575a988416SJim Ingham bool m_internal; 135833df7cd3SJim Ingham bool m_use_dummy; 13595a988416SJim Ingham }; 13605a988416SJim Ingham 13615a988416SJim Ingham protected: 1362b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 136333df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 136433df7cd3SJim Ingham 1365b9c1b51eSKate Stone if (target == nullptr) { 13665a988416SJim Ingham result.AppendError("Invalid target. No current target or breakpoints."); 13675a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13685a988416SJim Ingham return true; 13695a988416SJim Ingham } 13705a988416SJim Ingham 1371b9c1b51eSKate Stone const BreakpointList &breakpoints = 1372b9c1b51eSKate Stone target->GetBreakpointList(m_options.m_internal); 1373bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1374bb19a13cSSaleem Abdulrasool target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 13755a988416SJim Ingham 13765a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 13775a988416SJim Ingham 1378b9c1b51eSKate Stone if (num_breakpoints == 0) { 13795a988416SJim Ingham result.AppendMessage("No breakpoints currently set."); 13805a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 13815a988416SJim Ingham return true; 13825a988416SJim Ingham } 13835a988416SJim Ingham 13845a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 13855a988416SJim Ingham 138611eb9c64SZachary Turner if (command.empty()) { 13875a988416SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 13885a988416SJim Ingham result.AppendMessage("Current breakpoints:"); 1389b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 13905a988416SJim Ingham Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1391b842f2ecSJim Ingham if (breakpoint->AllowList()) 1392b842f2ecSJim Ingham AddBreakpointDescription(&output_stream, breakpoint, 1393b842f2ecSJim Ingham m_options.m_level); 13945a988416SJim Ingham } 13955a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1396b9c1b51eSKate Stone } else { 13975a988416SJim Ingham // Particular breakpoints selected; show info about that breakpoint. 13985a988416SJim Ingham BreakpointIDList valid_bp_ids; 1399b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1400b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1401b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 14025a988416SJim Ingham 1403b9c1b51eSKate Stone if (result.Succeeded()) { 1404b9c1b51eSKate Stone for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 14055a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1406b9c1b51eSKate Stone Breakpoint *breakpoint = 1407b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1408b9c1b51eSKate Stone AddBreakpointDescription(&output_stream, breakpoint, 1409b9c1b51eSKate Stone m_options.m_level); 14105a988416SJim Ingham } 14115a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1412b9c1b51eSKate Stone } else { 14137428a18cSKate Stone result.AppendError("Invalid breakpoint ID."); 14145a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 14155a988416SJim Ingham } 14165a988416SJim Ingham } 14175a988416SJim Ingham 14185a988416SJim Ingham return result.Succeeded(); 14195a988416SJim Ingham } 14205a988416SJim Ingham 14215a988416SJim Ingham private: 14225a988416SJim Ingham CommandOptions m_options; 14235a988416SJim Ingham }; 14245a988416SJim Ingham 14255a988416SJim Ingham //------------------------------------------------------------------------- 14265a988416SJim Ingham // CommandObjectBreakpointClear 14275a988416SJim Ingham //------------------------------------------------------------------------- 14281f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions 14291f0f5b5bSZachary Turner 14301f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_clear_options[] = { 14311f0f5b5bSZachary Turner // clang-format off 14321f0f5b5bSZachary 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." }, 14331f0f5b5bSZachary Turner { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } 14341f0f5b5bSZachary Turner // clang-format on 14351f0f5b5bSZachary Turner }; 14361f0f5b5bSZachary Turner 14375a988416SJim Ingham #pragma mark Clear 14385a988416SJim Ingham 1439b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed { 14405a988416SJim Ingham public: 1441b9c1b51eSKate Stone typedef enum BreakpointClearType { 14425a988416SJim Ingham eClearTypeInvalid, 14435a988416SJim Ingham eClearTypeFileAndLine 14445a988416SJim Ingham } BreakpointClearType; 14455a988416SJim Ingham 14467428a18cSKate Stone CommandObjectBreakpointClear(CommandInterpreter &interpreter) 14477428a18cSKate Stone : CommandObjectParsed(interpreter, "breakpoint clear", 1448b9c1b51eSKate Stone "Delete or disable breakpoints matching the " 1449b9c1b51eSKate Stone "specified source file and line.", 14505a988416SJim Ingham "breakpoint clear <cmd-options>"), 1451b9c1b51eSKate Stone m_options() {} 14525a988416SJim Ingham 14539e85e5a8SEugene Zelenko ~CommandObjectBreakpointClear() override = default; 14545a988416SJim Ingham 1455b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 14565a988416SJim Ingham 1457b9c1b51eSKate Stone class CommandOptions : public Options { 14585a988416SJim Ingham public: 1459b9c1b51eSKate Stone CommandOptions() : Options(), m_filename(), m_line_num(0) {} 14605a988416SJim Ingham 14619e85e5a8SEugene Zelenko ~CommandOptions() override = default; 14625a988416SJim Ingham 146397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1464b9c1b51eSKate Stone ExecutionContext *execution_context) override { 146597206d57SZachary Turner Status error; 14663bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 14675a988416SJim Ingham 1468b9c1b51eSKate Stone switch (short_option) { 14695a988416SJim Ingham case 'f': 14705a988416SJim Ingham m_filename.assign(option_arg); 14715a988416SJim Ingham break; 14725a988416SJim Ingham 14735a988416SJim Ingham case 'l': 1474fe11483bSZachary Turner option_arg.getAsInteger(0, m_line_num); 14755a988416SJim Ingham break; 14765a988416SJim Ingham 14775a988416SJim Ingham default: 1478b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1479b9c1b51eSKate Stone short_option); 14805a988416SJim Ingham break; 14815a988416SJim Ingham } 14825a988416SJim Ingham 14835a988416SJim Ingham return error; 14845a988416SJim Ingham } 14855a988416SJim Ingham 1486b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14875a988416SJim Ingham m_filename.clear(); 14885a988416SJim Ingham m_line_num = 0; 14895a988416SJim Ingham } 14905a988416SJim Ingham 14911f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 149270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_clear_options); 14931f0f5b5bSZachary Turner } 14945a988416SJim Ingham 14955a988416SJim Ingham // Instance variables to hold the values for command options. 14965a988416SJim Ingham 14975a988416SJim Ingham std::string m_filename; 14985a988416SJim Ingham uint32_t m_line_num; 14995a988416SJim Ingham }; 15005a988416SJim Ingham 15015a988416SJim Ingham protected: 1502b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1503893c932aSJim Ingham Target *target = GetSelectedOrDummyTarget(); 1504b9c1b51eSKate Stone if (target == nullptr) { 15055a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 15065a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15075a988416SJim Ingham return false; 15085a988416SJim Ingham } 15095a988416SJim Ingham 151005097246SAdrian Prantl // The following are the various types of breakpoints that could be 151105097246SAdrian Prantl // cleared: 15125a988416SJim Ingham // 1). -f -l (clearing breakpoint by source location) 15135a988416SJim Ingham 15145a988416SJim Ingham BreakpointClearType break_type = eClearTypeInvalid; 15155a988416SJim Ingham 15165a988416SJim Ingham if (m_options.m_line_num != 0) 15175a988416SJim Ingham break_type = eClearTypeFileAndLine; 15185a988416SJim Ingham 1519bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1520bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 15215a988416SJim Ingham 15225a988416SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 15235a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 15245a988416SJim Ingham 15255a988416SJim Ingham // Early return if there's no breakpoint at all. 1526b9c1b51eSKate Stone if (num_breakpoints == 0) { 15275a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15285a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15295a988416SJim Ingham return result.Succeeded(); 15305a988416SJim Ingham } 15315a988416SJim Ingham 15325a988416SJim Ingham // Find matching breakpoints and delete them. 15335a988416SJim Ingham 15345a988416SJim Ingham // First create a copy of all the IDs. 15355a988416SJim Ingham std::vector<break_id_t> BreakIDs; 15365a988416SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) 15379e85e5a8SEugene Zelenko BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 15385a988416SJim Ingham 15395a988416SJim Ingham int num_cleared = 0; 15405a988416SJim Ingham StreamString ss; 1541b9c1b51eSKate Stone switch (break_type) { 15425a988416SJim Ingham case eClearTypeFileAndLine: // Breakpoint by source position 15435a988416SJim Ingham { 15445a988416SJim Ingham const ConstString filename(m_options.m_filename.c_str()); 15455a988416SJim Ingham BreakpointLocationCollection loc_coll; 15465a988416SJim Ingham 1547b9c1b51eSKate Stone for (size_t i = 0; i < num_breakpoints; ++i) { 15485a988416SJim Ingham Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 15495a988416SJim Ingham 1550b9c1b51eSKate Stone if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1551b9c1b51eSKate Stone // If the collection size is 0, it's a full match and we can just 1552b9c1b51eSKate Stone // remove the breakpoint. 1553b9c1b51eSKate Stone if (loc_coll.GetSize() == 0) { 15545a988416SJim Ingham bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 15555a988416SJim Ingham ss.EOL(); 15565a988416SJim Ingham target->RemoveBreakpointByID(bp->GetID()); 15575a988416SJim Ingham ++num_cleared; 15585a988416SJim Ingham } 15595a988416SJim Ingham } 15605a988416SJim Ingham } 1561b9c1b51eSKate Stone } break; 15625a988416SJim Ingham 15635a988416SJim Ingham default: 15645a988416SJim Ingham break; 15655a988416SJim Ingham } 15665a988416SJim Ingham 1567b9c1b51eSKate Stone if (num_cleared > 0) { 15685a988416SJim Ingham Stream &output_stream = result.GetOutputStream(); 15695a988416SJim Ingham output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1570c156427dSZachary Turner output_stream << ss.GetString(); 15715a988416SJim Ingham output_stream.EOL(); 15725a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1573b9c1b51eSKate Stone } else { 15745a988416SJim Ingham result.AppendError("Breakpoint clear: No breakpoint cleared."); 15755a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 15765a988416SJim Ingham } 15775a988416SJim Ingham 15785a988416SJim Ingham return result.Succeeded(); 15795a988416SJim Ingham } 15805a988416SJim Ingham 15815a988416SJim Ingham private: 15825a988416SJim Ingham CommandOptions m_options; 15835a988416SJim Ingham }; 15845a988416SJim Ingham 15855a988416SJim Ingham //------------------------------------------------------------------------- 15865a988416SJim Ingham // CommandObjectBreakpointDelete 15875a988416SJim Ingham //------------------------------------------------------------------------- 15881f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_delete_options[] = { 15891f0f5b5bSZachary Turner // clang-format off 15901f0f5b5bSZachary Turner { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, 15911f0f5b5bSZachary 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." }, 15921f0f5b5bSZachary Turner // clang-format on 15931f0f5b5bSZachary Turner }; 15941f0f5b5bSZachary Turner 15955a988416SJim Ingham #pragma mark Delete 15965a988416SJim Ingham 1597b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed { 15985a988416SJim Ingham public: 1599b9c1b51eSKate Stone CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1600b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "breakpoint delete", 1601b9c1b51eSKate Stone "Delete the specified breakpoint(s). If no " 1602b9c1b51eSKate Stone "breakpoints are specified, delete them all.", 16039e85e5a8SEugene Zelenko nullptr), 1604b9c1b51eSKate Stone m_options() { 16055a988416SJim Ingham CommandArgumentEntry arg; 1606b9c1b51eSKate Stone CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1607b9c1b51eSKate Stone eArgTypeBreakpointIDRange); 1608b9c1b51eSKate Stone // Add the entry for the first argument for this command to the object's 1609b9c1b51eSKate Stone // arguments vector. 16105a988416SJim Ingham m_arguments.push_back(arg); 16115a988416SJim Ingham } 16125a988416SJim Ingham 16139e85e5a8SEugene Zelenko ~CommandObjectBreakpointDelete() override = default; 16145a988416SJim Ingham 1615b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 161633df7cd3SJim Ingham 1617b9c1b51eSKate Stone class CommandOptions : public Options { 161833df7cd3SJim Ingham public: 1619b9c1b51eSKate Stone CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 162033df7cd3SJim Ingham 16219e85e5a8SEugene Zelenko ~CommandOptions() override = default; 162233df7cd3SJim Ingham 162397206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1624b9c1b51eSKate Stone ExecutionContext *execution_context) override { 162597206d57SZachary Turner Status error; 162633df7cd3SJim Ingham const int short_option = m_getopt_table[option_idx].val; 162733df7cd3SJim Ingham 1628b9c1b51eSKate Stone switch (short_option) { 162933df7cd3SJim Ingham case 'f': 163033df7cd3SJim Ingham m_force = true; 163133df7cd3SJim Ingham break; 163233df7cd3SJim Ingham 163333df7cd3SJim Ingham case 'D': 163433df7cd3SJim Ingham m_use_dummy = true; 163533df7cd3SJim Ingham break; 163633df7cd3SJim Ingham 163733df7cd3SJim Ingham default: 1638b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized option '%c'", 1639b9c1b51eSKate Stone short_option); 164033df7cd3SJim Ingham break; 164133df7cd3SJim Ingham } 164233df7cd3SJim Ingham 164333df7cd3SJim Ingham return error; 164433df7cd3SJim Ingham } 164533df7cd3SJim Ingham 1646b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 164733df7cd3SJim Ingham m_use_dummy = false; 164833df7cd3SJim Ingham m_force = false; 164933df7cd3SJim Ingham } 165033df7cd3SJim Ingham 16511f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 165270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_delete_options); 16531f0f5b5bSZachary Turner } 165433df7cd3SJim Ingham 165533df7cd3SJim Ingham // Instance variables to hold the values for command options. 165633df7cd3SJim Ingham bool m_use_dummy; 165733df7cd3SJim Ingham bool m_force; 165833df7cd3SJim Ingham }; 165933df7cd3SJim Ingham 16605a988416SJim Ingham protected: 1661b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 166233df7cd3SJim Ingham Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 166333df7cd3SJim Ingham 1664b9c1b51eSKate Stone if (target == nullptr) { 16655a988416SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 16665a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16675a988416SJim Ingham return false; 16685a988416SJim Ingham } 16695a988416SJim Ingham 1670bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 1671bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 16725a988416SJim Ingham 16735a988416SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 16745a988416SJim Ingham 16755a988416SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 16765a988416SJim Ingham 1677b9c1b51eSKate Stone if (num_breakpoints == 0) { 16785a988416SJim Ingham result.AppendError("No breakpoints exist to be deleted."); 16795a988416SJim Ingham result.SetStatus(eReturnStatusFailed); 16805a988416SJim Ingham return false; 16815a988416SJim Ingham } 16825a988416SJim Ingham 168311eb9c64SZachary Turner if (command.empty()) { 1684b9c1b51eSKate Stone if (!m_options.m_force && 1685b9c1b51eSKate Stone !m_interpreter.Confirm( 1686b9c1b51eSKate Stone "About to delete all breakpoints, do you want to do that?", 1687b9c1b51eSKate Stone true)) { 16885a988416SJim Ingham result.AppendMessage("Operation cancelled..."); 1689b9c1b51eSKate Stone } else { 1690b842f2ecSJim Ingham target->RemoveAllowedBreakpoints(); 1691b9c1b51eSKate Stone result.AppendMessageWithFormat( 1692b9c1b51eSKate Stone "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1693b9c1b51eSKate Stone (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 16945a988416SJim Ingham } 16955a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 1696b9c1b51eSKate Stone } else { 16975a988416SJim Ingham // Particular breakpoint selected; disable that breakpoint. 16985a988416SJim Ingham BreakpointIDList valid_bp_ids; 1699b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1700b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 1701b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 17025a988416SJim Ingham 1703b9c1b51eSKate Stone if (result.Succeeded()) { 17045a988416SJim Ingham int delete_count = 0; 17055a988416SJim Ingham int disable_count = 0; 17065a988416SJim Ingham const size_t count = valid_bp_ids.GetSize(); 1707b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 17085a988416SJim Ingham BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 17095a988416SJim Ingham 1710b9c1b51eSKate Stone if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1711b9c1b51eSKate Stone if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1712b9c1b51eSKate Stone Breakpoint *breakpoint = 1713b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1714b9c1b51eSKate Stone BreakpointLocation *location = 1715b9c1b51eSKate Stone breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1716b9c1b51eSKate Stone // It makes no sense to try to delete individual locations, so we 1717b9c1b51eSKate Stone // disable them instead. 1718b9c1b51eSKate Stone if (location) { 17195a988416SJim Ingham location->SetEnabled(false); 17205a988416SJim Ingham ++disable_count; 17215a988416SJim Ingham } 1722b9c1b51eSKate Stone } else { 17235a988416SJim Ingham target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 17245a988416SJim Ingham ++delete_count; 17255a988416SJim Ingham } 17265a988416SJim Ingham } 17275a988416SJim Ingham } 1728b9c1b51eSKate Stone result.AppendMessageWithFormat( 1729b9c1b51eSKate Stone "%d breakpoints deleted; %d breakpoint locations disabled.\n", 17305a988416SJim Ingham delete_count, disable_count); 17315a988416SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 17325a988416SJim Ingham } 17335a988416SJim Ingham } 17345a988416SJim Ingham return result.Succeeded(); 17355a988416SJim Ingham } 17369e85e5a8SEugene Zelenko 173733df7cd3SJim Ingham private: 173833df7cd3SJim Ingham CommandOptions m_options; 173933df7cd3SJim Ingham }; 174033df7cd3SJim Ingham 174130fdc8d8SChris Lattner //------------------------------------------------------------------------- 17425e09c8c3SJim Ingham // CommandObjectBreakpointName 17435e09c8c3SJim Ingham //------------------------------------------------------------------------- 17445e09c8c3SJim Ingham 17457428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = { 1746ac9c3a62SKate Stone // clang-format off 1747ac9c3a62SKate Stone {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, 1748ac9c3a62SKate Stone {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 1749b842f2ecSJim 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."}, 1750e9632ebaSJim Ingham {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."}, 1751ac9c3a62SKate Stone // clang-format on 17525e09c8c3SJim Ingham }; 1753b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup { 17545e09c8c3SJim Ingham public: 1755b9c1b51eSKate Stone BreakpointNameOptionGroup() 1756b9c1b51eSKate Stone : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 17575e09c8c3SJim Ingham } 17585e09c8c3SJim Ingham 17599e85e5a8SEugene Zelenko ~BreakpointNameOptionGroup() override = default; 17605e09c8c3SJim Ingham 17611f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 176270602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_name_options); 17635e09c8c3SJim Ingham } 17645e09c8c3SJim Ingham 176597206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1766b9c1b51eSKate Stone ExecutionContext *execution_context) override { 176797206d57SZachary Turner Status error; 17685e09c8c3SJim Ingham const int short_option = g_breakpoint_name_options[option_idx].short_option; 17695e09c8c3SJim Ingham 1770b9c1b51eSKate Stone switch (short_option) { 17715e09c8c3SJim Ingham case 'N': 1772fe11483bSZachary Turner if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1773b9c1b51eSKate Stone error.Success()) 1774fe11483bSZachary Turner m_name.SetValueFromString(option_arg); 17755e09c8c3SJim Ingham break; 17765e09c8c3SJim Ingham case 'B': 1777fe11483bSZachary Turner if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1778b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17798cef4b0bSZachary Turner "unrecognized value \"%s\" for breakpoint", 1780fe11483bSZachary Turner option_arg.str().c_str()); 17815e09c8c3SJim Ingham break; 17825e09c8c3SJim Ingham case 'D': 1783fe11483bSZachary Turner if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1784b9c1b51eSKate Stone error.SetErrorStringWithFormat( 17858cef4b0bSZachary Turner "unrecognized value \"%s\" for use-dummy", 1786fe11483bSZachary Turner option_arg.str().c_str()); 17875e09c8c3SJim Ingham break; 1788e9632ebaSJim Ingham case 'H': 1789e9632ebaSJim Ingham m_help_string.SetValueFromString(option_arg); 1790e9632ebaSJim Ingham break; 17915e09c8c3SJim Ingham 17925e09c8c3SJim Ingham default: 1793b9c1b51eSKate Stone error.SetErrorStringWithFormat("unrecognized short option '%c'", 1794b9c1b51eSKate Stone short_option); 17955e09c8c3SJim Ingham break; 17965e09c8c3SJim Ingham } 17975e09c8c3SJim Ingham return error; 17985e09c8c3SJim Ingham } 17995e09c8c3SJim Ingham 1800b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 18015e09c8c3SJim Ingham m_name.Clear(); 18025e09c8c3SJim Ingham m_breakpoint.Clear(); 18035e09c8c3SJim Ingham m_use_dummy.Clear(); 18045e09c8c3SJim Ingham m_use_dummy.SetDefaultValue(false); 1805e9632ebaSJim Ingham m_help_string.Clear(); 18065e09c8c3SJim Ingham } 18075e09c8c3SJim Ingham 18085e09c8c3SJim Ingham OptionValueString m_name; 18095e09c8c3SJim Ingham OptionValueUInt64 m_breakpoint; 18105e09c8c3SJim Ingham OptionValueBoolean m_use_dummy; 1811e9632ebaSJim Ingham OptionValueString m_help_string; 18125e09c8c3SJim Ingham }; 18135e09c8c3SJim Ingham 1814b842f2ecSJim Ingham static OptionDefinition g_breakpoint_access_options[] = { 1815b842f2ecSJim Ingham // clang-format off 1816b842f2ecSJim 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."}, 1817b842f2ecSJim 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."}, 1818b842f2ecSJim 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."}, 1819b842f2ecSJim Ingham // clang-format on 1820b842f2ecSJim Ingham }; 1821b842f2ecSJim Ingham 1822b842f2ecSJim Ingham class BreakpointAccessOptionGroup : public OptionGroup 1823b842f2ecSJim Ingham { 1824b842f2ecSJim Ingham public: 1825b842f2ecSJim Ingham BreakpointAccessOptionGroup() : 1826b842f2ecSJim Ingham OptionGroup() 1827b842f2ecSJim Ingham {} 1828b842f2ecSJim Ingham 1829b842f2ecSJim Ingham ~BreakpointAccessOptionGroup() override = default; 1830b842f2ecSJim Ingham 1831b842f2ecSJim Ingham llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1832b842f2ecSJim Ingham return llvm::makeArrayRef(g_breakpoint_access_options); 1833b842f2ecSJim Ingham } 1834b842f2ecSJim Ingham Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1835b842f2ecSJim Ingham ExecutionContext *execution_context) override { 1836b842f2ecSJim Ingham Status error; 1837b842f2ecSJim Ingham const int short_option 1838b842f2ecSJim Ingham = g_breakpoint_access_options[option_idx].short_option; 1839b842f2ecSJim Ingham 1840b842f2ecSJim Ingham switch (short_option) { 1841b842f2ecSJim Ingham case 'L': { 1842b842f2ecSJim Ingham bool value, success; 184347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1844b842f2ecSJim Ingham if (success) { 1845b842f2ecSJim Ingham m_permissions.SetAllowList(value); 1846b842f2ecSJim Ingham } else 1847b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1848b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1849b842f2ecSJim Ingham option_arg.str().c_str()); 1850b842f2ecSJim Ingham } break; 1851b842f2ecSJim Ingham case 'A': { 1852b842f2ecSJim Ingham bool value, success; 185347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1854b842f2ecSJim Ingham if (success) { 1855b842f2ecSJim Ingham m_permissions.SetAllowDisable(value); 1856b842f2ecSJim Ingham } else 1857b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1858b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1859b842f2ecSJim Ingham option_arg.str().c_str()); 1860b842f2ecSJim Ingham } break; 1861b842f2ecSJim Ingham case 'D': { 1862b842f2ecSJim Ingham bool value, success; 186347cbf4a0SPavel Labath value = OptionArgParser::ToBoolean(option_arg, false, &success); 1864b842f2ecSJim Ingham if (success) { 1865b842f2ecSJim Ingham m_permissions.SetAllowDelete(value); 1866b842f2ecSJim Ingham } else 1867b842f2ecSJim Ingham error.SetErrorStringWithFormat( 1868b842f2ecSJim Ingham "invalid boolean value '%s' passed for -L option", 1869b842f2ecSJim Ingham option_arg.str().c_str()); 1870b842f2ecSJim Ingham } break; 1871b842f2ecSJim Ingham 1872b842f2ecSJim Ingham } 1873b842f2ecSJim Ingham 1874b842f2ecSJim Ingham return error; 1875b842f2ecSJim Ingham } 1876b842f2ecSJim Ingham 1877b842f2ecSJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 1878b842f2ecSJim Ingham } 1879b842f2ecSJim Ingham 1880b842f2ecSJim Ingham const BreakpointName::Permissions &GetPermissions() const 1881b842f2ecSJim Ingham { 1882b842f2ecSJim Ingham return m_permissions; 1883b842f2ecSJim Ingham } 1884b842f2ecSJim Ingham BreakpointName::Permissions m_permissions; 1885b842f2ecSJim Ingham }; 1886b842f2ecSJim Ingham 1887b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1888b842f2ecSJim Ingham public: 1889b842f2ecSJim Ingham CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1890b842f2ecSJim Ingham : CommandObjectParsed( 1891b842f2ecSJim Ingham interpreter, "configure", "Configure the options for the breakpoint" 1892b842f2ecSJim Ingham " name provided. " 1893b842f2ecSJim Ingham "If you provide a breakpoint id, the options will be copied from " 1894b842f2ecSJim Ingham "the breakpoint, otherwise only the options specified will be set " 1895b842f2ecSJim Ingham "on the name.", 1896b842f2ecSJim Ingham "breakpoint name configure <command-options> " 1897b842f2ecSJim Ingham "<breakpoint-name-list>"), 1898b842f2ecSJim Ingham m_bp_opts(), m_option_group() { 1899b842f2ecSJim Ingham // Create the first variant for the first (and only) argument for this 1900b842f2ecSJim Ingham // command. 1901b842f2ecSJim Ingham CommandArgumentEntry arg1; 1902b842f2ecSJim Ingham CommandArgumentData id_arg; 1903b842f2ecSJim Ingham id_arg.arg_type = eArgTypeBreakpointName; 1904b842f2ecSJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 1905b842f2ecSJim Ingham arg1.push_back(id_arg); 1906b842f2ecSJim Ingham m_arguments.push_back(arg1); 1907b842f2ecSJim Ingham 1908b842f2ecSJim Ingham m_option_group.Append(&m_bp_opts, 1909b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1910b842f2ecSJim Ingham LLDB_OPT_SET_1); 1911b842f2ecSJim Ingham m_option_group.Append(&m_access_options, 1912b842f2ecSJim Ingham LLDB_OPT_SET_ALL, 1913b842f2ecSJim Ingham LLDB_OPT_SET_ALL); 1914e9632ebaSJim Ingham m_option_group.Append(&m_bp_id, 1915e9632ebaSJim Ingham LLDB_OPT_SET_2|LLDB_OPT_SET_4, 1916e9632ebaSJim Ingham LLDB_OPT_SET_ALL); 1917b842f2ecSJim Ingham m_option_group.Finalize(); 1918b842f2ecSJim Ingham } 1919b842f2ecSJim Ingham 1920b842f2ecSJim Ingham ~CommandObjectBreakpointNameConfigure() override = default; 1921b842f2ecSJim Ingham 1922b842f2ecSJim Ingham Options *GetOptions() override { return &m_option_group; } 1923b842f2ecSJim Ingham 1924b842f2ecSJim Ingham protected: 1925b842f2ecSJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 1926b842f2ecSJim Ingham 1927b842f2ecSJim Ingham const size_t argc = command.GetArgumentCount(); 1928b842f2ecSJim Ingham if (argc == 0) { 1929b842f2ecSJim Ingham result.AppendError("No names provided."); 1930b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1931b842f2ecSJim Ingham return false; 1932b842f2ecSJim Ingham } 1933b842f2ecSJim Ingham 1934b842f2ecSJim Ingham Target *target = 1935b842f2ecSJim Ingham GetSelectedOrDummyTarget(false); 1936b842f2ecSJim Ingham 1937b842f2ecSJim Ingham if (target == nullptr) { 1938b842f2ecSJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 1939b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1940b842f2ecSJim Ingham return false; 1941b842f2ecSJim Ingham } 1942b842f2ecSJim Ingham 1943b842f2ecSJim Ingham std::unique_lock<std::recursive_mutex> lock; 1944b842f2ecSJim Ingham target->GetBreakpointList().GetListMutex(lock); 1945b842f2ecSJim Ingham 1946b842f2ecSJim Ingham // Make a pass through first to see that all the names are legal. 1947b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1948b842f2ecSJim Ingham Status error; 1949b842f2ecSJim Ingham if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) 1950b842f2ecSJim Ingham { 1951b842f2ecSJim Ingham result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1952b842f2ecSJim Ingham entry.c_str(), error.AsCString()); 1953b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1954b842f2ecSJim Ingham return false; 1955b842f2ecSJim Ingham } 1956b842f2ecSJim Ingham } 195705097246SAdrian Prantl // Now configure them, we already pre-checked the names so we don't need to 195805097246SAdrian Prantl // check the error: 1959b842f2ecSJim Ingham BreakpointSP bp_sp; 1960b842f2ecSJim Ingham if (m_bp_id.m_breakpoint.OptionWasSet()) 1961b842f2ecSJim Ingham { 1962b842f2ecSJim Ingham lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1963b842f2ecSJim Ingham bp_sp = target->GetBreakpointByID(bp_id); 1964b842f2ecSJim Ingham if (!bp_sp) 1965b842f2ecSJim Ingham { 1966b842f2ecSJim Ingham result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1967b842f2ecSJim Ingham bp_id); 1968b842f2ecSJim Ingham result.SetStatus(eReturnStatusFailed); 1969b842f2ecSJim Ingham return false; 1970b842f2ecSJim Ingham } 1971b842f2ecSJim Ingham } 1972b842f2ecSJim Ingham 1973b842f2ecSJim Ingham Status error; 1974b842f2ecSJim Ingham for (auto &entry : command.entries()) { 1975b842f2ecSJim Ingham ConstString name(entry.c_str()); 1976b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(name, true, error); 1977b842f2ecSJim Ingham if (!bp_name) 1978b842f2ecSJim Ingham continue; 1979e9632ebaSJim Ingham if (m_bp_id.m_help_string.OptionWasSet()) 1980e9632ebaSJim Ingham bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1981e9632ebaSJim Ingham 1982b842f2ecSJim Ingham if (bp_sp) 1983b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1984b842f2ecSJim Ingham *bp_sp->GetOptions(), 1985b842f2ecSJim Ingham m_access_options.GetPermissions()); 1986b842f2ecSJim Ingham else 1987b842f2ecSJim Ingham target->ConfigureBreakpointName(*bp_name, 1988b842f2ecSJim Ingham m_bp_opts.GetBreakpointOptions(), 1989b842f2ecSJim Ingham m_access_options.GetPermissions()); 1990b842f2ecSJim Ingham } 1991b842f2ecSJim Ingham return true; 1992b842f2ecSJim Ingham } 1993b842f2ecSJim Ingham 1994b842f2ecSJim Ingham private: 1995b842f2ecSJim Ingham BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1996b842f2ecSJim Ingham BreakpointOptionGroup m_bp_opts; 1997b842f2ecSJim Ingham BreakpointAccessOptionGroup m_access_options; 1998b842f2ecSJim Ingham OptionGroupOptions m_option_group; 1999b842f2ecSJim Ingham }; 2000b842f2ecSJim Ingham 2001b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 20025e09c8c3SJim Ingham public: 2003b9c1b51eSKate Stone CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 2004b9c1b51eSKate Stone : CommandObjectParsed( 2005b9c1b51eSKate Stone interpreter, "add", "Add a name to the breakpoints provided.", 20065e09c8c3SJim Ingham "breakpoint name add <command-options> <breakpoint-id-list>"), 2007b9c1b51eSKate Stone m_name_options(), m_option_group() { 2008b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 2009b9c1b51eSKate Stone // command. 20105e09c8c3SJim Ingham CommandArgumentEntry arg1; 20115e09c8c3SJim Ingham CommandArgumentData id_arg; 20125e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 20135e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 20145e09c8c3SJim Ingham arg1.push_back(id_arg); 20155e09c8c3SJim Ingham m_arguments.push_back(arg1); 20165e09c8c3SJim Ingham 20175e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 20185e09c8c3SJim Ingham m_option_group.Finalize(); 20195e09c8c3SJim Ingham } 20205e09c8c3SJim Ingham 20219e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameAdd() override = default; 20225e09c8c3SJim Ingham 2023b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 20245e09c8c3SJim Ingham 20255e09c8c3SJim Ingham protected: 2026b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2027b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 20285e09c8c3SJim Ingham result.SetError("No name option provided."); 20295e09c8c3SJim Ingham return false; 20305e09c8c3SJim Ingham } 20315e09c8c3SJim Ingham 2032b9c1b51eSKate Stone Target *target = 2033b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 20345e09c8c3SJim Ingham 2035b9c1b51eSKate Stone if (target == nullptr) { 20365e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 20375e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20385e09c8c3SJim Ingham return false; 20395e09c8c3SJim Ingham } 20405e09c8c3SJim Ingham 2041bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2042bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 20435e09c8c3SJim Ingham 20445e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 20455e09c8c3SJim Ingham 20465e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 2047b9c1b51eSKate Stone if (num_breakpoints == 0) { 20485e09c8c3SJim Ingham result.SetError("No breakpoints, cannot add names."); 20495e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20505e09c8c3SJim Ingham return false; 20515e09c8c3SJim Ingham } 20525e09c8c3SJim Ingham 20535e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 20545e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2055b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2056b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2057b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 20585e09c8c3SJim Ingham 2059b9c1b51eSKate Stone if (result.Succeeded()) { 2060b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 20615e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot add names."); 20625e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 20635e09c8c3SJim Ingham return false; 20645e09c8c3SJim Ingham } 20655e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2066b842f2ecSJim Ingham const char *bp_name = m_name_options.m_name.GetCurrentValue(); 2067b842f2ecSJim Ingham Status error; // This error reports illegal names, but we've already 2068b842f2ecSJim Ingham // checked that, so we don't need to check it again here. 2069b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2070b9c1b51eSKate Stone lldb::break_id_t bp_id = 2071b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 20725e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2073b842f2ecSJim Ingham target->AddNameToBreakpoint(bp_sp, bp_name, error); 20745e09c8c3SJim Ingham } 20755e09c8c3SJim Ingham } 20765e09c8c3SJim Ingham 20775e09c8c3SJim Ingham return true; 20785e09c8c3SJim Ingham } 20795e09c8c3SJim Ingham 20805e09c8c3SJim Ingham private: 20815e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 20825e09c8c3SJim Ingham OptionGroupOptions m_option_group; 20835e09c8c3SJim Ingham }; 20845e09c8c3SJim Ingham 2085b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 20865e09c8c3SJim Ingham public: 2087b9c1b51eSKate Stone CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 2088b9c1b51eSKate Stone : CommandObjectParsed( 2089b9c1b51eSKate Stone interpreter, "delete", 20905e09c8c3SJim Ingham "Delete a name from the breakpoints provided.", 20915e09c8c3SJim Ingham "breakpoint name delete <command-options> <breakpoint-id-list>"), 2092b9c1b51eSKate Stone m_name_options(), m_option_group() { 2093b9c1b51eSKate Stone // Create the first variant for the first (and only) argument for this 2094b9c1b51eSKate Stone // command. 20955e09c8c3SJim Ingham CommandArgumentEntry arg1; 20965e09c8c3SJim Ingham CommandArgumentData id_arg; 20975e09c8c3SJim Ingham id_arg.arg_type = eArgTypeBreakpointID; 20985e09c8c3SJim Ingham id_arg.arg_repetition = eArgRepeatOptional; 20995e09c8c3SJim Ingham arg1.push_back(id_arg); 21005e09c8c3SJim Ingham m_arguments.push_back(arg1); 21015e09c8c3SJim Ingham 21025e09c8c3SJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 21035e09c8c3SJim Ingham m_option_group.Finalize(); 21045e09c8c3SJim Ingham } 21055e09c8c3SJim Ingham 21069e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameDelete() override = default; 21075e09c8c3SJim Ingham 2108b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 21095e09c8c3SJim Ingham 21105e09c8c3SJim Ingham protected: 2111b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2112b9c1b51eSKate Stone if (!m_name_options.m_name.OptionWasSet()) { 21135e09c8c3SJim Ingham result.SetError("No name option provided."); 21145e09c8c3SJim Ingham return false; 21155e09c8c3SJim Ingham } 21165e09c8c3SJim Ingham 2117b9c1b51eSKate Stone Target *target = 2118b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 21195e09c8c3SJim Ingham 2120b9c1b51eSKate Stone if (target == nullptr) { 21215e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 21225e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21235e09c8c3SJim Ingham return false; 21245e09c8c3SJim Ingham } 21255e09c8c3SJim Ingham 2126bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2127bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 21285e09c8c3SJim Ingham 21295e09c8c3SJim Ingham const BreakpointList &breakpoints = target->GetBreakpointList(); 21305e09c8c3SJim Ingham 21315e09c8c3SJim Ingham size_t num_breakpoints = breakpoints.GetSize(); 2132b9c1b51eSKate Stone if (num_breakpoints == 0) { 21335e09c8c3SJim Ingham result.SetError("No breakpoints, cannot delete names."); 21345e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21355e09c8c3SJim Ingham return false; 21365e09c8c3SJim Ingham } 21375e09c8c3SJim Ingham 21385e09c8c3SJim Ingham // Particular breakpoint selected; disable that breakpoint. 21395e09c8c3SJim Ingham BreakpointIDList valid_bp_ids; 2140b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2141b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2142b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::deletePerm); 21435e09c8c3SJim Ingham 2144b9c1b51eSKate Stone if (result.Succeeded()) { 2145b9c1b51eSKate Stone if (valid_bp_ids.GetSize() == 0) { 21465e09c8c3SJim Ingham result.SetError("No breakpoints specified, cannot delete names."); 21475e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21485e09c8c3SJim Ingham return false; 21495e09c8c3SJim Ingham } 2150b842f2ecSJim Ingham ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 21515e09c8c3SJim Ingham size_t num_valid_ids = valid_bp_ids.GetSize(); 2152b9c1b51eSKate Stone for (size_t index = 0; index < num_valid_ids; index++) { 2153b9c1b51eSKate Stone lldb::break_id_t bp_id = 2154b9c1b51eSKate Stone valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 21555e09c8c3SJim Ingham BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2156b842f2ecSJim Ingham target->RemoveNameFromBreakpoint(bp_sp, bp_name); 21575e09c8c3SJim Ingham } 21585e09c8c3SJim Ingham } 21595e09c8c3SJim Ingham 21605e09c8c3SJim Ingham return true; 21615e09c8c3SJim Ingham } 21625e09c8c3SJim Ingham 21635e09c8c3SJim Ingham private: 21645e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 21655e09c8c3SJim Ingham OptionGroupOptions m_option_group; 21665e09c8c3SJim Ingham }; 21675e09c8c3SJim Ingham 2168b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed { 21695e09c8c3SJim Ingham public: 2170b9c1b51eSKate Stone CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2171b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "list", 2172b842f2ecSJim Ingham "List either the names for a breakpoint or info " 2173b842f2ecSJim Ingham "about a given name. With no arguments, lists all " 2174b842f2ecSJim Ingham "names", 21755e09c8c3SJim Ingham "breakpoint name list <command-options>"), 2176b9c1b51eSKate Stone m_name_options(), m_option_group() { 2177b842f2ecSJim Ingham m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 21785e09c8c3SJim Ingham m_option_group.Finalize(); 21795e09c8c3SJim Ingham } 21805e09c8c3SJim Ingham 21819e85e5a8SEugene Zelenko ~CommandObjectBreakpointNameList() override = default; 21825e09c8c3SJim Ingham 2183b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 21845e09c8c3SJim Ingham 21855e09c8c3SJim Ingham protected: 2186b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 2187b9c1b51eSKate Stone Target *target = 2188b9c1b51eSKate Stone GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 21895e09c8c3SJim Ingham 2190b9c1b51eSKate Stone if (target == nullptr) { 21915e09c8c3SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 21925e09c8c3SJim Ingham result.SetStatus(eReturnStatusFailed); 21935e09c8c3SJim Ingham return false; 21945e09c8c3SJim Ingham } 21955e09c8c3SJim Ingham 2196b842f2ecSJim Ingham 2197b842f2ecSJim Ingham std::vector<std::string> name_list; 2198b842f2ecSJim Ingham if (command.empty()) { 2199b842f2ecSJim Ingham target->GetBreakpointNames(name_list); 2200b842f2ecSJim Ingham } else { 2201b842f2ecSJim Ingham for (const Args::ArgEntry &arg : command) 2202b842f2ecSJim Ingham { 2203b842f2ecSJim Ingham name_list.push_back(arg.c_str()); 2204b842f2ecSJim Ingham } 2205b842f2ecSJim Ingham } 2206b842f2ecSJim Ingham 2207b842f2ecSJim Ingham if (name_list.empty()) { 2208b842f2ecSJim Ingham result.AppendMessage("No breakpoint names found."); 2209b842f2ecSJim Ingham } else { 2210b842f2ecSJim Ingham for (const std::string &name_str : name_list) { 2211b842f2ecSJim Ingham const char *name = name_str.c_str(); 2212b842f2ecSJim Ingham // First print out the options for the name: 2213b842f2ecSJim Ingham Status error; 2214b842f2ecSJim Ingham BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), 2215b842f2ecSJim Ingham false, 2216b842f2ecSJim Ingham error); 2217b842f2ecSJim Ingham if (bp_name) 2218b842f2ecSJim Ingham { 2219b842f2ecSJim Ingham StreamString s; 2220b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s\n", name); 2221b842f2ecSJim Ingham if (bp_name->GetDescription(&s, eDescriptionLevelFull)) 2222b842f2ecSJim Ingham { 2223b842f2ecSJim Ingham result.AppendMessage(s.GetString()); 2224b842f2ecSJim Ingham } 2225b842f2ecSJim Ingham 2226bb19a13cSSaleem Abdulrasool std::unique_lock<std::recursive_mutex> lock; 2227bb19a13cSSaleem Abdulrasool target->GetBreakpointList().GetListMutex(lock); 22285e09c8c3SJim Ingham 22295e09c8c3SJim Ingham BreakpointList &breakpoints = target->GetBreakpointList(); 2230b842f2ecSJim Ingham bool any_set = false; 2231b9c1b51eSKate Stone for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2232b9c1b51eSKate Stone if (bp_sp->MatchesName(name)) { 22335e09c8c3SJim Ingham StreamString s; 2234b842f2ecSJim Ingham any_set = true; 22355e09c8c3SJim Ingham bp_sp->GetDescription(&s, eDescriptionLevelBrief); 22365e09c8c3SJim Ingham s.EOL(); 2237c156427dSZachary Turner result.AppendMessage(s.GetString()); 22385e09c8c3SJim Ingham } 22395e09c8c3SJim Ingham } 2240b842f2ecSJim Ingham if (!any_set) 2241b842f2ecSJim Ingham result.AppendMessage("No breakpoints using this name."); 2242b9c1b51eSKate Stone } else { 2243b842f2ecSJim Ingham result.AppendMessageWithFormat("Name: %s not found.\n", name); 22445e09c8c3SJim Ingham } 2245b842f2ecSJim Ingham } 22465e09c8c3SJim Ingham } 22475e09c8c3SJim Ingham return true; 22485e09c8c3SJim Ingham } 22495e09c8c3SJim Ingham 22505e09c8c3SJim Ingham private: 22515e09c8c3SJim Ingham BreakpointNameOptionGroup m_name_options; 22525e09c8c3SJim Ingham OptionGroupOptions m_option_group; 22535e09c8c3SJim Ingham }; 22545e09c8c3SJim Ingham 22555e09c8c3SJim Ingham //------------------------------------------------------------------------- 2256e14dc268SJim Ingham // CommandObjectBreakpointName 22575e09c8c3SJim Ingham //------------------------------------------------------------------------- 2258b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword { 22595e09c8c3SJim Ingham public: 22607428a18cSKate Stone CommandObjectBreakpointName(CommandInterpreter &interpreter) 2261b9c1b51eSKate Stone : CommandObjectMultiword( 2262b9c1b51eSKate Stone interpreter, "name", "Commands to manage name tags for breakpoints", 2263b9c1b51eSKate Stone "breakpoint name <subcommand> [<command-options>]") { 2264b9c1b51eSKate Stone CommandObjectSP add_command_object( 2265b9c1b51eSKate Stone new CommandObjectBreakpointNameAdd(interpreter)); 2266b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2267b9c1b51eSKate Stone new CommandObjectBreakpointNameDelete(interpreter)); 2268b9c1b51eSKate Stone CommandObjectSP list_command_object( 2269b9c1b51eSKate Stone new CommandObjectBreakpointNameList(interpreter)); 2270b842f2ecSJim Ingham CommandObjectSP configure_command_object( 2271b842f2ecSJim Ingham new CommandObjectBreakpointNameConfigure(interpreter)); 22725e09c8c3SJim Ingham 22735e09c8c3SJim Ingham LoadSubCommand("add", add_command_object); 22745e09c8c3SJim Ingham LoadSubCommand("delete", delete_command_object); 22755e09c8c3SJim Ingham LoadSubCommand("list", list_command_object); 2276b842f2ecSJim Ingham LoadSubCommand("configure", configure_command_object); 22775e09c8c3SJim Ingham } 22785e09c8c3SJim Ingham 22799e85e5a8SEugene Zelenko ~CommandObjectBreakpointName() override = default; 22805e09c8c3SJim Ingham }; 22815e09c8c3SJim Ingham 22825e09c8c3SJim Ingham //------------------------------------------------------------------------- 2283e14dc268SJim Ingham // CommandObjectBreakpointRead 2284e14dc268SJim Ingham //------------------------------------------------------------------------- 22853acdf385SJim Ingham #pragma mark Read::CommandOptions 22861f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_read_options[] = { 22871f0f5b5bSZachary Turner // clang-format off 22881f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, 22893acdf385SJim Ingham {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, 22901f0f5b5bSZachary Turner // clang-format on 22911f0f5b5bSZachary Turner }; 22921f0f5b5bSZachary Turner 22931f0f5b5bSZachary Turner #pragma mark Read 2294e14dc268SJim Ingham 2295e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed { 2296e14dc268SJim Ingham public: 2297e14dc268SJim Ingham CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2298e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint read", 2299e14dc268SJim Ingham "Read and set the breakpoints previously saved to " 2300e14dc268SJim Ingham "a file with \"breakpoint write\". ", 2301e14dc268SJim Ingham nullptr), 2302e14dc268SJim Ingham m_options() { 2303e14dc268SJim Ingham CommandArgumentEntry arg; 2304e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2305e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2306e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2307e14dc268SJim Ingham // arguments vector. 2308e14dc268SJim Ingham m_arguments.push_back(arg); 2309e14dc268SJim Ingham } 2310e14dc268SJim Ingham 2311e14dc268SJim Ingham ~CommandObjectBreakpointRead() override = default; 2312e14dc268SJim Ingham 2313e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2314e14dc268SJim Ingham 2315e14dc268SJim Ingham class CommandOptions : public Options { 2316e14dc268SJim Ingham public: 2317e14dc268SJim Ingham CommandOptions() : Options() {} 2318e14dc268SJim Ingham 2319e14dc268SJim Ingham ~CommandOptions() override = default; 2320e14dc268SJim Ingham 232197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2322e14dc268SJim Ingham ExecutionContext *execution_context) override { 232397206d57SZachary Turner Status error; 2324e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2325e14dc268SJim Ingham 2326e14dc268SJim Ingham switch (short_option) { 2327e14dc268SJim Ingham case 'f': 2328e14dc268SJim Ingham m_filename.assign(option_arg); 2329e14dc268SJim Ingham break; 23303acdf385SJim Ingham case 'N': { 233197206d57SZachary Turner Status name_error; 23323acdf385SJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 23333acdf385SJim Ingham name_error)) { 23343acdf385SJim Ingham error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 23353acdf385SJim Ingham name_error.AsCString()); 23363acdf385SJim Ingham } 23373acdf385SJim Ingham m_names.push_back(option_arg); 23383acdf385SJim Ingham break; 23393acdf385SJim Ingham } 2340e14dc268SJim Ingham default: 2341e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2342e14dc268SJim Ingham short_option); 2343e14dc268SJim Ingham break; 2344e14dc268SJim Ingham } 2345e14dc268SJim Ingham 2346e14dc268SJim Ingham return error; 2347e14dc268SJim Ingham } 2348e14dc268SJim Ingham 2349e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2350e14dc268SJim Ingham m_filename.clear(); 23513acdf385SJim Ingham m_names.clear(); 2352e14dc268SJim Ingham } 2353e14dc268SJim Ingham 23541f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 235570602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_read_options); 23561f0f5b5bSZachary Turner } 2357e14dc268SJim Ingham 2358e14dc268SJim Ingham // Instance variables to hold the values for command options. 2359e14dc268SJim Ingham 2360e14dc268SJim Ingham std::string m_filename; 23613acdf385SJim Ingham std::vector<std::string> m_names; 2362e14dc268SJim Ingham }; 2363e14dc268SJim Ingham 2364e14dc268SJim Ingham protected: 2365e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2366e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2367e14dc268SJim Ingham if (target == nullptr) { 2368e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2369e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2370e14dc268SJim Ingham return false; 2371e14dc268SJim Ingham } 2372e14dc268SJim Ingham 23733acdf385SJim Ingham std::unique_lock<std::recursive_mutex> lock; 23743acdf385SJim Ingham target->GetBreakpointList().GetListMutex(lock); 23753acdf385SJim Ingham 2376e14dc268SJim Ingham FileSpec input_spec(m_options.m_filename, true); 237701f16664SJim Ingham BreakpointIDList new_bps; 237897206d57SZachary Turner Status error = target->CreateBreakpointsFromFile( 237997206d57SZachary Turner input_spec, m_options.m_names, new_bps); 2380e14dc268SJim Ingham 2381e14dc268SJim Ingham if (!error.Success()) { 238201f16664SJim Ingham result.AppendError(error.AsCString()); 2383e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 238401f16664SJim Ingham return false; 2385e14dc268SJim Ingham } 23863acdf385SJim Ingham 23873acdf385SJim Ingham Stream &output_stream = result.GetOutputStream(); 23883acdf385SJim Ingham 23893acdf385SJim Ingham size_t num_breakpoints = new_bps.GetSize(); 23903acdf385SJim Ingham if (num_breakpoints == 0) { 23913acdf385SJim Ingham result.AppendMessage("No breakpoints added."); 23923acdf385SJim Ingham } else { 23933acdf385SJim Ingham // No breakpoint selected; show info about all currently set breakpoints. 23943acdf385SJim Ingham result.AppendMessage("New breakpoints:"); 23953acdf385SJim Ingham for (size_t i = 0; i < num_breakpoints; ++i) { 23963acdf385SJim Ingham BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 23973acdf385SJim Ingham Breakpoint *bp = target->GetBreakpointList() 23983acdf385SJim Ingham .FindBreakpointByID(bp_id.GetBreakpointID()) 23993acdf385SJim Ingham .get(); 24003acdf385SJim Ingham if (bp) 24013acdf385SJim Ingham bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 24023acdf385SJim Ingham false); 24033acdf385SJim Ingham } 24043acdf385SJim Ingham } 2405e14dc268SJim Ingham return result.Succeeded(); 2406e14dc268SJim Ingham } 2407e14dc268SJim Ingham 2408e14dc268SJim Ingham private: 2409e14dc268SJim Ingham CommandOptions m_options; 2410e14dc268SJim Ingham }; 2411e14dc268SJim Ingham 2412e14dc268SJim Ingham //------------------------------------------------------------------------- 2413e14dc268SJim Ingham // CommandObjectBreakpointWrite 2414e14dc268SJim Ingham //------------------------------------------------------------------------- 24151f0f5b5bSZachary Turner #pragma mark Write::CommandOptions 24161f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_write_options[] = { 24171f0f5b5bSZachary Turner // clang-format off 24181f0f5b5bSZachary Turner { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, 24192d3628e1SJim Ingham { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, 24201f0f5b5bSZachary Turner // clang-format on 24211f0f5b5bSZachary Turner }; 24221f0f5b5bSZachary Turner 24231f0f5b5bSZachary Turner #pragma mark Write 2424e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed { 2425e14dc268SJim Ingham public: 2426e14dc268SJim Ingham CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2427e14dc268SJim Ingham : CommandObjectParsed(interpreter, "breakpoint write", 2428e14dc268SJim Ingham "Write the breakpoints listed to a file that can " 2429e14dc268SJim Ingham "be read in with \"breakpoint read\". " 2430e14dc268SJim Ingham "If given no arguments, writes all breakpoints.", 2431e14dc268SJim Ingham nullptr), 2432e14dc268SJim Ingham m_options() { 2433e14dc268SJim Ingham CommandArgumentEntry arg; 2434e14dc268SJim Ingham CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2435e14dc268SJim Ingham eArgTypeBreakpointIDRange); 2436e14dc268SJim Ingham // Add the entry for the first argument for this command to the object's 2437e14dc268SJim Ingham // arguments vector. 2438e14dc268SJim Ingham m_arguments.push_back(arg); 2439e14dc268SJim Ingham } 2440e14dc268SJim Ingham 2441e14dc268SJim Ingham ~CommandObjectBreakpointWrite() override = default; 2442e14dc268SJim Ingham 2443e14dc268SJim Ingham Options *GetOptions() override { return &m_options; } 2444e14dc268SJim Ingham 2445e14dc268SJim Ingham class CommandOptions : public Options { 2446e14dc268SJim Ingham public: 2447e14dc268SJim Ingham CommandOptions() : Options() {} 2448e14dc268SJim Ingham 2449e14dc268SJim Ingham ~CommandOptions() override = default; 2450e14dc268SJim Ingham 245197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2452e14dc268SJim Ingham ExecutionContext *execution_context) override { 245397206d57SZachary Turner Status error; 2454e14dc268SJim Ingham const int short_option = m_getopt_table[option_idx].val; 2455e14dc268SJim Ingham 2456e14dc268SJim Ingham switch (short_option) { 2457e14dc268SJim Ingham case 'f': 2458e14dc268SJim Ingham m_filename.assign(option_arg); 2459e14dc268SJim Ingham break; 24602d3628e1SJim Ingham case 'a': 24612d3628e1SJim Ingham m_append = true; 24622d3628e1SJim Ingham break; 2463e14dc268SJim Ingham default: 2464e14dc268SJim Ingham error.SetErrorStringWithFormat("unrecognized option '%c'", 2465e14dc268SJim Ingham short_option); 2466e14dc268SJim Ingham break; 2467e14dc268SJim Ingham } 2468e14dc268SJim Ingham 2469e14dc268SJim Ingham return error; 2470e14dc268SJim Ingham } 2471e14dc268SJim Ingham 2472e14dc268SJim Ingham void OptionParsingStarting(ExecutionContext *execution_context) override { 2473e14dc268SJim Ingham m_filename.clear(); 24742d3628e1SJim Ingham m_append = false; 2475e14dc268SJim Ingham } 2476e14dc268SJim Ingham 24771f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 247870602439SZachary Turner return llvm::makeArrayRef(g_breakpoint_write_options); 24791f0f5b5bSZachary Turner } 2480e14dc268SJim Ingham 2481e14dc268SJim Ingham // Instance variables to hold the values for command options. 2482e14dc268SJim Ingham 2483e14dc268SJim Ingham std::string m_filename; 24842d3628e1SJim Ingham bool m_append = false; 2485e14dc268SJim Ingham }; 2486e14dc268SJim Ingham 2487e14dc268SJim Ingham protected: 2488e14dc268SJim Ingham bool DoExecute(Args &command, CommandReturnObject &result) override { 2489e14dc268SJim Ingham Target *target = GetSelectedOrDummyTarget(); 2490e14dc268SJim Ingham if (target == nullptr) { 2491e14dc268SJim Ingham result.AppendError("Invalid target. No existing target or breakpoints."); 2492e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2493e14dc268SJim Ingham return false; 2494e14dc268SJim Ingham } 2495e14dc268SJim Ingham 2496e14dc268SJim Ingham std::unique_lock<std::recursive_mutex> lock; 2497e14dc268SJim Ingham target->GetBreakpointList().GetListMutex(lock); 2498e14dc268SJim Ingham 2499e14dc268SJim Ingham BreakpointIDList valid_bp_ids; 250011eb9c64SZachary Turner if (!command.empty()) { 2501e14dc268SJim Ingham CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2502b842f2ecSJim Ingham command, target, result, &valid_bp_ids, 2503b842f2ecSJim Ingham BreakpointName::Permissions::PermissionKinds::listPerm); 2504e14dc268SJim Ingham 250501f16664SJim Ingham if (!result.Succeeded()) { 2506e14dc268SJim Ingham result.SetStatus(eReturnStatusFailed); 2507e14dc268SJim Ingham return false; 2508e14dc268SJim Ingham } 2509e14dc268SJim Ingham } 251097206d57SZachary Turner Status error = target->SerializeBreakpointsToFile( 2511771ef6d4SMalcolm Parsons FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append); 251201f16664SJim Ingham if (!error.Success()) { 251301f16664SJim Ingham result.AppendErrorWithFormat("error serializing breakpoints: %s.", 251401f16664SJim Ingham error.AsCString()); 251501f16664SJim Ingham result.SetStatus(eReturnStatusFailed); 2516e14dc268SJim Ingham } 2517e14dc268SJim Ingham return result.Succeeded(); 2518e14dc268SJim Ingham } 2519e14dc268SJim Ingham 2520e14dc268SJim Ingham private: 2521e14dc268SJim Ingham CommandOptions m_options; 2522e14dc268SJim Ingham }; 2523e14dc268SJim Ingham 2524e14dc268SJim Ingham //------------------------------------------------------------------------- 252530fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint 252630fdc8d8SChris Lattner //------------------------------------------------------------------------- 2527ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint 252830fdc8d8SChris Lattner 2529b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2530b9c1b51eSKate Stone CommandInterpreter &interpreter) 2531b9c1b51eSKate Stone : CommandObjectMultiword( 2532b9c1b51eSKate Stone interpreter, "breakpoint", 25337428a18cSKate Stone "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2534b9c1b51eSKate Stone "breakpoint <subcommand> [<command-options>]") { 2535b9c1b51eSKate Stone CommandObjectSP list_command_object( 2536b9c1b51eSKate Stone new CommandObjectBreakpointList(interpreter)); 2537b9c1b51eSKate Stone CommandObjectSP enable_command_object( 2538b9c1b51eSKate Stone new CommandObjectBreakpointEnable(interpreter)); 2539b9c1b51eSKate Stone CommandObjectSP disable_command_object( 2540b9c1b51eSKate Stone new CommandObjectBreakpointDisable(interpreter)); 2541b9c1b51eSKate Stone CommandObjectSP clear_command_object( 2542b9c1b51eSKate Stone new CommandObjectBreakpointClear(interpreter)); 2543b9c1b51eSKate Stone CommandObjectSP delete_command_object( 2544b9c1b51eSKate Stone new CommandObjectBreakpointDelete(interpreter)); 2545b9c1b51eSKate Stone CommandObjectSP set_command_object( 2546b9c1b51eSKate Stone new CommandObjectBreakpointSet(interpreter)); 2547b9c1b51eSKate Stone CommandObjectSP command_command_object( 2548b9c1b51eSKate Stone new CommandObjectBreakpointCommand(interpreter)); 2549b9c1b51eSKate Stone CommandObjectSP modify_command_object( 2550b9c1b51eSKate Stone new CommandObjectBreakpointModify(interpreter)); 2551b9c1b51eSKate Stone CommandObjectSP name_command_object( 2552b9c1b51eSKate Stone new CommandObjectBreakpointName(interpreter)); 2553e14dc268SJim Ingham CommandObjectSP write_command_object( 2554e14dc268SJim Ingham new CommandObjectBreakpointWrite(interpreter)); 2555e14dc268SJim Ingham CommandObjectSP read_command_object( 2556e14dc268SJim Ingham new CommandObjectBreakpointRead(interpreter)); 255730fdc8d8SChris Lattner 2558b7234e40SJohnny Chen list_command_object->SetCommandName("breakpoint list"); 255930fdc8d8SChris Lattner enable_command_object->SetCommandName("breakpoint enable"); 256030fdc8d8SChris Lattner disable_command_object->SetCommandName("breakpoint disable"); 2561b7234e40SJohnny Chen clear_command_object->SetCommandName("breakpoint clear"); 2562b7234e40SJohnny Chen delete_command_object->SetCommandName("breakpoint delete"); 2563ae1c4cf5SJim Ingham set_command_object->SetCommandName("breakpoint set"); 2564b7234e40SJohnny Chen command_command_object->SetCommandName("breakpoint command"); 2565b7234e40SJohnny Chen modify_command_object->SetCommandName("breakpoint modify"); 25665e09c8c3SJim Ingham name_command_object->SetCommandName("breakpoint name"); 2567e14dc268SJim Ingham write_command_object->SetCommandName("breakpoint write"); 2568e14dc268SJim Ingham read_command_object->SetCommandName("breakpoint read"); 256930fdc8d8SChris Lattner 257023f59509SGreg Clayton LoadSubCommand("list", list_command_object); 257123f59509SGreg Clayton LoadSubCommand("enable", enable_command_object); 257223f59509SGreg Clayton LoadSubCommand("disable", disable_command_object); 257323f59509SGreg Clayton LoadSubCommand("clear", clear_command_object); 257423f59509SGreg Clayton LoadSubCommand("delete", delete_command_object); 257523f59509SGreg Clayton LoadSubCommand("set", set_command_object); 257623f59509SGreg Clayton LoadSubCommand("command", command_command_object); 257723f59509SGreg Clayton LoadSubCommand("modify", modify_command_object); 25785e09c8c3SJim Ingham LoadSubCommand("name", name_command_object); 2579e14dc268SJim Ingham LoadSubCommand("write", write_command_object); 2580e14dc268SJim Ingham LoadSubCommand("read", read_command_object); 258130fdc8d8SChris Lattner } 258230fdc8d8SChris Lattner 25839e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 258430fdc8d8SChris Lattner 2585b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 25865e09c8c3SJim Ingham bool allow_locations, 25875e09c8c3SJim Ingham CommandReturnObject &result, 2588b842f2ecSJim Ingham BreakpointIDList *valid_ids, 2589b842f2ecSJim Ingham BreakpointName::Permissions 2590b842f2ecSJim Ingham ::PermissionKinds 2591b842f2ecSJim Ingham purpose) { 259230fdc8d8SChris Lattner // args can be strings representing 1). integers (for breakpoint ids) 2593b9c1b51eSKate Stone // 2). the full breakpoint & location 2594b9c1b51eSKate Stone // canonical representation 2595b9c1b51eSKate Stone // 3). the word "to" or a hyphen, 2596b9c1b51eSKate Stone // representing a range (in which case there 2597b9c1b51eSKate Stone // had *better* be an entry both before & 2598b9c1b51eSKate Stone // after of one of the first two types. 25995e09c8c3SJim Ingham // 4). A breakpoint name 2600b9c1b51eSKate Stone // If args is empty, we will use the last created breakpoint (if there is 2601b9c1b51eSKate Stone // one.) 260230fdc8d8SChris Lattner 260330fdc8d8SChris Lattner Args temp_args; 260430fdc8d8SChris Lattner 260511eb9c64SZachary Turner if (args.empty()) { 2606b9c1b51eSKate Stone if (target->GetLastCreatedBreakpoint()) { 2607b9c1b51eSKate Stone valid_ids->AddBreakpointID(BreakpointID( 2608b9c1b51eSKate Stone target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 260936f3b369SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 2610b9c1b51eSKate Stone } else { 2611b9c1b51eSKate Stone result.AppendError( 2612b9c1b51eSKate Stone "No breakpoint specified and no last created breakpoint."); 261336f3b369SJim Ingham result.SetStatus(eReturnStatusFailed); 261436f3b369SJim Ingham } 261536f3b369SJim Ingham return; 261636f3b369SJim Ingham } 261736f3b369SJim Ingham 2618b9c1b51eSKate Stone // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 261905097246SAdrian Prantl // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 262005097246SAdrian Prantl // id range strings over; instead generate a list of strings for all the 262105097246SAdrian Prantl // breakpoint ids in the range, and shove all of those breakpoint id strings 262205097246SAdrian Prantl // into TEMP_ARGS. 262330fdc8d8SChris Lattner 2624b9c1b51eSKate Stone BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2625b842f2ecSJim Ingham purpose, result, temp_args); 262630fdc8d8SChris Lattner 2627b9c1b51eSKate Stone // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2628b9c1b51eSKate Stone // BreakpointIDList: 262930fdc8d8SChris Lattner 263016662f3cSPavel Labath valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 263130fdc8d8SChris Lattner 263205097246SAdrian Prantl // At this point, all of the breakpoint ids that the user passed in have 263305097246SAdrian Prantl // been converted to breakpoint IDs and put into valid_ids. 263430fdc8d8SChris Lattner 2635b9c1b51eSKate Stone if (result.Succeeded()) { 2636b9c1b51eSKate Stone // Now that we've converted everything from args into a list of breakpoint 263705097246SAdrian Prantl // ids, go through our tentative list of breakpoint id's and verify that 263805097246SAdrian Prantl // they correspond to valid/currently set breakpoints. 263930fdc8d8SChris Lattner 2640c982c768SGreg Clayton const size_t count = valid_ids->GetSize(); 2641b9c1b51eSKate Stone for (size_t i = 0; i < count; ++i) { 264230fdc8d8SChris Lattner BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2643b9c1b51eSKate Stone Breakpoint *breakpoint = 2644b9c1b51eSKate Stone target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2645b9c1b51eSKate Stone if (breakpoint != nullptr) { 2646c7bece56SGreg Clayton const size_t num_locations = breakpoint->GetNumLocations(); 2647b9c1b51eSKate Stone if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 264830fdc8d8SChris Lattner StreamString id_str; 2649b9c1b51eSKate Stone BreakpointID::GetCanonicalReference( 2650b9c1b51eSKate Stone &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2651c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2652b9c1b51eSKate Stone result.AppendErrorWithFormat( 2653b9c1b51eSKate Stone "'%s' is not a currently valid breakpoint/location id.\n", 265430fdc8d8SChris Lattner id_str.GetData()); 265530fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 265630fdc8d8SChris Lattner } 2657b9c1b51eSKate Stone } else { 2658c982c768SGreg Clayton i = valid_ids->GetSize() + 1; 2659b9c1b51eSKate Stone result.AppendErrorWithFormat( 2660b9c1b51eSKate Stone "'%d' is not a currently valid breakpoint ID.\n", 26617428a18cSKate Stone cur_bp_id.GetBreakpointID()); 266230fdc8d8SChris Lattner result.SetStatus(eReturnStatusFailed); 266330fdc8d8SChris Lattner } 266430fdc8d8SChris Lattner } 266530fdc8d8SChris Lattner } 266630fdc8d8SChris Lattner } 2667