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"
21*3eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
22b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h"
23b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
24b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
2532abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
265e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
275e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
28b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
290e0984eeSJim Ingham #include "lldb/Target/Language.h"
30b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
31b9c1b51eSKate Stone #include "lldb/Target/Target.h"
321b54c88cSJim Ingham #include "lldb/Target/Thread.h"
331b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
34bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
35bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner using namespace lldb;
3830fdc8d8SChris Lattner using namespace lldb_private;
3930fdc8d8SChris Lattner 
40b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
41b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
4230fdc8d8SChris Lattner   s->IndentMore();
4330fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4430fdc8d8SChris Lattner   s->IndentLess();
4530fdc8d8SChris Lattner   s->EOL();
4630fdc8d8SChris Lattner }
4730fdc8d8SChris Lattner 
481f0f5b5bSZachary Turner // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
491f0f5b5bSZachary Turner // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
501f0f5b5bSZachary Turner #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
511f0f5b5bSZachary Turner #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
521f0f5b5bSZachary Turner #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
531f0f5b5bSZachary Turner #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
541f0f5b5bSZachary Turner #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
551f0f5b5bSZachary Turner #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
561f0f5b5bSZachary Turner 
571f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_set_options[] = {
581f0f5b5bSZachary Turner     // clang-format off
591f0f5b5bSZachary 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 "
601f0f5b5bSZachary Turner   "multiple times to specify multiple shared libraries." },
611f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "ignore-count",           'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeCount,               "Set the number of times this breakpoint is skipped before stopping." },
621f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "one-shot",               'o', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "The breakpoint is deleted the first time it causes a stop." },
631f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "condition",              'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeExpression,          "The breakpoint stops only if this condition expression evaluates to true." },
641f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "thread-index",           'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadIndex,         "The breakpoint stops only for the thread whose indeX matches this argument." },
651f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "thread-id",              't', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadID,            "The breakpoint stops only for the thread whose TID matches this argument." },
661f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "thread-name",            'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeThreadName,          "The breakpoint stops only for the thread whose thread name matches this "
671f0f5b5bSZachary Turner   "argument." },
681f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "hardware",               'H', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "Require the breakpoint to use hardware breakpoints." },
691f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "queue-name",             'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeQueueName,           "The breakpoint stops only for threads in the queue whose name is given by "
701f0f5b5bSZachary Turner   "this argument." },
711f0f5b5bSZachary 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 "
721f0f5b5bSZachary Turner   "lldb only looks for files that are #included if they use the standard include "
731f0f5b5bSZachary Turner   "file extensions.  To set breakpoints on .c/.cpp/.m/.mm files that are "
741f0f5b5bSZachary Turner   "#included, set target.inline-breakpoint-strategy to \"always\"." },
751f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,                true,  "line",                   'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,             "Specifies the line number on which to set this breakpoint." },
761f0f5b5bSZachary Turner 
771f0f5b5bSZachary Turner   // Comment out this option for the moment, as we don't actually use it, but will in the future.
781f0f5b5bSZachary Turner   // This way users won't see it, but the infrastructure is left in place.
791f0f5b5bSZachary Turner   //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, nullptr, "<column>",
801f0f5b5bSZachary Turner   //    "Set the breakpoint by source location at this particular column."},
811f0f5b5bSZachary Turner 
821f0f5b5bSZachary 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 "
831f0f5b5bSZachary Turner   "a particular binary, then the address will be converted to a \"file\" "
841f0f5b5bSZachary Turner   "address, so that the breakpoint will track that binary+offset no matter where "
851f0f5b5bSZachary Turner   "the binary eventually loads.  Alternately, if you also specify the module - "
861f0f5b5bSZachary Turner   "with the -s option - then the address will be treated as a file address in "
871f0f5b5bSZachary Turner   "that module, and resolved accordingly.  Again, this will allow lldb to track "
881f0f5b5bSZachary Turner   "that offset on subsequent reloads.  The module need not have been loaded at "
891f0f5b5bSZachary Turner   "the time you specify this breakpoint, and will get resolved when the module "
901f0f5b5bSZachary Turner   "is loaded." },
911f0f5b5bSZachary 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 "
921f0f5b5bSZachary Turner   "one breakpoint for multiple names" },
931f0f5b5bSZachary 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 "
941f0f5b5bSZachary Turner   "functions.  Can be repeated multiple times." },
951f0f5b5bSZachary 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 "
961f0f5b5bSZachary Turner   "namespaces and all arguments, and for Objective C this means a full function "
971f0f5b5bSZachary Turner   "prototype with class and selector.  Can be repeated multiple times to make "
981f0f5b5bSZachary Turner   "one breakpoint for multiple names." },
991f0f5b5bSZachary 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 "
1001f0f5b5bSZachary Turner   "make one breakpoint for multiple Selectors." },
1011f0f5b5bSZachary 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 "
1021f0f5b5bSZachary Turner   "make one breakpoint for multiple methods." },
1031f0f5b5bSZachary 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 "
1041f0f5b5bSZachary Turner   "the function name(s)." },
1051f0f5b5bSZachary 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 "
1061f0f5b5bSZachary Turner   "ignored).  Can be repeated multiple times to make one breakpoint for multiple "
1071f0f5b5bSZachary Turner   "symbols." },
1081f0f5b5bSZachary 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 "
1091f0f5b5bSZachary Turner   "against the source text in a source file or files specified with the -f "
1101f0f5b5bSZachary Turner   "option.  The -f option can be specified more than once.  If no source files "
1111f0f5b5bSZachary Turner   "are specified, uses the current \"default source file\".  If you want to "
1121f0f5b5bSZachary Turner   "match against all source files, pass the \"--all-files\" option." },
1131f0f5b5bSZachary Turner   { LLDB_OPT_SET_9,                false, "all-files",              'A', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "All files are searched for source pattern matches." },
1141f0f5b5bSZachary 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 "
1151f0f5b5bSZachary Turner   "options, on throw but not catch.)" },
1161f0f5b5bSZachary Turner   { LLDB_OPT_SET_10,               false, "on-throw",               'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception throW." },
1171f0f5b5bSZachary Turner   { LLDB_OPT_SET_10,               false, "on-catch",               'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception catcH." },
1181f0f5b5bSZachary Turner 
1191f0f5b5bSZachary Turner   //  Don't add this option till it actually does something useful...
1201f0f5b5bSZachary Turner   //    { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
1211f0f5b5bSZachary 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" },
1221f0f5b5bSZachary Turner 
1231f0f5b5bSZachary 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 "
1241f0f5b5bSZachary Turner   "(note: currently only implemented for setting breakpoints on identifiers).  "
1251f0f5b5bSZachary Turner   "If not set the target.language setting is used." },
1261f0f5b5bSZachary 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.  "
1271f0f5b5bSZachary Turner   "If not set the target.skip-prologue setting is used." },
1281f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL,              false, "dummy-breakpoints",      'D', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, "
1291f0f5b5bSZachary Turner   "which prime new targets." },
1301f0f5b5bSZachary 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." },
1311f0f5b5bSZachary 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.  "
1321f0f5b5bSZachary Turner   "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
1331f0f5b5bSZachary 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 "
1341f0f5b5bSZachary Turner   "setting is used." },
1351f0f5b5bSZachary Turner     // clang-format on
1361f0f5b5bSZachary Turner };
1371f0f5b5bSZachary Turner 
13830fdc8d8SChris Lattner //-------------------------------------------------------------------------
1395a988416SJim Ingham // CommandObjectBreakpointSet
14030fdc8d8SChris Lattner //-------------------------------------------------------------------------
14130fdc8d8SChris Lattner 
142b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
1435a988416SJim Ingham public:
144b9c1b51eSKate Stone   typedef enum BreakpointSetType {
1455a988416SJim Ingham     eSetTypeInvalid,
1465a988416SJim Ingham     eSetTypeFileAndLine,
1475a988416SJim Ingham     eSetTypeAddress,
1485a988416SJim Ingham     eSetTypeFunctionName,
1495a988416SJim Ingham     eSetTypeFunctionRegexp,
1505a988416SJim Ingham     eSetTypeSourceRegexp,
1515a988416SJim Ingham     eSetTypeException
1525a988416SJim Ingham   } BreakpointSetType;
1535a988416SJim Ingham 
154b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
155b9c1b51eSKate Stone       : CommandObjectParsed(
156b9c1b51eSKate Stone             interpreter, "breakpoint set",
1575a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
1585a988416SJim Ingham             "breakpoint set <cmd-options>"),
159b9c1b51eSKate Stone         m_options() {}
1605a988416SJim Ingham 
1619e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
1625a988416SJim Ingham 
163b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1645a988416SJim Ingham 
165b9c1b51eSKate Stone   class CommandOptions : public Options {
1665a988416SJim Ingham   public:
167b9c1b51eSKate Stone     CommandOptions()
168b9c1b51eSKate Stone         : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
169b9c1b51eSKate Stone           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
170b9c1b51eSKate Stone           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
171b9c1b51eSKate Stone           m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
172b9c1b51eSKate Stone           m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
173b9c1b51eSKate Stone           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
174a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
17523b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
176b9c1b51eSKate Stone           m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
177b9c1b51eSKate Stone           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
17830fdc8d8SChris Lattner 
1799e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
18087df91b8SJim Ingham 
181fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
182b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
18330fdc8d8SChris Lattner       Error error;
1843bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
18530fdc8d8SChris Lattner 
186b9c1b51eSKate Stone       switch (short_option) {
187b9c1b51eSKate Stone       case 'a': {
188b9c1b51eSKate Stone         m_load_addr = Args::StringToAddress(execution_context, option_arg,
189e1cfbc79STodd Fiala                                             LLDB_INVALID_ADDRESS, &error);
190b9c1b51eSKate Stone       } break;
19130fdc8d8SChris Lattner 
192e732052fSJim Ingham       case 'A':
193e732052fSJim Ingham         m_all_files = true;
194e732052fSJim Ingham         break;
195e732052fSJim Ingham 
196ca36cd16SJim Ingham       case 'b':
197ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
198ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
199ca36cd16SJim Ingham         break;
200ca36cd16SJim Ingham 
201fe11483bSZachary Turner       case 'C':
202fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
203b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
204fe11483bSZachary Turner                                          option_arg.str().c_str());
20530fdc8d8SChris Lattner         break;
2069e85e5a8SEugene Zelenko 
2077d49c9c8SJohnny Chen       case 'c':
2087d49c9c8SJohnny Chen         m_condition.assign(option_arg);
2097d49c9c8SJohnny Chen         break;
2107d49c9c8SJohnny Chen 
21133df7cd3SJim Ingham       case 'D':
21233df7cd3SJim Ingham         m_use_dummy = true;
21333df7cd3SJim Ingham         break;
21433df7cd3SJim Ingham 
215b9c1b51eSKate Stone       case 'E': {
216fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
217fab10e89SJim Ingham 
218b9c1b51eSKate Stone         switch (language) {
219fab10e89SJim Ingham         case eLanguageTypeC89:
220fab10e89SJim Ingham         case eLanguageTypeC:
221fab10e89SJim Ingham         case eLanguageTypeC99:
2221d0089faSBruce Mitchener         case eLanguageTypeC11:
223a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
224fab10e89SJim Ingham           break;
225fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2261d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2271d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
2282ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
229a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
230fab10e89SJim Ingham           break;
231fab10e89SJim Ingham         case eLanguageTypeObjC:
232a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
233fab10e89SJim Ingham           break;
234fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
235b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
236b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
237fab10e89SJim Ingham           break;
238fab10e89SJim Ingham         case eLanguageTypeUnknown:
239b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
240b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
241fe11483bSZachary Turner               option_arg.str().c_str());
242fab10e89SJim Ingham           break;
243fab10e89SJim Ingham         default:
244b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
245b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
246fe11483bSZachary Turner               option_arg.str().c_str());
247fab10e89SJim Ingham         }
248b9c1b51eSKate Stone       } break;
249ca36cd16SJim Ingham 
250ca36cd16SJim Ingham       case 'f':
251ca36cd16SJim Ingham         m_filenames.AppendIfUnique(FileSpec(option_arg, false));
252fab10e89SJim Ingham         break;
253ca36cd16SJim Ingham 
254ca36cd16SJim Ingham       case 'F':
255ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
256ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
257ca36cd16SJim Ingham         break;
258ca36cd16SJim Ingham 
259b9c1b51eSKate Stone       case 'h': {
260fab10e89SJim Ingham         bool success;
261fe11483bSZachary Turner         m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
262fab10e89SJim Ingham         if (!success)
263b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
264fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
265fe11483bSZachary Turner               option_arg.str().c_str());
266b9c1b51eSKate Stone       } break;
267eb023e75SGreg Clayton 
268eb023e75SGreg Clayton       case 'H':
269eb023e75SGreg Clayton         m_hardware = true;
270eb023e75SGreg Clayton         break;
271eb023e75SGreg Clayton 
272ca36cd16SJim Ingham       case 'i':
273fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_ignore_count))
274b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid ignore count '%s'",
275fe11483bSZachary Turner                                          option_arg.str().c_str());
276ca36cd16SJim Ingham         break;
277ca36cd16SJim Ingham 
278b9c1b51eSKate Stone       case 'K': {
279a8558b62SJim Ingham         bool success;
280a8558b62SJim Ingham         bool value;
281fe11483bSZachary Turner         value = Args::StringToBoolean(option_arg, true, &success);
282a8558b62SJim Ingham         if (value)
283a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
284a8558b62SJim Ingham         else
285a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
286a8558b62SJim Ingham 
287a8558b62SJim Ingham         if (!success)
288b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
289b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
290fe11483bSZachary Turner               option_arg.str().c_str());
291b9c1b51eSKate Stone       } break;
292ca36cd16SJim Ingham 
293fe11483bSZachary Turner       case 'l':
294fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
295b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
296fe11483bSZachary Turner                                          option_arg.str().c_str());
297ca36cd16SJim Ingham         break;
298055ad9beSIlia K 
29923b1decbSDawn Perchik       case 'L':
300fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
30123b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
302b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
303fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
304fe11483bSZachary Turner               option_arg.str().c_str());
30523b1decbSDawn Perchik         break;
30623b1decbSDawn Perchik 
307b9c1b51eSKate Stone       case 'm': {
308055ad9beSIlia K         bool success;
309055ad9beSIlia K         bool value;
310fe11483bSZachary Turner         value = Args::StringToBoolean(option_arg, true, &success);
311055ad9beSIlia K         if (value)
312055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
313055ad9beSIlia K         else
314055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
315055ad9beSIlia K 
316055ad9beSIlia K         if (!success)
317b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
318b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
319fe11483bSZachary Turner               option_arg.str().c_str());
320055ad9beSIlia K         break;
321055ad9beSIlia K       }
322055ad9beSIlia K 
323ca36cd16SJim Ingham       case 'M':
324ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
325ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
326ca36cd16SJim Ingham         break;
327ca36cd16SJim Ingham 
328ca36cd16SJim Ingham       case 'n':
329ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
330ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
331ca36cd16SJim Ingham         break;
332ca36cd16SJim Ingham 
3336fa7681bSZachary Turner       case 'N': {
334fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
3355e09c8c3SJim Ingham           m_breakpoint_names.push_back(option_arg);
336ff9a91eaSJim Ingham         else
337ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
338fe11483bSZachary Turner                                          option_arg.str().c_str());
3395e09c8c3SJim Ingham         break;
3406fa7681bSZachary Turner       }
3415e09c8c3SJim Ingham 
342b9c1b51eSKate Stone       case 'R': {
3432411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
344e1cfbc79STodd Fiala         tmp_offset_addr =
345b9c1b51eSKate Stone             Args::StringToAddress(execution_context, option_arg, 0, &error);
3462411167fSJim Ingham         if (error.Success())
3472411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
348b9c1b51eSKate Stone       } break;
3492411167fSJim Ingham 
350ca36cd16SJim Ingham       case 'o':
351ca36cd16SJim Ingham         m_one_shot = true;
352ca36cd16SJim Ingham         break;
353ca36cd16SJim Ingham 
354a72b31c7SJim Ingham       case 'O':
355fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
356fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
357a72b31c7SJim Ingham         break;
358a72b31c7SJim Ingham 
359ca36cd16SJim Ingham       case 'p':
360ca36cd16SJim Ingham         m_source_text_regexp.assign(option_arg);
361ca36cd16SJim Ingham         break;
362ca36cd16SJim Ingham 
363ca36cd16SJim Ingham       case 'q':
364ca36cd16SJim Ingham         m_queue_name.assign(option_arg);
365ca36cd16SJim Ingham         break;
366ca36cd16SJim Ingham 
367ca36cd16SJim Ingham       case 'r':
368ca36cd16SJim Ingham         m_func_regexp.assign(option_arg);
369ca36cd16SJim Ingham         break;
370ca36cd16SJim Ingham 
371ca36cd16SJim Ingham       case 's':
372ca36cd16SJim Ingham         m_modules.AppendIfUnique(FileSpec(option_arg, false));
373ca36cd16SJim Ingham         break;
374ca36cd16SJim Ingham 
375ca36cd16SJim Ingham       case 'S':
376ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
377ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
378ca36cd16SJim Ingham         break;
379ca36cd16SJim Ingham 
380ca36cd16SJim Ingham       case 't':
381fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_thread_id))
382b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid thread id string '%s'",
383fe11483bSZachary Turner                                          option_arg.str().c_str());
384ca36cd16SJim Ingham         break;
385ca36cd16SJim Ingham 
386ca36cd16SJim Ingham       case 'T':
387ca36cd16SJim Ingham         m_thread_name.assign(option_arg);
388ca36cd16SJim Ingham         break;
389ca36cd16SJim Ingham 
390b9c1b51eSKate Stone       case 'w': {
391ca36cd16SJim Ingham         bool success;
392fe11483bSZachary Turner         m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
393ca36cd16SJim Ingham         if (!success)
394b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
395fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
396fe11483bSZachary Turner               option_arg.str().c_str());
397b9c1b51eSKate Stone       } break;
398ca36cd16SJim Ingham 
399ca36cd16SJim Ingham       case 'x':
400fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_thread_index))
401b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid thread index string '%s'",
402fe11483bSZachary Turner                                          option_arg.str().c_str());
403ca36cd16SJim Ingham         break;
404ca36cd16SJim Ingham 
40576bb8d67SJim Ingham       case 'X':
40676bb8d67SJim Ingham         m_source_regex_func_names.insert(option_arg);
40776bb8d67SJim Ingham         break;
40876bb8d67SJim Ingham 
40930fdc8d8SChris Lattner       default:
410b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
411b9c1b51eSKate Stone                                        short_option);
41230fdc8d8SChris Lattner         break;
41330fdc8d8SChris Lattner       }
41430fdc8d8SChris Lattner 
41530fdc8d8SChris Lattner       return error;
41630fdc8d8SChris Lattner     }
4179e85e5a8SEugene Zelenko 
418b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
4197d49c9c8SJohnny Chen       m_condition.clear();
42087df91b8SJim Ingham       m_filenames.Clear();
42130fdc8d8SChris Lattner       m_line_num = 0;
42230fdc8d8SChris Lattner       m_column = 0;
423fab10e89SJim Ingham       m_func_names.clear();
4241f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
42530fdc8d8SChris Lattner       m_func_regexp.clear();
4261f746071SGreg Clayton       m_source_text_regexp.clear();
42787df91b8SJim Ingham       m_modules.Clear();
4281f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4292411167fSJim Ingham       m_offset_addr = 0;
430c982c768SGreg Clayton       m_ignore_count = 0;
4311b54c88cSJim Ingham       m_thread_id = LLDB_INVALID_THREAD_ID;
432c982c768SGreg Clayton       m_thread_index = UINT32_MAX;
4331b54c88cSJim Ingham       m_thread_name.clear();
4341b54c88cSJim Ingham       m_queue_name.clear();
435fab10e89SJim Ingham       m_catch_bp = false;
436fab10e89SJim Ingham       m_throw_bp = true;
437eb023e75SGreg Clayton       m_hardware = false;
438a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
43923b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
440a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
441ca36cd16SJim Ingham       m_one_shot = false;
44233df7cd3SJim Ingham       m_use_dummy = false;
4435e09c8c3SJim Ingham       m_breakpoint_names.clear();
444e732052fSJim Ingham       m_all_files = false;
445a72b31c7SJim Ingham       m_exception_extra_args.Clear();
446055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
44776bb8d67SJim Ingham       m_source_regex_func_names.clear();
44830fdc8d8SChris Lattner     }
44930fdc8d8SChris Lattner 
4501f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
45170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
4521f0f5b5bSZachary Turner     }
45330fdc8d8SChris Lattner 
4545a988416SJim Ingham     // Instance variables to hold the values for command options.
455969795f1SJim Ingham 
4565a988416SJim Ingham     std::string m_condition;
4575a988416SJim Ingham     FileSpecList m_filenames;
4585a988416SJim Ingham     uint32_t m_line_num;
4595a988416SJim Ingham     uint32_t m_column;
4605a988416SJim Ingham     std::vector<std::string> m_func_names;
4615e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
4625a988416SJim Ingham     uint32_t m_func_name_type_mask;
4635a988416SJim Ingham     std::string m_func_regexp;
4645a988416SJim Ingham     std::string m_source_text_regexp;
4655a988416SJim Ingham     FileSpecList m_modules;
4665a988416SJim Ingham     lldb::addr_t m_load_addr;
4672411167fSJim Ingham     lldb::addr_t m_offset_addr;
4685a988416SJim Ingham     uint32_t m_ignore_count;
4695a988416SJim Ingham     lldb::tid_t m_thread_id;
4705a988416SJim Ingham     uint32_t m_thread_index;
4715a988416SJim Ingham     std::string m_thread_name;
4725a988416SJim Ingham     std::string m_queue_name;
4735a988416SJim Ingham     bool m_catch_bp;
4745a988416SJim Ingham     bool m_throw_bp;
475eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
476a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
47723b1decbSDawn Perchik     lldb::LanguageType m_language;
4785a988416SJim Ingham     LazyBool m_skip_prologue;
479ca36cd16SJim Ingham     bool m_one_shot;
48033df7cd3SJim Ingham     bool m_use_dummy;
481e732052fSJim Ingham     bool m_all_files;
482a72b31c7SJim Ingham     Args m_exception_extra_args;
483055ad9beSIlia K     LazyBool m_move_to_nearest_code;
48476bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
4855a988416SJim Ingham   };
4865a988416SJim Ingham 
4875a988416SJim Ingham protected:
488b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
48933df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
49033df7cd3SJim Ingham 
491b9c1b51eSKate Stone     if (target == nullptr) {
492b9c1b51eSKate Stone       result.AppendError("Invalid target.  Must set target before setting "
493b9c1b51eSKate Stone                          "breakpoints (see 'target create' command).");
49430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
49530fdc8d8SChris Lattner       return false;
49630fdc8d8SChris Lattner     }
49730fdc8d8SChris Lattner 
49830fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
49930fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
50030fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
50130fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
502b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
503b9c1b51eSKate Stone     //   expression)
504b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
505b9c1b51eSKate Stone     //   to source text)
506b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
507b9c1b51eSKate Stone     //   given language.)
50830fdc8d8SChris Lattner 
50930fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
51030fdc8d8SChris Lattner 
51130fdc8d8SChris Lattner     if (m_options.m_line_num != 0)
51230fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
51330fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
51430fdc8d8SChris Lattner       break_type = eSetTypeAddress;
515fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
51630fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
51730fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
51830fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
519969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
520969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
521a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
522fab10e89SJim Ingham       break_type = eSetTypeException;
52330fdc8d8SChris Lattner 
5249e85e5a8SEugene Zelenko     Breakpoint *bp = nullptr;
525274060b6SGreg Clayton     FileSpec module_spec;
526a8558b62SJim Ingham     const bool internal = false;
527a8558b62SJim Ingham 
528b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
529b9c1b51eSKate Stone     // that off.
530b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
531b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5322411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5332411167fSJim Ingham 
534b9c1b51eSKate Stone     switch (break_type) {
53530fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
53630fdc8d8SChris Lattner     {
53730fdc8d8SChris Lattner       FileSpec file;
538c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
539b9c1b51eSKate Stone       if (num_files == 0) {
540b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
54187df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
54287df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
54387df91b8SJim Ingham           return false;
54487df91b8SJim Ingham         }
545b9c1b51eSKate Stone       } else if (num_files > 1) {
546b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
547b9c1b51eSKate Stone                            "line breakpoints.");
54887df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
54987df91b8SJim Ingham         return false;
550b9c1b51eSKate Stone       } else
55187df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
55230fdc8d8SChris Lattner 
5531f746071SGreg Clayton       // Only check for inline functions if
5541f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5551f746071SGreg Clayton 
556b9c1b51eSKate Stone       bp = target
557b9c1b51eSKate Stone                ->CreateBreakpoint(&(m_options.m_modules), file,
558b9c1b51eSKate Stone                                   m_options.m_line_num, m_options.m_offset_addr,
559b9c1b51eSKate Stone                                   check_inlines, m_options.m_skip_prologue,
560b9c1b51eSKate Stone                                   internal, m_options.m_hardware,
561b9c1b51eSKate Stone                                   m_options.m_move_to_nearest_code)
562b9c1b51eSKate Stone                .get();
563b9c1b51eSKate Stone     } break;
5646eee5aa0SGreg Clayton 
56530fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
566055a08a4SJim Ingham     {
567b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
568b9c1b51eSKate Stone       // with the library, and
569b9c1b51eSKate Stone       // use that.  That way the address breakpoint will track the load location
570b9c1b51eSKate Stone       // of the library.
571055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
572b9c1b51eSKate Stone       if (num_modules_specified == 1) {
573b9c1b51eSKate Stone         const FileSpec *file_spec =
574b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
575b9c1b51eSKate Stone         bp = target
576b9c1b51eSKate Stone                  ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
577b9c1b51eSKate Stone                                                    internal, file_spec,
578b9c1b51eSKate Stone                                                    m_options.m_hardware)
579b9c1b51eSKate Stone                  .get();
580b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
581b9c1b51eSKate Stone         bp = target
582b9c1b51eSKate Stone                  ->CreateBreakpoint(m_options.m_load_addr, internal,
583b9c1b51eSKate Stone                                     m_options.m_hardware)
584b9c1b51eSKate Stone                  .get();
585b9c1b51eSKate Stone       } else {
586b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
587b9c1b51eSKate Stone                            "address breakpoints.");
588055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
589055a08a4SJim Ingham         return false;
590055a08a4SJim Ingham       }
59130fdc8d8SChris Lattner       break;
592055a08a4SJim Ingham     }
59330fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
5940c5cd90dSGreg Clayton     {
5950c5cd90dSGreg Clayton       uint32_t name_type_mask = m_options.m_func_name_type_mask;
5960c5cd90dSGreg Clayton 
5970c5cd90dSGreg Clayton       if (name_type_mask == 0)
598e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
5990c5cd90dSGreg Clayton 
600b9c1b51eSKate Stone       bp = target
601b9c1b51eSKate Stone                ->CreateBreakpoint(
602b9c1b51eSKate Stone                    &(m_options.m_modules), &(m_options.m_filenames),
603b9c1b51eSKate Stone                    m_options.m_func_names, name_type_mask, m_options.m_language,
604b9c1b51eSKate Stone                    m_options.m_offset_addr, m_options.m_skip_prologue, internal,
605b9c1b51eSKate Stone                    m_options.m_hardware)
606b9c1b51eSKate Stone                .get();
607b9c1b51eSKate Stone     } break;
6080c5cd90dSGreg Clayton 
609b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
610b9c1b51eSKate Stone                                  // name
61130fdc8d8SChris Lattner       {
61295eae423SZachary Turner         RegularExpression regexp(m_options.m_func_regexp);
613b9c1b51eSKate Stone         if (!regexp.IsValid()) {
614969795f1SJim Ingham           char err_str[1024];
615969795f1SJim Ingham           regexp.GetErrorAsCString(err_str, sizeof(err_str));
616b9c1b51eSKate Stone           result.AppendErrorWithFormat(
617b9c1b51eSKate Stone               "Function name regular expression could not be compiled: \"%s\"",
618969795f1SJim Ingham               err_str);
61930fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
620969795f1SJim Ingham           return false;
62130fdc8d8SChris Lattner         }
62287df91b8SJim Ingham 
623b9c1b51eSKate Stone         bp = target
624b9c1b51eSKate Stone                  ->CreateFuncRegexBreakpoint(
625b9c1b51eSKate Stone                      &(m_options.m_modules), &(m_options.m_filenames), regexp,
626b9c1b51eSKate Stone                      m_options.m_language, m_options.m_skip_prologue, internal,
627b9c1b51eSKate Stone                      m_options.m_hardware)
628b9c1b51eSKate Stone                  .get();
629e14dc268SJim Ingham       }
630e14dc268SJim Ingham       break;
631969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
632969795f1SJim Ingham     {
633c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
63487df91b8SJim Ingham 
635b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
636969795f1SJim Ingham         FileSpec file;
637b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
638b9c1b51eSKate Stone           result.AppendError(
639b9c1b51eSKate Stone               "No files provided and could not find default file.");
64087df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
64187df91b8SJim Ingham           return false;
642b9c1b51eSKate Stone         } else {
64387df91b8SJim Ingham           m_options.m_filenames.Append(file);
64487df91b8SJim Ingham         }
64587df91b8SJim Ingham       }
6460c5cd90dSGreg Clayton 
64795eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
648b9c1b51eSKate Stone       if (!regexp.IsValid()) {
649969795f1SJim Ingham         char err_str[1024];
650969795f1SJim Ingham         regexp.GetErrorAsCString(err_str, sizeof(err_str));
651b9c1b51eSKate Stone         result.AppendErrorWithFormat(
652b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
653969795f1SJim Ingham             err_str);
654969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
655969795f1SJim Ingham         return false;
656969795f1SJim Ingham       }
657b9c1b51eSKate Stone       bp = target
658b9c1b51eSKate Stone                ->CreateSourceRegexBreakpoint(
659b9c1b51eSKate Stone                    &(m_options.m_modules), &(m_options.m_filenames),
660b9c1b51eSKate Stone                    m_options.m_source_regex_func_names, regexp, internal,
661b9c1b51eSKate Stone                    m_options.m_hardware, m_options.m_move_to_nearest_code)
662b9c1b51eSKate Stone                .get();
663b9c1b51eSKate Stone     } break;
664b9c1b51eSKate Stone     case eSetTypeException: {
665a72b31c7SJim Ingham       Error precond_error;
666b9c1b51eSKate Stone       bp = target
667b9c1b51eSKate Stone                ->CreateExceptionBreakpoint(
668b9c1b51eSKate Stone                    m_options.m_exception_language, m_options.m_catch_bp,
669b9c1b51eSKate Stone                    m_options.m_throw_bp, internal,
670b9c1b51eSKate Stone                    &m_options.m_exception_extra_args, &precond_error)
671b9c1b51eSKate Stone                .get();
672b9c1b51eSKate Stone       if (precond_error.Fail()) {
673b9c1b51eSKate Stone         result.AppendErrorWithFormat(
674b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
675a72b31c7SJim Ingham             precond_error.AsCString());
676a72b31c7SJim Ingham         target->RemoveBreakpointByID(bp->GetID());
677a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
678a72b31c7SJim Ingham         return false;
679a72b31c7SJim Ingham       }
680b9c1b51eSKate Stone     } break;
68130fdc8d8SChris Lattner     default:
68230fdc8d8SChris Lattner       break;
68330fdc8d8SChris Lattner     }
68430fdc8d8SChris Lattner 
6851b54c88cSJim Ingham     // Now set the various options that were passed in:
686b9c1b51eSKate Stone     if (bp) {
6871b54c88cSJim Ingham       if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
6881b54c88cSJim Ingham         bp->SetThreadID(m_options.m_thread_id);
6891b54c88cSJim Ingham 
690c982c768SGreg Clayton       if (m_options.m_thread_index != UINT32_MAX)
6911b54c88cSJim Ingham         bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
6921b54c88cSJim Ingham 
6931b54c88cSJim Ingham       if (!m_options.m_thread_name.empty())
694b9c1b51eSKate Stone         bp->GetOptions()->GetThreadSpec()->SetName(
695b9c1b51eSKate Stone             m_options.m_thread_name.c_str());
6961b54c88cSJim Ingham 
6971b54c88cSJim Ingham       if (!m_options.m_queue_name.empty())
698b9c1b51eSKate Stone         bp->GetOptions()->GetThreadSpec()->SetQueueName(
699b9c1b51eSKate Stone             m_options.m_queue_name.c_str());
7001b54c88cSJim Ingham 
701c982c768SGreg Clayton       if (m_options.m_ignore_count != 0)
7021b54c88cSJim Ingham         bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
7037d49c9c8SJohnny Chen 
7047d49c9c8SJohnny Chen       if (!m_options.m_condition.empty())
7057d49c9c8SJohnny Chen         bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
706ca36cd16SJim Ingham 
707b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
708ff9a91eaSJim Ingham         Error name_error;
709ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
710ff9a91eaSJim Ingham           bp->AddName(name.c_str(), name_error);
711ff9a91eaSJim Ingham           if (name_error.Fail()) {
712ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
713ff9a91eaSJim Ingham                                          name.c_str());
714ff9a91eaSJim Ingham             target->RemoveBreakpointByID(bp->GetID());
715ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
716ff9a91eaSJim Ingham             return false;
717ff9a91eaSJim Ingham           }
718ff9a91eaSJim Ingham         }
7195e09c8c3SJim Ingham       }
7205e09c8c3SJim Ingham 
721ca36cd16SJim Ingham       bp->SetOneShot(m_options.m_one_shot);
7221b54c88cSJim Ingham     }
7231b54c88cSJim Ingham 
724b9c1b51eSKate Stone     if (bp) {
72585e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7261391cc7dSJim Ingham       const bool show_locations = false;
727b9c1b51eSKate Stone       bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
728b9c1b51eSKate Stone                          show_locations);
7294aeb1989SJim Ingham       if (target == m_interpreter.GetDebugger().GetDummyTarget())
730b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
731b9c1b51eSKate Stone                              "into future targets.\n");
732b9c1b51eSKate Stone       else {
733b9c1b51eSKate Stone         // Don't print out this warning for exception breakpoints.  They can get
734b9c1b51eSKate Stone         // set before the target
735b9c1b51eSKate Stone         // is set, but we won't know how to actually set the breakpoint till we
736b9c1b51eSKate Stone         // run.
737b9c1b51eSKate Stone         if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
738b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
739b9c1b51eSKate Stone                                "actual locations.\n");
7404aeb1989SJim Ingham         }
7414aeb1989SJim Ingham       }
74230fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
743b9c1b51eSKate Stone     } else if (!bp) {
74430fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
74530fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
74630fdc8d8SChris Lattner     }
74730fdc8d8SChris Lattner 
74830fdc8d8SChris Lattner     return result.Succeeded();
74930fdc8d8SChris Lattner   }
75030fdc8d8SChris Lattner 
7515a988416SJim Ingham private:
752b9c1b51eSKate Stone   bool GetDefaultFile(Target *target, FileSpec &file,
753b9c1b51eSKate Stone                       CommandReturnObject &result) {
7545a988416SJim Ingham     uint32_t default_line;
7555a988416SJim Ingham     // First use the Source Manager's default file.
7565a988416SJim Ingham     // Then use the current stack frame's file.
757b9c1b51eSKate Stone     if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
758b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
759b9c1b51eSKate Stone       if (cur_frame == nullptr) {
760b9c1b51eSKate Stone         result.AppendError(
761b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7625a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7635a988416SJim Ingham         return false;
764b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
765b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
766b9c1b51eSKate Stone                            "file, it has no debug info.");
7675a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7685a988416SJim Ingham         return false;
769b9c1b51eSKate Stone       } else {
770b9c1b51eSKate Stone         const SymbolContext &sc =
771b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
772b9c1b51eSKate Stone         if (sc.line_entry.file) {
7735a988416SJim Ingham           file = sc.line_entry.file;
774b9c1b51eSKate Stone         } else {
775b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
776b9c1b51eSKate Stone                              "use as the default file.");
7775a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
7785a988416SJim Ingham           return false;
7795a988416SJim Ingham         }
7805a988416SJim Ingham       }
7815a988416SJim Ingham     }
7825a988416SJim Ingham     return true;
7835a988416SJim Ingham   }
7845a988416SJim Ingham 
7855a988416SJim Ingham   CommandOptions m_options;
7865a988416SJim Ingham };
7879e85e5a8SEugene Zelenko 
7885a988416SJim Ingham //-------------------------------------------------------------------------
7895a988416SJim Ingham // CommandObjectBreakpointModify
7905a988416SJim Ingham //-------------------------------------------------------------------------
7911f0f5b5bSZachary Turner 
7921f0f5b5bSZachary Turner #pragma mark Modify::CommandOptions
7931f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_modify_options[] = {
7941f0f5b5bSZachary Turner     // clang-format off
7951f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,       "Set the number of times this breakpoint is skipped before stopping." },
7961f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "one-shot",     'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,     "The breakpoint is deleted the first time it stop causes a stop." },
7971f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
7981f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID,    "The breakpoint stops only for the thread whose TID matches this argument." },
7991f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName,  "The breakpoint stops only for the thread whose thread name matches this argument." },
8001f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, 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." },
8011f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression,  "The breakpoint stops only if this condition expression evaluates to true." },
8021f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Enable the breakpoint." },
8031f0f5b5bSZachary Turner   { LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Disable the breakpoint." },
8041f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument,  nullptr, nullptr, 0, eArgTypeNone,        "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
8051f0f5b5bSZachary Turner     // clang-format on
8061f0f5b5bSZachary Turner };
8071f0f5b5bSZachary Turner 
8085a988416SJim Ingham #pragma mark Modify
8095a988416SJim Ingham 
810b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8115a988416SJim Ingham public:
812b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
813b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
814b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
815b9c1b51eSKate Stone                             "breakpoints in the executable.  "
816b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
817b9c1b51eSKate Stone                             "created breakpoint.  "
818b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
819b9c1b51eSKate Stone                             "empty argument clears the modification.",
8209e85e5a8SEugene Zelenko                             nullptr),
821b9c1b51eSKate Stone         m_options() {
8225a988416SJim Ingham     CommandArgumentEntry arg;
823b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
824b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
825b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
826b9c1b51eSKate Stone     // arguments vector.
8275a988416SJim Ingham     m_arguments.push_back(arg);
8285a988416SJim Ingham   }
8295a988416SJim Ingham 
8309e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8315a988416SJim Ingham 
832b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8335a988416SJim Ingham 
834b9c1b51eSKate Stone   class CommandOptions : public Options {
8355a988416SJim Ingham   public:
836b9c1b51eSKate Stone     CommandOptions()
837b9c1b51eSKate Stone         : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
838b9c1b51eSKate Stone           m_thread_id_passed(false), m_thread_index(UINT32_MAX),
839b9c1b51eSKate Stone           m_thread_index_passed(false), m_thread_name(), m_queue_name(),
840b9c1b51eSKate Stone           m_condition(), m_one_shot(false), m_enable_passed(false),
841b9c1b51eSKate Stone           m_enable_value(false), m_name_passed(false), m_queue_passed(false),
842b9c1b51eSKate Stone           m_condition_passed(false), m_one_shot_passed(false),
843b9c1b51eSKate Stone           m_use_dummy(false) {}
8445a988416SJim Ingham 
8459e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
8465a988416SJim Ingham 
847fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
848b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
8495a988416SJim Ingham       Error error;
8503bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
8515a988416SJim Ingham 
852b9c1b51eSKate Stone       switch (short_option) {
8535a988416SJim Ingham       case 'c':
854fe11483bSZachary Turner         m_condition = option_arg;
8555a988416SJim Ingham         m_condition_passed = true;
8565a988416SJim Ingham         break;
8575a988416SJim Ingham       case 'd':
8585a988416SJim Ingham         m_enable_passed = true;
8595a988416SJim Ingham         m_enable_value = false;
8605a988416SJim Ingham         break;
86133df7cd3SJim Ingham       case 'D':
86233df7cd3SJim Ingham         m_use_dummy = true;
86333df7cd3SJim Ingham         break;
8645a988416SJim Ingham       case 'e':
8655a988416SJim Ingham         m_enable_passed = true;
8665a988416SJim Ingham         m_enable_value = true;
8675a988416SJim Ingham         break;
8685a988416SJim Ingham       case 'i':
869fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_ignore_count))
870b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid ignore count '%s'",
871fe11483bSZachary Turner                                          option_arg.str().c_str());
8725a988416SJim Ingham         break;
873b9c1b51eSKate Stone       case 'o': {
874ca36cd16SJim Ingham         bool value, success;
875fe11483bSZachary Turner         value = Args::StringToBoolean(option_arg, false, &success);
876b9c1b51eSKate Stone         if (success) {
877ca36cd16SJim Ingham           m_one_shot_passed = true;
878ca36cd16SJim Ingham           m_one_shot = value;
879b9c1b51eSKate Stone         } else
880b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
881fe11483bSZachary Turner               "invalid boolean value '%s' passed for -o option",
882fe11483bSZachary Turner               option_arg.str().c_str());
883b9c1b51eSKate Stone       } break;
8845a988416SJim Ingham       case 't':
885b9c1b51eSKate Stone         if (option_arg[0] == '\0') {
8865a988416SJim Ingham           m_thread_id = LLDB_INVALID_THREAD_ID;
8875a988416SJim Ingham           m_thread_id_passed = true;
888b9c1b51eSKate Stone         } else {
889fe11483bSZachary Turner           if (option_arg.getAsInteger(0, m_thread_id))
890b9c1b51eSKate Stone             error.SetErrorStringWithFormat("invalid thread id string '%s'",
891fe11483bSZachary Turner                                            option_arg.str().c_str());
8925a988416SJim Ingham           else
8935a988416SJim Ingham             m_thread_id_passed = true;
8945a988416SJim Ingham         }
8955a988416SJim Ingham         break;
8965a988416SJim Ingham       case 'T':
897fe11483bSZachary Turner         m_thread_name = option_arg;
8985a988416SJim Ingham         m_name_passed = true;
8995a988416SJim Ingham         break;
9005a988416SJim Ingham       case 'q':
901fe11483bSZachary Turner         m_queue_name = option_arg;
9025a988416SJim Ingham         m_queue_passed = true;
9035a988416SJim Ingham         break;
9045a988416SJim Ingham       case 'x':
905b9c1b51eSKate Stone         if (option_arg[0] == '\n') {
9065a988416SJim Ingham           m_thread_index = UINT32_MAX;
9075a988416SJim Ingham           m_thread_index_passed = true;
908b9c1b51eSKate Stone         } else {
909fe11483bSZachary Turner           if (option_arg.getAsInteger(0, m_thread_index))
910b9c1b51eSKate Stone             error.SetErrorStringWithFormat("invalid thread index string '%s'",
911fe11483bSZachary Turner                                            option_arg.str().c_str());
9125a988416SJim Ingham           else
9135a988416SJim Ingham             m_thread_index_passed = true;
9145a988416SJim Ingham         }
9155a988416SJim Ingham         break;
9165a988416SJim Ingham       default:
917b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
918b9c1b51eSKate Stone                                        short_option);
9195a988416SJim Ingham         break;
9205a988416SJim Ingham       }
9215a988416SJim Ingham 
9225a988416SJim Ingham       return error;
9235a988416SJim Ingham     }
9249e85e5a8SEugene Zelenko 
925b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
9265a988416SJim Ingham       m_ignore_count = 0;
9275a988416SJim Ingham       m_thread_id = LLDB_INVALID_THREAD_ID;
9285a988416SJim Ingham       m_thread_id_passed = false;
9295a988416SJim Ingham       m_thread_index = UINT32_MAX;
9305a988416SJim Ingham       m_thread_index_passed = false;
9315a988416SJim Ingham       m_thread_name.clear();
9325a988416SJim Ingham       m_queue_name.clear();
9335a988416SJim Ingham       m_condition.clear();
934ca36cd16SJim Ingham       m_one_shot = false;
9355a988416SJim Ingham       m_enable_passed = false;
9365a988416SJim Ingham       m_queue_passed = false;
9375a988416SJim Ingham       m_name_passed = false;
9385a988416SJim Ingham       m_condition_passed = false;
939ca36cd16SJim Ingham       m_one_shot_passed = false;
94033df7cd3SJim Ingham       m_use_dummy = false;
9415a988416SJim Ingham     }
9425a988416SJim Ingham 
9431f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
94470602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_modify_options);
9451f0f5b5bSZachary Turner     }
9465a988416SJim Ingham 
9475a988416SJim Ingham     // Instance variables to hold the values for command options.
9485a988416SJim Ingham 
9495a988416SJim Ingham     uint32_t m_ignore_count;
9505a988416SJim Ingham     lldb::tid_t m_thread_id;
9515a988416SJim Ingham     bool m_thread_id_passed;
9525a988416SJim Ingham     uint32_t m_thread_index;
9535a988416SJim Ingham     bool m_thread_index_passed;
9545a988416SJim Ingham     std::string m_thread_name;
9555a988416SJim Ingham     std::string m_queue_name;
9565a988416SJim Ingham     std::string m_condition;
957ca36cd16SJim Ingham     bool m_one_shot;
9585a988416SJim Ingham     bool m_enable_passed;
9595a988416SJim Ingham     bool m_enable_value;
9605a988416SJim Ingham     bool m_name_passed;
9615a988416SJim Ingham     bool m_queue_passed;
9625a988416SJim Ingham     bool m_condition_passed;
963ca36cd16SJim Ingham     bool m_one_shot_passed;
96433df7cd3SJim Ingham     bool m_use_dummy;
9655a988416SJim Ingham   };
9665a988416SJim Ingham 
9675a988416SJim Ingham protected:
968b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
96933df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
970b9c1b51eSKate Stone     if (target == nullptr) {
9715a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
9725a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9735a988416SJim Ingham       return false;
9745a988416SJim Ingham     }
9755a988416SJim Ingham 
976bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
977bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
9785a988416SJim Ingham 
9795a988416SJim Ingham     BreakpointIDList valid_bp_ids;
9805a988416SJim Ingham 
981b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
982b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
9835a988416SJim Ingham 
984b9c1b51eSKate Stone     if (result.Succeeded()) {
9855a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
986b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
9875a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9885a988416SJim Ingham 
989b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
990b9c1b51eSKate Stone           Breakpoint *bp =
991b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
992b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
993b9c1b51eSKate Stone             BreakpointLocation *location =
994b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
995b9c1b51eSKate Stone             if (location) {
9965a988416SJim Ingham               if (m_options.m_thread_id_passed)
9975a988416SJim Ingham                 location->SetThreadID(m_options.m_thread_id);
9985a988416SJim Ingham 
9995a988416SJim Ingham               if (m_options.m_thread_index_passed)
10005a988416SJim Ingham                 location->SetThreadIndex(m_options.m_thread_index);
10015a988416SJim Ingham 
10025a988416SJim Ingham               if (m_options.m_name_passed)
10035a988416SJim Ingham                 location->SetThreadName(m_options.m_thread_name.c_str());
10045a988416SJim Ingham 
10055a988416SJim Ingham               if (m_options.m_queue_passed)
10065a988416SJim Ingham                 location->SetQueueName(m_options.m_queue_name.c_str());
10075a988416SJim Ingham 
10085a988416SJim Ingham               if (m_options.m_ignore_count != 0)
10095a988416SJim Ingham                 location->SetIgnoreCount(m_options.m_ignore_count);
10105a988416SJim Ingham 
10115a988416SJim Ingham               if (m_options.m_enable_passed)
10125a988416SJim Ingham                 location->SetEnabled(m_options.m_enable_value);
10135a988416SJim Ingham 
10145a988416SJim Ingham               if (m_options.m_condition_passed)
10155a988416SJim Ingham                 location->SetCondition(m_options.m_condition.c_str());
10165a988416SJim Ingham             }
1017b9c1b51eSKate Stone           } else {
10185a988416SJim Ingham             if (m_options.m_thread_id_passed)
10195a988416SJim Ingham               bp->SetThreadID(m_options.m_thread_id);
10205a988416SJim Ingham 
10215a988416SJim Ingham             if (m_options.m_thread_index_passed)
10225a988416SJim Ingham               bp->SetThreadIndex(m_options.m_thread_index);
10235a988416SJim Ingham 
10245a988416SJim Ingham             if (m_options.m_name_passed)
10255a988416SJim Ingham               bp->SetThreadName(m_options.m_thread_name.c_str());
10265a988416SJim Ingham 
10275a988416SJim Ingham             if (m_options.m_queue_passed)
10285a988416SJim Ingham               bp->SetQueueName(m_options.m_queue_name.c_str());
10295a988416SJim Ingham 
10305a988416SJim Ingham             if (m_options.m_ignore_count != 0)
10315a988416SJim Ingham               bp->SetIgnoreCount(m_options.m_ignore_count);
10325a988416SJim Ingham 
10335a988416SJim Ingham             if (m_options.m_enable_passed)
10345a988416SJim Ingham               bp->SetEnabled(m_options.m_enable_value);
10355a988416SJim Ingham 
10365a988416SJim Ingham             if (m_options.m_condition_passed)
10375a988416SJim Ingham               bp->SetCondition(m_options.m_condition.c_str());
10385a988416SJim Ingham           }
10395a988416SJim Ingham         }
10405a988416SJim Ingham       }
10415a988416SJim Ingham     }
10425a988416SJim Ingham 
10435a988416SJim Ingham     return result.Succeeded();
10445a988416SJim Ingham   }
10455a988416SJim Ingham 
10465a988416SJim Ingham private:
10475a988416SJim Ingham   CommandOptions m_options;
10485a988416SJim Ingham };
10495a988416SJim Ingham 
10505a988416SJim Ingham //-------------------------------------------------------------------------
10515a988416SJim Ingham // CommandObjectBreakpointEnable
10525a988416SJim Ingham //-------------------------------------------------------------------------
10535a988416SJim Ingham #pragma mark Enable
10545a988416SJim Ingham 
1055b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
10565a988416SJim Ingham public:
1057b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1058b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
1059b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
1060b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
1061b9c1b51eSKate Stone                             nullptr) {
10625a988416SJim Ingham     CommandArgumentEntry arg;
1063b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1064b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1065b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1066b9c1b51eSKate Stone     // arguments vector.
10675a988416SJim Ingham     m_arguments.push_back(arg);
10685a988416SJim Ingham   }
10695a988416SJim Ingham 
10709e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
10715a988416SJim Ingham 
10725a988416SJim Ingham protected:
1073b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1074893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1075b9c1b51eSKate Stone     if (target == nullptr) {
10765a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
10775a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10785a988416SJim Ingham       return false;
10795a988416SJim Ingham     }
10805a988416SJim Ingham 
1081bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1082bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
10835a988416SJim Ingham 
10845a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
10855a988416SJim Ingham 
10865a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10875a988416SJim Ingham 
1088b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10895a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
10905a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10915a988416SJim Ingham       return false;
10925a988416SJim Ingham     }
10935a988416SJim Ingham 
109411eb9c64SZachary Turner     if (command.empty()) {
10955a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
10965a988416SJim Ingham       target->EnableAllBreakpoints();
1097b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1098b9c1b51eSKate Stone                                      " breakpoints)\n",
1099b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
11005a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1101b9c1b51eSKate Stone     } else {
11025a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
11035a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1104b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1105b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
11065a988416SJim Ingham 
1107b9c1b51eSKate Stone       if (result.Succeeded()) {
11085a988416SJim Ingham         int enable_count = 0;
11095a988416SJim Ingham         int loc_count = 0;
11105a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1111b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
11125a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
11135a988416SJim Ingham 
1114b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1115b9c1b51eSKate Stone             Breakpoint *breakpoint =
1116b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1117b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1118b9c1b51eSKate Stone               BreakpointLocation *location =
1119b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1120b9c1b51eSKate Stone               if (location) {
11215a988416SJim Ingham                 location->SetEnabled(true);
11225a988416SJim Ingham                 ++loc_count;
11235a988416SJim Ingham               }
1124b9c1b51eSKate Stone             } else {
11255a988416SJim Ingham               breakpoint->SetEnabled(true);
11265a988416SJim Ingham               ++enable_count;
11275a988416SJim Ingham             }
11285a988416SJim Ingham           }
11295a988416SJim Ingham         }
1130b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1131b9c1b51eSKate Stone                                        enable_count + loc_count);
11325a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
11335a988416SJim Ingham       }
11345a988416SJim Ingham     }
11355a988416SJim Ingham 
11365a988416SJim Ingham     return result.Succeeded();
11375a988416SJim Ingham   }
11385a988416SJim Ingham };
11395a988416SJim Ingham 
11405a988416SJim Ingham //-------------------------------------------------------------------------
11415a988416SJim Ingham // CommandObjectBreakpointDisable
11425a988416SJim Ingham //-------------------------------------------------------------------------
11435a988416SJim Ingham #pragma mark Disable
11445a988416SJim Ingham 
1145b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
11465a988416SJim Ingham public:
11477428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1148b9c1b51eSKate Stone       : CommandObjectParsed(
1149b9c1b51eSKate Stone             interpreter, "breakpoint disable",
1150b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
11517428a18cSKate Stone             "them.  If none are specified, disable all "
11527428a18cSKate Stone             "breakpoints.",
1153b9c1b51eSKate Stone             nullptr) {
1154b9c1b51eSKate Stone     SetHelpLong(
1155b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
11567428a18cSKate Stone If none are specified, disable all breakpoints."
11577428a18cSKate Stone         R"(
1158ea671fbdSKate Stone 
11597428a18cSKate Stone )"
11607428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
11617428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
11627428a18cSKate Stone         R"(
1163ea671fbdSKate Stone 
1164ea671fbdSKate Stone     (lldb) break disable 1
1165ea671fbdSKate Stone     (lldb) break enable 1.1
1166ea671fbdSKate Stone 
1167ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1168ea671fbdSKate Stone 
1169ea671fbdSKate Stone     (lldb) break disable 1.*
1170ea671fbdSKate Stone     (lldb) break enable 1.1
1171ea671fbdSKate Stone 
11727428a18cSKate Stone )"
11737428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
11747428a18cSKate Stone the second re-enables the first location.");
1175b0fac509SJim Ingham 
11765a988416SJim Ingham     CommandArgumentEntry arg;
1177b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1178b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1179b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1180b9c1b51eSKate Stone     // arguments vector.
11815a988416SJim Ingham     m_arguments.push_back(arg);
11825a988416SJim Ingham   }
11835a988416SJim Ingham 
11849e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
11855a988416SJim Ingham 
11865a988416SJim Ingham protected:
1187b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1188893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1189b9c1b51eSKate Stone     if (target == nullptr) {
11905a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
11915a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
11925a988416SJim Ingham       return false;
11935a988416SJim Ingham     }
11945a988416SJim Ingham 
1195bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1196bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
11975a988416SJim Ingham 
11985a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
11995a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
12005a988416SJim Ingham 
1201b9c1b51eSKate Stone     if (num_breakpoints == 0) {
12025a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
12035a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
12045a988416SJim Ingham       return false;
12055a988416SJim Ingham     }
12065a988416SJim Ingham 
120711eb9c64SZachary Turner     if (command.empty()) {
12085a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
12095a988416SJim Ingham       target->DisableAllBreakpoints();
1210b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1211b9c1b51eSKate Stone                                      " breakpoints)\n",
1212b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
12135a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1214b9c1b51eSKate Stone     } else {
12155a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
12165a988416SJim Ingham       BreakpointIDList valid_bp_ids;
12175a988416SJim Ingham 
1218b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1219b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
12205a988416SJim Ingham 
1221b9c1b51eSKate Stone       if (result.Succeeded()) {
12225a988416SJim Ingham         int disable_count = 0;
12235a988416SJim Ingham         int loc_count = 0;
12245a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1225b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
12265a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
12275a988416SJim Ingham 
1228b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1229b9c1b51eSKate Stone             Breakpoint *breakpoint =
1230b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1231b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1232b9c1b51eSKate Stone               BreakpointLocation *location =
1233b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1234b9c1b51eSKate Stone               if (location) {
12355a988416SJim Ingham                 location->SetEnabled(false);
12365a988416SJim Ingham                 ++loc_count;
12375a988416SJim Ingham               }
1238b9c1b51eSKate Stone             } else {
12395a988416SJim Ingham               breakpoint->SetEnabled(false);
12405a988416SJim Ingham               ++disable_count;
12415a988416SJim Ingham             }
12425a988416SJim Ingham           }
12435a988416SJim Ingham         }
1244b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1245b9c1b51eSKate Stone                                        disable_count + loc_count);
12465a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
12475a988416SJim Ingham       }
12485a988416SJim Ingham     }
12495a988416SJim Ingham 
12505a988416SJim Ingham     return result.Succeeded();
12515a988416SJim Ingham   }
12525a988416SJim Ingham };
12535a988416SJim Ingham 
12545a988416SJim Ingham //-------------------------------------------------------------------------
12555a988416SJim Ingham // CommandObjectBreakpointList
12565a988416SJim Ingham //-------------------------------------------------------------------------
12571f0f5b5bSZachary Turner 
12581f0f5b5bSZachary Turner #pragma mark List::CommandOptions
12591f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_list_options[] = {
12601f0f5b5bSZachary Turner     // clang-format off
12611f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "internal",          'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
12621f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,   false, "brief",             'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
12631f0f5b5bSZachary Turner   // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
12641f0f5b5bSZachary Turner   // But I need to see it for now, and don't want to wait.
12651f0f5b5bSZachary Turner   { LLDB_OPT_SET_2,   false, "full",              'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
12661f0f5b5bSZachary 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)." },
12671f0f5b5bSZachary 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." },
12681f0f5b5bSZachary Turner     // clang-format on
12691f0f5b5bSZachary Turner };
12701f0f5b5bSZachary Turner 
12715a988416SJim Ingham #pragma mark List
12725a988416SJim Ingham 
1273b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
12745a988416SJim Ingham public:
1275b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1276b9c1b51eSKate Stone       : CommandObjectParsed(
1277b9c1b51eSKate Stone             interpreter, "breakpoint list",
12785a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
12799e85e5a8SEugene Zelenko             nullptr),
1280b9c1b51eSKate Stone         m_options() {
12815a988416SJim Ingham     CommandArgumentEntry arg;
12825a988416SJim Ingham     CommandArgumentData bp_id_arg;
12835a988416SJim Ingham 
12845a988416SJim Ingham     // Define the first (and only) variant of this arg.
12855a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
12865a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
12875a988416SJim Ingham 
1288b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1289b9c1b51eSKate Stone     // argument entry.
12905a988416SJim Ingham     arg.push_back(bp_id_arg);
12915a988416SJim Ingham 
12925a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
12935a988416SJim Ingham     m_arguments.push_back(arg);
12945a988416SJim Ingham   }
12955a988416SJim Ingham 
12969e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
12975a988416SJim Ingham 
1298b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12995a988416SJim Ingham 
1300b9c1b51eSKate Stone   class CommandOptions : public Options {
13015a988416SJim Ingham   public:
1302b9c1b51eSKate Stone     CommandOptions()
1303b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
13045a988416SJim Ingham     }
13055a988416SJim Ingham 
13069e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
13075a988416SJim Ingham 
1308fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1309b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
13105a988416SJim Ingham       Error error;
13113bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
13125a988416SJim Ingham 
1313b9c1b51eSKate Stone       switch (short_option) {
13145a988416SJim Ingham       case 'b':
13155a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
13165a988416SJim Ingham         break;
131733df7cd3SJim Ingham       case 'D':
131833df7cd3SJim Ingham         m_use_dummy = true;
131933df7cd3SJim Ingham         break;
13205a988416SJim Ingham       case 'f':
13215a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
13225a988416SJim Ingham         break;
13235a988416SJim Ingham       case 'v':
13245a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
13255a988416SJim Ingham         break;
13265a988416SJim Ingham       case 'i':
13275a988416SJim Ingham         m_internal = true;
13285a988416SJim Ingham         break;
13295a988416SJim Ingham       default:
1330b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1331b9c1b51eSKate Stone                                        short_option);
13325a988416SJim Ingham         break;
13335a988416SJim Ingham       }
13345a988416SJim Ingham 
13355a988416SJim Ingham       return error;
13365a988416SJim Ingham     }
13375a988416SJim Ingham 
1338b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
13395a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
13405a988416SJim Ingham       m_internal = false;
134133df7cd3SJim Ingham       m_use_dummy = false;
13425a988416SJim Ingham     }
13435a988416SJim Ingham 
13441f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
134570602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
13461f0f5b5bSZachary Turner     }
13475a988416SJim Ingham 
13485a988416SJim Ingham     // Instance variables to hold the values for command options.
13495a988416SJim Ingham 
13505a988416SJim Ingham     lldb::DescriptionLevel m_level;
13515a988416SJim Ingham 
13525a988416SJim Ingham     bool m_internal;
135333df7cd3SJim Ingham     bool m_use_dummy;
13545a988416SJim Ingham   };
13555a988416SJim Ingham 
13565a988416SJim Ingham protected:
1357b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
135833df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
135933df7cd3SJim Ingham 
1360b9c1b51eSKate Stone     if (target == nullptr) {
13615a988416SJim Ingham       result.AppendError("Invalid target. No current target or breakpoints.");
13625a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
13635a988416SJim Ingham       return true;
13645a988416SJim Ingham     }
13655a988416SJim Ingham 
1366b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1367b9c1b51eSKate Stone         target->GetBreakpointList(m_options.m_internal);
1368bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1369bb19a13cSSaleem Abdulrasool     target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
13705a988416SJim Ingham 
13715a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13725a988416SJim Ingham 
1373b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13745a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
13755a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
13765a988416SJim Ingham       return true;
13775a988416SJim Ingham     }
13785a988416SJim Ingham 
13795a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
13805a988416SJim Ingham 
138111eb9c64SZachary Turner     if (command.empty()) {
13825a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
13835a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1384b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13855a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
13865a988416SJim Ingham         AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
13875a988416SJim Ingham       }
13885a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1389b9c1b51eSKate Stone     } else {
13905a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
13915a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1392b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1393b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
13945a988416SJim Ingham 
1395b9c1b51eSKate Stone       if (result.Succeeded()) {
1396b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
13975a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1398b9c1b51eSKate Stone           Breakpoint *breakpoint =
1399b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1400b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1401b9c1b51eSKate Stone                                    m_options.m_level);
14025a988416SJim Ingham         }
14035a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1404b9c1b51eSKate Stone       } else {
14057428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
14065a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
14075a988416SJim Ingham       }
14085a988416SJim Ingham     }
14095a988416SJim Ingham 
14105a988416SJim Ingham     return result.Succeeded();
14115a988416SJim Ingham   }
14125a988416SJim Ingham 
14135a988416SJim Ingham private:
14145a988416SJim Ingham   CommandOptions m_options;
14155a988416SJim Ingham };
14165a988416SJim Ingham 
14175a988416SJim Ingham //-------------------------------------------------------------------------
14185a988416SJim Ingham // CommandObjectBreakpointClear
14195a988416SJim Ingham //-------------------------------------------------------------------------
14201f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
14211f0f5b5bSZachary Turner 
14221f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_clear_options[] = {
14231f0f5b5bSZachary Turner     // clang-format off
14241f0f5b5bSZachary 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." },
14251f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, true,  "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,  "Specify the breakpoint by source location at this particular line." }
14261f0f5b5bSZachary Turner     // clang-format on
14271f0f5b5bSZachary Turner };
14281f0f5b5bSZachary Turner 
14295a988416SJim Ingham #pragma mark Clear
14305a988416SJim Ingham 
1431b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
14325a988416SJim Ingham public:
1433b9c1b51eSKate Stone   typedef enum BreakpointClearType {
14345a988416SJim Ingham     eClearTypeInvalid,
14355a988416SJim Ingham     eClearTypeFileAndLine
14365a988416SJim Ingham   } BreakpointClearType;
14375a988416SJim Ingham 
14387428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
14397428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1440b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1441b9c1b51eSKate Stone                             "specified source file and line.",
14425a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1443b9c1b51eSKate Stone         m_options() {}
14445a988416SJim Ingham 
14459e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
14465a988416SJim Ingham 
1447b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
14485a988416SJim Ingham 
1449b9c1b51eSKate Stone   class CommandOptions : public Options {
14505a988416SJim Ingham   public:
1451b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
14525a988416SJim Ingham 
14539e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
14545a988416SJim Ingham 
1455fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1456b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
14575a988416SJim Ingham       Error error;
14583bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
14595a988416SJim Ingham 
1460b9c1b51eSKate Stone       switch (short_option) {
14615a988416SJim Ingham       case 'f':
14625a988416SJim Ingham         m_filename.assign(option_arg);
14635a988416SJim Ingham         break;
14645a988416SJim Ingham 
14655a988416SJim Ingham       case 'l':
1466fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
14675a988416SJim Ingham         break;
14685a988416SJim Ingham 
14695a988416SJim Ingham       default:
1470b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1471b9c1b51eSKate Stone                                        short_option);
14725a988416SJim Ingham         break;
14735a988416SJim Ingham       }
14745a988416SJim Ingham 
14755a988416SJim Ingham       return error;
14765a988416SJim Ingham     }
14775a988416SJim Ingham 
1478b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
14795a988416SJim Ingham       m_filename.clear();
14805a988416SJim Ingham       m_line_num = 0;
14815a988416SJim Ingham     }
14825a988416SJim Ingham 
14831f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
148470602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
14851f0f5b5bSZachary Turner     }
14865a988416SJim Ingham 
14875a988416SJim Ingham     // Instance variables to hold the values for command options.
14885a988416SJim Ingham 
14895a988416SJim Ingham     std::string m_filename;
14905a988416SJim Ingham     uint32_t m_line_num;
14915a988416SJim Ingham   };
14925a988416SJim Ingham 
14935a988416SJim Ingham protected:
1494b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1495893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1496b9c1b51eSKate Stone     if (target == nullptr) {
14975a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
14985a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14995a988416SJim Ingham       return false;
15005a988416SJim Ingham     }
15015a988416SJim Ingham 
15025a988416SJim Ingham     // The following are the various types of breakpoints that could be cleared:
15035a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
15045a988416SJim Ingham 
15055a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
15065a988416SJim Ingham 
15075a988416SJim Ingham     if (m_options.m_line_num != 0)
15085a988416SJim Ingham       break_type = eClearTypeFileAndLine;
15095a988416SJim Ingham 
1510bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1511bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
15125a988416SJim Ingham 
15135a988416SJim Ingham     BreakpointList &breakpoints = target->GetBreakpointList();
15145a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
15155a988416SJim Ingham 
15165a988416SJim Ingham     // Early return if there's no breakpoint at all.
1517b9c1b51eSKate Stone     if (num_breakpoints == 0) {
15185a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
15195a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15205a988416SJim Ingham       return result.Succeeded();
15215a988416SJim Ingham     }
15225a988416SJim Ingham 
15235a988416SJim Ingham     // Find matching breakpoints and delete them.
15245a988416SJim Ingham 
15255a988416SJim Ingham     // First create a copy of all the IDs.
15265a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
15275a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
15289e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
15295a988416SJim Ingham 
15305a988416SJim Ingham     int num_cleared = 0;
15315a988416SJim Ingham     StreamString ss;
1532b9c1b51eSKate Stone     switch (break_type) {
15335a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
15345a988416SJim Ingham     {
15355a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
15365a988416SJim Ingham       BreakpointLocationCollection loc_coll;
15375a988416SJim Ingham 
1538b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
15395a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
15405a988416SJim Ingham 
1541b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1542b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1543b9c1b51eSKate Stone           // remove the breakpoint.
1544b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
15455a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
15465a988416SJim Ingham             ss.EOL();
15475a988416SJim Ingham             target->RemoveBreakpointByID(bp->GetID());
15485a988416SJim Ingham             ++num_cleared;
15495a988416SJim Ingham           }
15505a988416SJim Ingham         }
15515a988416SJim Ingham       }
1552b9c1b51eSKate Stone     } break;
15535a988416SJim Ingham 
15545a988416SJim Ingham     default:
15555a988416SJim Ingham       break;
15565a988416SJim Ingham     }
15575a988416SJim Ingham 
1558b9c1b51eSKate Stone     if (num_cleared > 0) {
15595a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
15605a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1561c156427dSZachary Turner       output_stream << ss.GetString();
15625a988416SJim Ingham       output_stream.EOL();
15635a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1564b9c1b51eSKate Stone     } else {
15655a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
15665a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15675a988416SJim Ingham     }
15685a988416SJim Ingham 
15695a988416SJim Ingham     return result.Succeeded();
15705a988416SJim Ingham   }
15715a988416SJim Ingham 
15725a988416SJim Ingham private:
15735a988416SJim Ingham   CommandOptions m_options;
15745a988416SJim Ingham };
15755a988416SJim Ingham 
15765a988416SJim Ingham //-------------------------------------------------------------------------
15775a988416SJim Ingham // CommandObjectBreakpointDelete
15785a988416SJim Ingham //-------------------------------------------------------------------------
15791f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_delete_options[] = {
15801f0f5b5bSZachary Turner     // clang-format off
15811f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "force",             'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
15821f0f5b5bSZachary 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." },
15831f0f5b5bSZachary Turner     // clang-format on
15841f0f5b5bSZachary Turner };
15851f0f5b5bSZachary Turner 
15865a988416SJim Ingham #pragma mark Delete
15875a988416SJim Ingham 
1588b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
15895a988416SJim Ingham public:
1590b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1591b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1592b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1593b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
15949e85e5a8SEugene Zelenko                             nullptr),
1595b9c1b51eSKate Stone         m_options() {
15965a988416SJim Ingham     CommandArgumentEntry arg;
1597b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1598b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1599b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1600b9c1b51eSKate Stone     // arguments vector.
16015a988416SJim Ingham     m_arguments.push_back(arg);
16025a988416SJim Ingham   }
16035a988416SJim Ingham 
16049e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
16055a988416SJim Ingham 
1606b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
160733df7cd3SJim Ingham 
1608b9c1b51eSKate Stone   class CommandOptions : public Options {
160933df7cd3SJim Ingham   public:
1610b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
161133df7cd3SJim Ingham 
16129e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
161333df7cd3SJim Ingham 
1614fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1615b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
161633df7cd3SJim Ingham       Error error;
161733df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
161833df7cd3SJim Ingham 
1619b9c1b51eSKate Stone       switch (short_option) {
162033df7cd3SJim Ingham       case 'f':
162133df7cd3SJim Ingham         m_force = true;
162233df7cd3SJim Ingham         break;
162333df7cd3SJim Ingham 
162433df7cd3SJim Ingham       case 'D':
162533df7cd3SJim Ingham         m_use_dummy = true;
162633df7cd3SJim Ingham         break;
162733df7cd3SJim Ingham 
162833df7cd3SJim Ingham       default:
1629b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1630b9c1b51eSKate Stone                                        short_option);
163133df7cd3SJim Ingham         break;
163233df7cd3SJim Ingham       }
163333df7cd3SJim Ingham 
163433df7cd3SJim Ingham       return error;
163533df7cd3SJim Ingham     }
163633df7cd3SJim Ingham 
1637b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
163833df7cd3SJim Ingham       m_use_dummy = false;
163933df7cd3SJim Ingham       m_force = false;
164033df7cd3SJim Ingham     }
164133df7cd3SJim Ingham 
16421f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
164370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
16441f0f5b5bSZachary Turner     }
164533df7cd3SJim Ingham 
164633df7cd3SJim Ingham     // Instance variables to hold the values for command options.
164733df7cd3SJim Ingham     bool m_use_dummy;
164833df7cd3SJim Ingham     bool m_force;
164933df7cd3SJim Ingham   };
165033df7cd3SJim Ingham 
16515a988416SJim Ingham protected:
1652b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
165333df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
165433df7cd3SJim Ingham 
1655b9c1b51eSKate Stone     if (target == nullptr) {
16565a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
16575a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
16585a988416SJim Ingham       return false;
16595a988416SJim Ingham     }
16605a988416SJim Ingham 
1661bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1662bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
16635a988416SJim Ingham 
16645a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
16655a988416SJim Ingham 
16665a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
16675a988416SJim Ingham 
1668b9c1b51eSKate Stone     if (num_breakpoints == 0) {
16695a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
16705a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
16715a988416SJim Ingham       return false;
16725a988416SJim Ingham     }
16735a988416SJim Ingham 
167411eb9c64SZachary Turner     if (command.empty()) {
1675b9c1b51eSKate Stone       if (!m_options.m_force &&
1676b9c1b51eSKate Stone           !m_interpreter.Confirm(
1677b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1678b9c1b51eSKate Stone               true)) {
16795a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1680b9c1b51eSKate Stone       } else {
16815a988416SJim Ingham         target->RemoveAllBreakpoints();
1682b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1683b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1684b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
16855a988416SJim Ingham       }
16865a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1687b9c1b51eSKate Stone     } else {
16885a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
16895a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1690b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1691b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
16925a988416SJim Ingham 
1693b9c1b51eSKate Stone       if (result.Succeeded()) {
16945a988416SJim Ingham         int delete_count = 0;
16955a988416SJim Ingham         int disable_count = 0;
16965a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1697b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
16985a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
16995a988416SJim Ingham 
1700b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1701b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1702b9c1b51eSKate Stone               Breakpoint *breakpoint =
1703b9c1b51eSKate Stone                   target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1704b9c1b51eSKate Stone               BreakpointLocation *location =
1705b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1706b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1707b9c1b51eSKate Stone               // disable them instead.
1708b9c1b51eSKate Stone               if (location) {
17095a988416SJim Ingham                 location->SetEnabled(false);
17105a988416SJim Ingham                 ++disable_count;
17115a988416SJim Ingham               }
1712b9c1b51eSKate Stone             } else {
17135a988416SJim Ingham               target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
17145a988416SJim Ingham               ++delete_count;
17155a988416SJim Ingham             }
17165a988416SJim Ingham           }
17175a988416SJim Ingham         }
1718b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1719b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
17205a988416SJim Ingham             delete_count, disable_count);
17215a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
17225a988416SJim Ingham       }
17235a988416SJim Ingham     }
17245a988416SJim Ingham     return result.Succeeded();
17255a988416SJim Ingham   }
17269e85e5a8SEugene Zelenko 
172733df7cd3SJim Ingham private:
172833df7cd3SJim Ingham   CommandOptions m_options;
172933df7cd3SJim Ingham };
173033df7cd3SJim Ingham 
173130fdc8d8SChris Lattner //-------------------------------------------------------------------------
17325e09c8c3SJim Ingham // CommandObjectBreakpointName
17335e09c8c3SJim Ingham //-------------------------------------------------------------------------
17345e09c8c3SJim Ingham 
17357428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = {
1736ac9c3a62SKate Stone     // clang-format off
1737ac9c3a62SKate Stone   {LLDB_OPT_SET_1,   false, "name",              'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1738ac9c3a62SKate Stone   {LLDB_OPT_SET_2,   false, "breakpoint-id",     'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID,   "Specify a breakpoint ID to use."},
1739ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL, 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."},
1740ac9c3a62SKate Stone     // clang-format on
17415e09c8c3SJim Ingham };
1742b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
17435e09c8c3SJim Ingham public:
1744b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1745b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
17465e09c8c3SJim Ingham   }
17475e09c8c3SJim Ingham 
17489e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
17495e09c8c3SJim Ingham 
17501f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
175170602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
17525e09c8c3SJim Ingham   }
17535e09c8c3SJim Ingham 
1754fe11483bSZachary Turner   Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1755b9c1b51eSKate Stone                        ExecutionContext *execution_context) override {
17565e09c8c3SJim Ingham     Error error;
17575e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
17585e09c8c3SJim Ingham 
1759b9c1b51eSKate Stone     switch (short_option) {
17605e09c8c3SJim Ingham     case 'N':
1761fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1762b9c1b51eSKate Stone           error.Success())
1763fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
17645e09c8c3SJim Ingham       break;
17655e09c8c3SJim Ingham 
17665e09c8c3SJim Ingham     case 'B':
1767fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1768b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
17698cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1770fe11483bSZachary Turner             option_arg.str().c_str());
17715e09c8c3SJim Ingham       break;
17725e09c8c3SJim Ingham     case 'D':
1773fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1774b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
17758cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1776fe11483bSZachary Turner             option_arg.str().c_str());
17775e09c8c3SJim Ingham       break;
17785e09c8c3SJim Ingham 
17795e09c8c3SJim Ingham     default:
1780b9c1b51eSKate Stone       error.SetErrorStringWithFormat("unrecognized short option '%c'",
1781b9c1b51eSKate Stone                                      short_option);
17825e09c8c3SJim Ingham       break;
17835e09c8c3SJim Ingham     }
17845e09c8c3SJim Ingham     return error;
17855e09c8c3SJim Ingham   }
17865e09c8c3SJim Ingham 
1787b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
17885e09c8c3SJim Ingham     m_name.Clear();
17895e09c8c3SJim Ingham     m_breakpoint.Clear();
17905e09c8c3SJim Ingham     m_use_dummy.Clear();
17915e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
17925e09c8c3SJim Ingham   }
17935e09c8c3SJim Ingham 
17945e09c8c3SJim Ingham   OptionValueString m_name;
17955e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
17965e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
17975e09c8c3SJim Ingham };
17985e09c8c3SJim Ingham 
1799b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
18005e09c8c3SJim Ingham public:
1801b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1802b9c1b51eSKate Stone       : CommandObjectParsed(
1803b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
18045e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1805b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1806b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1807b9c1b51eSKate Stone     // command.
18085e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18095e09c8c3SJim Ingham     CommandArgumentData id_arg;
18105e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18115e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18125e09c8c3SJim Ingham     arg1.push_back(id_arg);
18135e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18145e09c8c3SJim Ingham 
18155e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18165e09c8c3SJim Ingham     m_option_group.Finalize();
18175e09c8c3SJim Ingham   }
18185e09c8c3SJim Ingham 
18199e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
18205e09c8c3SJim Ingham 
1821b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18225e09c8c3SJim Ingham 
18235e09c8c3SJim Ingham protected:
1824b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1825b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18265e09c8c3SJim Ingham       result.SetError("No name option provided.");
18275e09c8c3SJim Ingham       return false;
18285e09c8c3SJim Ingham     }
18295e09c8c3SJim Ingham 
1830b9c1b51eSKate Stone     Target *target =
1831b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18325e09c8c3SJim Ingham 
1833b9c1b51eSKate Stone     if (target == nullptr) {
18345e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
18355e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18365e09c8c3SJim Ingham       return false;
18375e09c8c3SJim Ingham     }
18385e09c8c3SJim Ingham 
1839bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1840bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
18415e09c8c3SJim Ingham 
18425e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
18435e09c8c3SJim Ingham 
18445e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1845b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18465e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18475e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18485e09c8c3SJim Ingham       return false;
18495e09c8c3SJim Ingham     }
18505e09c8c3SJim Ingham 
18515e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18525e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1853b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1854b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
18555e09c8c3SJim Ingham 
1856b9c1b51eSKate Stone     if (result.Succeeded()) {
1857b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18585e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18595e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18605e09c8c3SJim Ingham         return false;
18615e09c8c3SJim Ingham       }
18625e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1863b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1864b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1865b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18665e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1867b9c1b51eSKate Stone         Error error; // We don't need to check the error here, since the option
1868b9c1b51eSKate Stone                      // parser checked it...
18695e09c8c3SJim Ingham         bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
18705e09c8c3SJim Ingham       }
18715e09c8c3SJim Ingham     }
18725e09c8c3SJim Ingham 
18735e09c8c3SJim Ingham     return true;
18745e09c8c3SJim Ingham   }
18755e09c8c3SJim Ingham 
18765e09c8c3SJim Ingham private:
18775e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18785e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18795e09c8c3SJim Ingham };
18805e09c8c3SJim Ingham 
1881b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18825e09c8c3SJim Ingham public:
1883b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1884b9c1b51eSKate Stone       : CommandObjectParsed(
1885b9c1b51eSKate Stone             interpreter, "delete",
18865e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18875e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1888b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1889b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1890b9c1b51eSKate Stone     // command.
18915e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18925e09c8c3SJim Ingham     CommandArgumentData id_arg;
18935e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18945e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18955e09c8c3SJim Ingham     arg1.push_back(id_arg);
18965e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18975e09c8c3SJim Ingham 
18985e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18995e09c8c3SJim Ingham     m_option_group.Finalize();
19005e09c8c3SJim Ingham   }
19015e09c8c3SJim Ingham 
19029e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
19035e09c8c3SJim Ingham 
1904b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19055e09c8c3SJim Ingham 
19065e09c8c3SJim Ingham protected:
1907b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1908b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
19095e09c8c3SJim Ingham       result.SetError("No name option provided.");
19105e09c8c3SJim Ingham       return false;
19115e09c8c3SJim Ingham     }
19125e09c8c3SJim Ingham 
1913b9c1b51eSKate Stone     Target *target =
1914b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19155e09c8c3SJim Ingham 
1916b9c1b51eSKate Stone     if (target == nullptr) {
19175e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
19185e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19195e09c8c3SJim Ingham       return false;
19205e09c8c3SJim Ingham     }
19215e09c8c3SJim Ingham 
1922bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1923bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
19245e09c8c3SJim Ingham 
19255e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
19265e09c8c3SJim Ingham 
19275e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1928b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19295e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
19305e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19315e09c8c3SJim Ingham       return false;
19325e09c8c3SJim Ingham     }
19335e09c8c3SJim Ingham 
19345e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19355e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1936b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1937b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
19385e09c8c3SJim Ingham 
1939b9c1b51eSKate Stone     if (result.Succeeded()) {
1940b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19415e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
19425e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19435e09c8c3SJim Ingham         return false;
19445e09c8c3SJim Ingham       }
19455e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1946b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1947b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1948b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19495e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
19505e09c8c3SJim Ingham         bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
19515e09c8c3SJim Ingham       }
19525e09c8c3SJim Ingham     }
19535e09c8c3SJim Ingham 
19545e09c8c3SJim Ingham     return true;
19555e09c8c3SJim Ingham   }
19565e09c8c3SJim Ingham 
19575e09c8c3SJim Ingham private:
19585e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19595e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19605e09c8c3SJim Ingham };
19615e09c8c3SJim Ingham 
1962b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19635e09c8c3SJim Ingham public:
1964b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1965b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1966b9c1b51eSKate Stone                             "List either the names for a breakpoint or the "
1967b9c1b51eSKate Stone                             "breakpoints for a given name.",
19685e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1969b9c1b51eSKate Stone         m_name_options(), m_option_group() {
19705e09c8c3SJim Ingham     m_option_group.Append(&m_name_options);
19715e09c8c3SJim Ingham     m_option_group.Finalize();
19725e09c8c3SJim Ingham   }
19735e09c8c3SJim Ingham 
19749e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19755e09c8c3SJim Ingham 
1976b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19775e09c8c3SJim Ingham 
19785e09c8c3SJim Ingham protected:
1979b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1980b9c1b51eSKate Stone     Target *target =
1981b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19825e09c8c3SJim Ingham 
1983b9c1b51eSKate Stone     if (target == nullptr) {
19845e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
19855e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19865e09c8c3SJim Ingham       return false;
19875e09c8c3SJim Ingham     }
19885e09c8c3SJim Ingham 
1989b9c1b51eSKate Stone     if (m_name_options.m_name.OptionWasSet()) {
19905e09c8c3SJim Ingham       const char *name = m_name_options.m_name.GetCurrentValue();
1991bb19a13cSSaleem Abdulrasool       std::unique_lock<std::recursive_mutex> lock;
1992bb19a13cSSaleem Abdulrasool       target->GetBreakpointList().GetListMutex(lock);
19935e09c8c3SJim Ingham 
19945e09c8c3SJim Ingham       BreakpointList &breakpoints = target->GetBreakpointList();
1995b9c1b51eSKate Stone       for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1996b9c1b51eSKate Stone         if (bp_sp->MatchesName(name)) {
19975e09c8c3SJim Ingham           StreamString s;
19985e09c8c3SJim Ingham           bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19995e09c8c3SJim Ingham           s.EOL();
2000c156427dSZachary Turner           result.AppendMessage(s.GetString());
20015e09c8c3SJim Ingham         }
20025e09c8c3SJim Ingham       }
20035e09c8c3SJim Ingham 
2004b9c1b51eSKate Stone     } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2005b9c1b51eSKate Stone       BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2006b9c1b51eSKate Stone           m_name_options.m_breakpoint.GetCurrentValue());
2007b9c1b51eSKate Stone       if (bp_sp) {
20085e09c8c3SJim Ingham         std::vector<std::string> names;
20095e09c8c3SJim Ingham         bp_sp->GetNames(names);
20105e09c8c3SJim Ingham         result.AppendMessage("Names:");
20115e09c8c3SJim Ingham         for (auto name : names)
20125e09c8c3SJim Ingham           result.AppendMessageWithFormat("    %s\n", name.c_str());
2013b9c1b51eSKate Stone       } else {
2014b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2015b9c1b51eSKate Stone             "Could not find breakpoint %" PRId64 ".\n",
20165e09c8c3SJim Ingham             m_name_options.m_breakpoint.GetCurrentValue());
20175e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
20185e09c8c3SJim Ingham         return false;
20195e09c8c3SJim Ingham       }
2020b9c1b51eSKate Stone     } else {
20215e09c8c3SJim Ingham       result.SetError("Must specify -N or -B option to list.");
20225e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
20235e09c8c3SJim Ingham       return false;
20245e09c8c3SJim Ingham     }
20255e09c8c3SJim Ingham     return true;
20265e09c8c3SJim Ingham   }
20275e09c8c3SJim Ingham 
20285e09c8c3SJim Ingham private:
20295e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20305e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20315e09c8c3SJim Ingham };
20325e09c8c3SJim Ingham 
20335e09c8c3SJim Ingham //-------------------------------------------------------------------------
2034e14dc268SJim Ingham // CommandObjectBreakpointName
20355e09c8c3SJim Ingham //-------------------------------------------------------------------------
2036b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20375e09c8c3SJim Ingham public:
20387428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2039b9c1b51eSKate Stone       : CommandObjectMultiword(
2040b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2041b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2042b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2043b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2044b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2045b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2046b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2047b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
20485e09c8c3SJim Ingham 
20495e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20505e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20515e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
20525e09c8c3SJim Ingham   }
20535e09c8c3SJim Ingham 
20549e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20555e09c8c3SJim Ingham };
20565e09c8c3SJim Ingham 
20575e09c8c3SJim Ingham //-------------------------------------------------------------------------
2058e14dc268SJim Ingham // CommandObjectBreakpointRead
2059e14dc268SJim Ingham //-------------------------------------------------------------------------
20603acdf385SJim Ingham #pragma mark Read::CommandOptions
20611f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_read_options[] = {
20621f0f5b5bSZachary Turner     // clang-format off
20631f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, true, "file",                   'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,       "The file from which to read the breakpoints." },
20643acdf385SJim Ingham   {LLDB_OPT_SET_ALL, false, "breakpoint-name",        'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                       eArgTypeBreakpointName, "Only read in breakpoints with this name."},
20651f0f5b5bSZachary Turner     // clang-format on
20661f0f5b5bSZachary Turner };
20671f0f5b5bSZachary Turner 
20681f0f5b5bSZachary Turner #pragma mark Read
2069e14dc268SJim Ingham 
2070e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2071e14dc268SJim Ingham public:
2072e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2073e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2074e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2075e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2076e14dc268SJim Ingham                             nullptr),
2077e14dc268SJim Ingham         m_options() {
2078e14dc268SJim Ingham     CommandArgumentEntry arg;
2079e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2080e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2081e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2082e14dc268SJim Ingham     // arguments vector.
2083e14dc268SJim Ingham     m_arguments.push_back(arg);
2084e14dc268SJim Ingham   }
2085e14dc268SJim Ingham 
2086e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2087e14dc268SJim Ingham 
2088e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2089e14dc268SJim Ingham 
2090e14dc268SJim Ingham   class CommandOptions : public Options {
2091e14dc268SJim Ingham   public:
2092e14dc268SJim Ingham     CommandOptions() : Options() {}
2093e14dc268SJim Ingham 
2094e14dc268SJim Ingham     ~CommandOptions() override = default;
2095e14dc268SJim Ingham 
2096fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2097e14dc268SJim Ingham                          ExecutionContext *execution_context) override {
2098e14dc268SJim Ingham       Error error;
2099e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2100e14dc268SJim Ingham 
2101e14dc268SJim Ingham       switch (short_option) {
2102e14dc268SJim Ingham       case 'f':
2103e14dc268SJim Ingham         m_filename.assign(option_arg);
2104e14dc268SJim Ingham         break;
21053acdf385SJim Ingham       case 'N': {
21063acdf385SJim Ingham         Error name_error;
21073acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
21083acdf385SJim Ingham                                                   name_error)) {
21093acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21103acdf385SJim Ingham                                          name_error.AsCString());
21113acdf385SJim Ingham         }
21123acdf385SJim Ingham         m_names.push_back(option_arg);
21133acdf385SJim Ingham         break;
21143acdf385SJim Ingham       }
2115e14dc268SJim Ingham       default:
2116e14dc268SJim Ingham         error.SetErrorStringWithFormat("unrecognized option '%c'",
2117e14dc268SJim Ingham                                        short_option);
2118e14dc268SJim Ingham         break;
2119e14dc268SJim Ingham       }
2120e14dc268SJim Ingham 
2121e14dc268SJim Ingham       return error;
2122e14dc268SJim Ingham     }
2123e14dc268SJim Ingham 
2124e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2125e14dc268SJim Ingham       m_filename.clear();
21263acdf385SJim Ingham       m_names.clear();
2127e14dc268SJim Ingham     }
2128e14dc268SJim Ingham 
21291f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
213070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
21311f0f5b5bSZachary Turner     }
2132e14dc268SJim Ingham 
2133e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2134e14dc268SJim Ingham 
2135e14dc268SJim Ingham     std::string m_filename;
21363acdf385SJim Ingham     std::vector<std::string> m_names;
2137e14dc268SJim Ingham   };
2138e14dc268SJim Ingham 
2139e14dc268SJim Ingham protected:
2140e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2141e14dc268SJim Ingham     Target *target = GetSelectedOrDummyTarget();
2142e14dc268SJim Ingham     if (target == nullptr) {
2143e14dc268SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
2144e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
2145e14dc268SJim Ingham       return false;
2146e14dc268SJim Ingham     }
2147e14dc268SJim Ingham 
21483acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
21493acdf385SJim Ingham     target->GetBreakpointList().GetListMutex(lock);
21503acdf385SJim Ingham 
2151e14dc268SJim Ingham     FileSpec input_spec(m_options.m_filename, true);
215201f16664SJim Ingham     BreakpointIDList new_bps;
21533acdf385SJim Ingham     Error error = target->CreateBreakpointsFromFile(input_spec,
21543acdf385SJim Ingham                                                     m_options.m_names, new_bps);
2155e14dc268SJim Ingham 
2156e14dc268SJim Ingham     if (!error.Success()) {
215701f16664SJim Ingham       result.AppendError(error.AsCString());
2158e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
215901f16664SJim Ingham       return false;
2160e14dc268SJim Ingham     }
21613acdf385SJim Ingham 
21623acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
21633acdf385SJim Ingham 
21643acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
21653acdf385SJim Ingham     if (num_breakpoints == 0) {
21663acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
21673acdf385SJim Ingham     } else {
21683acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
21693acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
21703acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
21713acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
21723acdf385SJim Ingham         Breakpoint *bp = target->GetBreakpointList()
21733acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
21743acdf385SJim Ingham                              .get();
21753acdf385SJim Ingham         if (bp)
21763acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
21773acdf385SJim Ingham                              false);
21783acdf385SJim Ingham       }
21793acdf385SJim Ingham     }
2180e14dc268SJim Ingham     return result.Succeeded();
2181e14dc268SJim Ingham   }
2182e14dc268SJim Ingham 
2183e14dc268SJim Ingham private:
2184e14dc268SJim Ingham   CommandOptions m_options;
2185e14dc268SJim Ingham };
2186e14dc268SJim Ingham 
2187e14dc268SJim Ingham //-------------------------------------------------------------------------
2188e14dc268SJim Ingham // CommandObjectBreakpointWrite
2189e14dc268SJim Ingham //-------------------------------------------------------------------------
21901f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
21911f0f5b5bSZachary Turner static OptionDefinition g_breakpoint_write_options[] = {
21921f0f5b5bSZachary Turner     // clang-format off
21931f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, true,  "file",  'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,    "The file into which to write the breakpoints." },
21942d3628e1SJim Ingham   { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                       eArgTypeNone,        "Append to saved breakpoints file if it exists."},
21951f0f5b5bSZachary Turner     // clang-format on
21961f0f5b5bSZachary Turner };
21971f0f5b5bSZachary Turner 
21981f0f5b5bSZachary Turner #pragma mark Write
2199e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2200e14dc268SJim Ingham public:
2201e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2202e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2203e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2204e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2205e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2206e14dc268SJim Ingham                             nullptr),
2207e14dc268SJim Ingham         m_options() {
2208e14dc268SJim Ingham     CommandArgumentEntry arg;
2209e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2210e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2211e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2212e14dc268SJim Ingham     // arguments vector.
2213e14dc268SJim Ingham     m_arguments.push_back(arg);
2214e14dc268SJim Ingham   }
2215e14dc268SJim Ingham 
2216e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2217e14dc268SJim Ingham 
2218e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2219e14dc268SJim Ingham 
2220e14dc268SJim Ingham   class CommandOptions : public Options {
2221e14dc268SJim Ingham   public:
2222e14dc268SJim Ingham     CommandOptions() : Options() {}
2223e14dc268SJim Ingham 
2224e14dc268SJim Ingham     ~CommandOptions() override = default;
2225e14dc268SJim Ingham 
2226fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2227e14dc268SJim Ingham                          ExecutionContext *execution_context) override {
2228e14dc268SJim Ingham       Error error;
2229e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2230e14dc268SJim Ingham 
2231e14dc268SJim Ingham       switch (short_option) {
2232e14dc268SJim Ingham       case 'f':
2233e14dc268SJim Ingham         m_filename.assign(option_arg);
2234e14dc268SJim Ingham         break;
22352d3628e1SJim Ingham       case 'a':
22362d3628e1SJim Ingham         m_append = true;
22372d3628e1SJim Ingham         break;
2238e14dc268SJim Ingham       default:
2239e14dc268SJim Ingham         error.SetErrorStringWithFormat("unrecognized option '%c'",
2240e14dc268SJim Ingham                                        short_option);
2241e14dc268SJim Ingham         break;
2242e14dc268SJim Ingham       }
2243e14dc268SJim Ingham 
2244e14dc268SJim Ingham       return error;
2245e14dc268SJim Ingham     }
2246e14dc268SJim Ingham 
2247e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2248e14dc268SJim Ingham       m_filename.clear();
22492d3628e1SJim Ingham       m_append = false;
2250e14dc268SJim Ingham     }
2251e14dc268SJim Ingham 
22521f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
225370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
22541f0f5b5bSZachary Turner     }
2255e14dc268SJim Ingham 
2256e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2257e14dc268SJim Ingham 
2258e14dc268SJim Ingham     std::string m_filename;
22592d3628e1SJim Ingham     bool m_append = false;
2260e14dc268SJim Ingham   };
2261e14dc268SJim Ingham 
2262e14dc268SJim Ingham protected:
2263e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2264e14dc268SJim Ingham     Target *target = GetSelectedOrDummyTarget();
2265e14dc268SJim Ingham     if (target == nullptr) {
2266e14dc268SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
2267e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
2268e14dc268SJim Ingham       return false;
2269e14dc268SJim Ingham     }
2270e14dc268SJim Ingham 
2271e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2272e14dc268SJim Ingham     target->GetBreakpointList().GetListMutex(lock);
2273e14dc268SJim Ingham 
2274e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
227511eb9c64SZachary Turner     if (!command.empty()) {
2276e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2277e14dc268SJim Ingham           command, target, result, &valid_bp_ids);
2278e14dc268SJim Ingham 
227901f16664SJim Ingham       if (!result.Succeeded()) {
2280e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2281e14dc268SJim Ingham         return false;
2282e14dc268SJim Ingham       }
2283e14dc268SJim Ingham     }
228401f16664SJim Ingham     Error error = target->SerializeBreakpointsToFile(
2285771ef6d4SMalcolm Parsons         FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append);
228601f16664SJim Ingham     if (!error.Success()) {
228701f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
228801f16664SJim Ingham                                    error.AsCString());
228901f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2290e14dc268SJim Ingham     }
2291e14dc268SJim Ingham     return result.Succeeded();
2292e14dc268SJim Ingham   }
2293e14dc268SJim Ingham 
2294e14dc268SJim Ingham private:
2295e14dc268SJim Ingham   CommandOptions m_options;
2296e14dc268SJim Ingham };
2297e14dc268SJim Ingham 
2298e14dc268SJim Ingham //-------------------------------------------------------------------------
229930fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
230030fdc8d8SChris Lattner //-------------------------------------------------------------------------
2301ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
230230fdc8d8SChris Lattner 
2303b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2304b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2305b9c1b51eSKate Stone     : CommandObjectMultiword(
2306b9c1b51eSKate Stone           interpreter, "breakpoint",
23077428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2308b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2309b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2310b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2311b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2312b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2313b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2314b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2315b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2316b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2317b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2318b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2319b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2320b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2321b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2322b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2323b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2324b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2325b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2326b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2327e14dc268SJim Ingham   CommandObjectSP write_command_object(
2328e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2329e14dc268SJim Ingham   CommandObjectSP read_command_object(
2330e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
233130fdc8d8SChris Lattner 
2332b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
233330fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
233430fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2335b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2336b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2337ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2338b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2339b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
23405e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2341e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2342e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
234330fdc8d8SChris Lattner 
234423f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
234523f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
234623f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
234723f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
234823f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
234923f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
235023f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
235123f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
23525e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2353e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2354e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
235530fdc8d8SChris Lattner }
235630fdc8d8SChris Lattner 
23579e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
235830fdc8d8SChris Lattner 
2359b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
23605e09c8c3SJim Ingham                                                  bool allow_locations,
23615e09c8c3SJim Ingham                                                  CommandReturnObject &result,
2362b9c1b51eSKate Stone                                                  BreakpointIDList *valid_ids) {
236330fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2364b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2365b9c1b51eSKate Stone   //                                  canonical representation
2366b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2367b9c1b51eSKate Stone   //                                  representing a range (in which case there
2368b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2369b9c1b51eSKate Stone   //                                      after of one of the first two types.
23705e09c8c3SJim Ingham   //                                  4). A breakpoint name
2371b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2372b9c1b51eSKate Stone   // one.)
237330fdc8d8SChris Lattner 
237430fdc8d8SChris Lattner   Args temp_args;
237530fdc8d8SChris Lattner 
237611eb9c64SZachary Turner   if (args.empty()) {
2377b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2378b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2379b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
238036f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2381b9c1b51eSKate Stone     } else {
2382b9c1b51eSKate Stone       result.AppendError(
2383b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
238436f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
238536f3b369SJim Ingham     }
238636f3b369SJim Ingham     return;
238736f3b369SJim Ingham   }
238836f3b369SJim Ingham 
2389b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2390b9c1b51eSKate Stone   // directly from the old ARGS to
2391b9c1b51eSKate Stone   // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead
2392b9c1b51eSKate Stone   // generate a list of strings for
2393b9c1b51eSKate Stone   // all the breakpoint ids in the range, and shove all of those breakpoint id
2394b9c1b51eSKate Stone   // strings into TEMP_ARGS.
239530fdc8d8SChris Lattner 
2396b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2397b9c1b51eSKate Stone                                            result, temp_args);
239830fdc8d8SChris Lattner 
2399b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2400b9c1b51eSKate Stone   // BreakpointIDList:
240130fdc8d8SChris Lattner 
2402b9c1b51eSKate Stone   valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2403b9c1b51eSKate Stone                                temp_args.GetArgumentCount(), result);
240430fdc8d8SChris Lattner 
2405b9c1b51eSKate Stone   // At this point,  all of the breakpoint ids that the user passed in have been
2406b9c1b51eSKate Stone   // converted to breakpoint IDs
240730fdc8d8SChris Lattner   // and put into valid_ids.
240830fdc8d8SChris Lattner 
2409b9c1b51eSKate Stone   if (result.Succeeded()) {
2410b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
2411b9c1b51eSKate Stone     // ids, go through our tentative list
2412b9c1b51eSKate Stone     // of breakpoint id's and verify that they correspond to valid/currently set
2413b9c1b51eSKate Stone     // breakpoints.
241430fdc8d8SChris Lattner 
2415c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2416b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
241730fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2418b9c1b51eSKate Stone       Breakpoint *breakpoint =
2419b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2420b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2421c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2422b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
242330fdc8d8SChris Lattner           StreamString id_str;
2424b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2425b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2426c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2427b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2428b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
242930fdc8d8SChris Lattner               id_str.GetData());
243030fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
243130fdc8d8SChris Lattner         }
2432b9c1b51eSKate Stone       } else {
2433c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2434b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2435b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
24367428a18cSKate Stone             cur_bp_id.GetBreakpointID());
243730fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
243830fdc8d8SChris Lattner       }
243930fdc8d8SChris Lattner     }
244030fdc8d8SChris Lattner   }
244130fdc8d8SChris Lattner }
2442