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