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*b9c1b51eSKate Stone #include "lldb/Core/RegularExpression.h"
22*b9c1b51eSKate Stone #include "lldb/Core/StreamString.h"
235275aaa0SVince Harron #include "lldb/Host/StringConvert.h"
24*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h"
25*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
26*b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
2732abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
285e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
295e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
30*b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
310e0984eeSJim Ingham #include "lldb/Target/Language.h"
32b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
33*b9c1b51eSKate Stone #include "lldb/Target/Target.h"
341b54c88cSJim Ingham #include "lldb/Target/Thread.h"
351b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner using namespace lldb;
3830fdc8d8SChris Lattner using namespace lldb_private;
3930fdc8d8SChris Lattner 
40*b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
41*b9c1b51eSKate 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 
4830fdc8d8SChris Lattner //-------------------------------------------------------------------------
495a988416SJim Ingham // CommandObjectBreakpointSet
5030fdc8d8SChris Lattner //-------------------------------------------------------------------------
5130fdc8d8SChris Lattner 
52*b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
535a988416SJim Ingham public:
54*b9c1b51eSKate Stone   typedef enum BreakpointSetType {
555a988416SJim Ingham     eSetTypeInvalid,
565a988416SJim Ingham     eSetTypeFileAndLine,
575a988416SJim Ingham     eSetTypeAddress,
585a988416SJim Ingham     eSetTypeFunctionName,
595a988416SJim Ingham     eSetTypeFunctionRegexp,
605a988416SJim Ingham     eSetTypeSourceRegexp,
615a988416SJim Ingham     eSetTypeException
625a988416SJim Ingham   } BreakpointSetType;
635a988416SJim Ingham 
64*b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
65*b9c1b51eSKate Stone       : CommandObjectParsed(
66*b9c1b51eSKate Stone             interpreter, "breakpoint set",
675a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
685a988416SJim Ingham             "breakpoint set <cmd-options>"),
69*b9c1b51eSKate Stone         m_options() {}
705a988416SJim Ingham 
719e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
725a988416SJim Ingham 
73*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
745a988416SJim Ingham 
75*b9c1b51eSKate Stone   class CommandOptions : public Options {
765a988416SJim Ingham   public:
77*b9c1b51eSKate Stone     CommandOptions()
78*b9c1b51eSKate Stone         : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
79*b9c1b51eSKate Stone           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
80*b9c1b51eSKate Stone           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
81*b9c1b51eSKate Stone           m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
82*b9c1b51eSKate Stone           m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
83*b9c1b51eSKate Stone           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
84a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
8523b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
86*b9c1b51eSKate Stone           m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
87*b9c1b51eSKate Stone           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
8830fdc8d8SChris Lattner 
899e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
9087df91b8SJim Ingham 
91*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
92*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
9330fdc8d8SChris Lattner       Error error;
943bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
9530fdc8d8SChris Lattner 
96*b9c1b51eSKate Stone       switch (short_option) {
97*b9c1b51eSKate Stone       case 'a': {
98*b9c1b51eSKate Stone         m_load_addr = Args::StringToAddress(execution_context, option_arg,
99e1cfbc79STodd Fiala                                             LLDB_INVALID_ADDRESS, &error);
100*b9c1b51eSKate Stone       } break;
10130fdc8d8SChris Lattner 
102e732052fSJim Ingham       case 'A':
103e732052fSJim Ingham         m_all_files = true;
104e732052fSJim Ingham         break;
105e732052fSJim Ingham 
106ca36cd16SJim Ingham       case 'b':
107ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
108ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
109ca36cd16SJim Ingham         break;
110ca36cd16SJim Ingham 
111*b9c1b51eSKate Stone       case 'C': {
1126312991cSJim Ingham         bool success;
1136312991cSJim Ingham         m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success);
1146312991cSJim Ingham         if (!success)
115*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
116*b9c1b51eSKate Stone                                          option_arg);
11730fdc8d8SChris Lattner         break;
1186312991cSJim Ingham       }
1199e85e5a8SEugene Zelenko 
1207d49c9c8SJohnny Chen       case 'c':
1217d49c9c8SJohnny Chen         m_condition.assign(option_arg);
1227d49c9c8SJohnny Chen         break;
1237d49c9c8SJohnny Chen 
12433df7cd3SJim Ingham       case 'D':
12533df7cd3SJim Ingham         m_use_dummy = true;
12633df7cd3SJim Ingham         break;
12733df7cd3SJim Ingham 
128*b9c1b51eSKate Stone       case 'E': {
1290e0984eeSJim Ingham         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
130fab10e89SJim Ingham 
131*b9c1b51eSKate Stone         switch (language) {
132fab10e89SJim Ingham         case eLanguageTypeC89:
133fab10e89SJim Ingham         case eLanguageTypeC:
134fab10e89SJim Ingham         case eLanguageTypeC99:
1351d0089faSBruce Mitchener         case eLanguageTypeC11:
136a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
137fab10e89SJim Ingham           break;
138fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
1391d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
1401d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
1412ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
142a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
143fab10e89SJim Ingham           break;
144fab10e89SJim Ingham         case eLanguageTypeObjC:
145a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
146fab10e89SJim Ingham           break;
147fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
148*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
149*b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
150fab10e89SJim Ingham           break;
151fab10e89SJim Ingham         case eLanguageTypeUnknown:
152*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
153*b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
154*b9c1b51eSKate Stone               option_arg);
155fab10e89SJim Ingham           break;
156fab10e89SJim Ingham         default:
157*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
158*b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
159*b9c1b51eSKate Stone               option_arg);
160fab10e89SJim Ingham         }
161*b9c1b51eSKate Stone       } break;
162ca36cd16SJim Ingham 
163ca36cd16SJim Ingham       case 'f':
164ca36cd16SJim Ingham         m_filenames.AppendIfUnique(FileSpec(option_arg, false));
165fab10e89SJim Ingham         break;
166ca36cd16SJim Ingham 
167ca36cd16SJim Ingham       case 'F':
168ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
169ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
170ca36cd16SJim Ingham         break;
171ca36cd16SJim Ingham 
172*b9c1b51eSKate Stone       case 'h': {
173fab10e89SJim Ingham         bool success;
174fab10e89SJim Ingham         m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
175fab10e89SJim Ingham         if (!success)
176*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
177*b9c1b51eSKate Stone               "Invalid boolean value for on-catch option: '%s'", option_arg);
178*b9c1b51eSKate Stone       } break;
179eb023e75SGreg Clayton 
180eb023e75SGreg Clayton       case 'H':
181eb023e75SGreg Clayton         m_hardware = true;
182eb023e75SGreg Clayton         break;
183eb023e75SGreg Clayton 
184ca36cd16SJim Ingham       case 'i':
1855275aaa0SVince Harron         m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
186ca36cd16SJim Ingham         if (m_ignore_count == UINT32_MAX)
187*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid ignore count '%s'",
188*b9c1b51eSKate Stone                                          option_arg);
189ca36cd16SJim Ingham         break;
190ca36cd16SJim Ingham 
191*b9c1b51eSKate Stone       case 'K': {
192a8558b62SJim Ingham         bool success;
193a8558b62SJim Ingham         bool value;
194a8558b62SJim Ingham         value = Args::StringToBoolean(option_arg, true, &success);
195a8558b62SJim Ingham         if (value)
196a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
197a8558b62SJim Ingham         else
198a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
199a8558b62SJim Ingham 
200a8558b62SJim Ingham         if (!success)
201*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
202*b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
203*b9c1b51eSKate Stone               option_arg);
204*b9c1b51eSKate Stone       } break;
205ca36cd16SJim Ingham 
206*b9c1b51eSKate Stone       case 'l': {
2076312991cSJim Ingham         bool success;
2086312991cSJim Ingham         m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
2096312991cSJim Ingham         if (!success)
210*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
211*b9c1b51eSKate Stone                                          option_arg);
212ca36cd16SJim Ingham         break;
2136312991cSJim Ingham       }
214055ad9beSIlia K 
21523b1decbSDawn Perchik       case 'L':
2160e0984eeSJim Ingham         m_language = Language::GetLanguageTypeFromString(option_arg);
21723b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
218*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
219*b9c1b51eSKate Stone               "Unknown language type: '%s' for breakpoint", option_arg);
22023b1decbSDawn Perchik         break;
22123b1decbSDawn Perchik 
222*b9c1b51eSKate Stone       case 'm': {
223055ad9beSIlia K         bool success;
224055ad9beSIlia K         bool value;
225055ad9beSIlia K         value = Args::StringToBoolean(option_arg, true, &success);
226055ad9beSIlia K         if (value)
227055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
228055ad9beSIlia K         else
229055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
230055ad9beSIlia K 
231055ad9beSIlia K         if (!success)
232*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
233*b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
234*b9c1b51eSKate Stone               option_arg);
235055ad9beSIlia K         break;
236055ad9beSIlia K       }
237055ad9beSIlia K 
238ca36cd16SJim Ingham       case 'M':
239ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
240ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
241ca36cd16SJim Ingham         break;
242ca36cd16SJim Ingham 
243ca36cd16SJim Ingham       case 'n':
244ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
245ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
246ca36cd16SJim Ingham         break;
247ca36cd16SJim Ingham 
2485e09c8c3SJim Ingham       case 'N':
2495e09c8c3SJim Ingham         if (BreakpointID::StringIsBreakpointName(option_arg, error))
2505e09c8c3SJim Ingham           m_breakpoint_names.push_back(option_arg);
2515e09c8c3SJim Ingham         break;
2525e09c8c3SJim Ingham 
253*b9c1b51eSKate Stone       case 'R': {
2542411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
255e1cfbc79STodd Fiala         tmp_offset_addr =
256*b9c1b51eSKate Stone             Args::StringToAddress(execution_context, option_arg, 0, &error);
2572411167fSJim Ingham         if (error.Success())
2582411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
259*b9c1b51eSKate Stone       } break;
2602411167fSJim Ingham 
261ca36cd16SJim Ingham       case 'o':
262ca36cd16SJim Ingham         m_one_shot = true;
263ca36cd16SJim Ingham         break;
264ca36cd16SJim Ingham 
265a72b31c7SJim Ingham       case 'O':
266a72b31c7SJim Ingham         m_exception_extra_args.AppendArgument("-O");
267a72b31c7SJim Ingham         m_exception_extra_args.AppendArgument(option_arg);
268a72b31c7SJim Ingham         break;
269a72b31c7SJim Ingham 
270ca36cd16SJim Ingham       case 'p':
271ca36cd16SJim Ingham         m_source_text_regexp.assign(option_arg);
272ca36cd16SJim Ingham         break;
273ca36cd16SJim Ingham 
274ca36cd16SJim Ingham       case 'q':
275ca36cd16SJim Ingham         m_queue_name.assign(option_arg);
276ca36cd16SJim Ingham         break;
277ca36cd16SJim Ingham 
278ca36cd16SJim Ingham       case 'r':
279ca36cd16SJim Ingham         m_func_regexp.assign(option_arg);
280ca36cd16SJim Ingham         break;
281ca36cd16SJim Ingham 
282ca36cd16SJim Ingham       case 's':
283ca36cd16SJim Ingham         m_modules.AppendIfUnique(FileSpec(option_arg, false));
284ca36cd16SJim Ingham         break;
285ca36cd16SJim Ingham 
286ca36cd16SJim Ingham       case 'S':
287ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
288ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
289ca36cd16SJim Ingham         break;
290ca36cd16SJim Ingham 
291ca36cd16SJim Ingham       case 't':
292*b9c1b51eSKate Stone         m_thread_id =
293*b9c1b51eSKate Stone             StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
294ca36cd16SJim Ingham         if (m_thread_id == LLDB_INVALID_THREAD_ID)
295*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid thread id string '%s'",
296*b9c1b51eSKate Stone                                          option_arg);
297ca36cd16SJim Ingham         break;
298ca36cd16SJim Ingham 
299ca36cd16SJim Ingham       case 'T':
300ca36cd16SJim Ingham         m_thread_name.assign(option_arg);
301ca36cd16SJim Ingham         break;
302ca36cd16SJim Ingham 
303*b9c1b51eSKate Stone       case 'w': {
304ca36cd16SJim Ingham         bool success;
305ca36cd16SJim Ingham         m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
306ca36cd16SJim Ingham         if (!success)
307*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
308*b9c1b51eSKate Stone               "Invalid boolean value for on-throw option: '%s'", option_arg);
309*b9c1b51eSKate Stone       } break;
310ca36cd16SJim Ingham 
311ca36cd16SJim Ingham       case 'x':
3125275aaa0SVince Harron         m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
313ca36cd16SJim Ingham         if (m_thread_id == UINT32_MAX)
314*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid thread index string '%s'",
315*b9c1b51eSKate Stone                                          option_arg);
316ca36cd16SJim Ingham         break;
317ca36cd16SJim Ingham 
31876bb8d67SJim Ingham       case 'X':
31976bb8d67SJim Ingham         m_source_regex_func_names.insert(option_arg);
32076bb8d67SJim Ingham         break;
32176bb8d67SJim Ingham 
32230fdc8d8SChris Lattner       default:
323*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
324*b9c1b51eSKate Stone                                        short_option);
32530fdc8d8SChris Lattner         break;
32630fdc8d8SChris Lattner       }
32730fdc8d8SChris Lattner 
32830fdc8d8SChris Lattner       return error;
32930fdc8d8SChris Lattner     }
3309e85e5a8SEugene Zelenko 
331*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
3327d49c9c8SJohnny Chen       m_condition.clear();
33387df91b8SJim Ingham       m_filenames.Clear();
33430fdc8d8SChris Lattner       m_line_num = 0;
33530fdc8d8SChris Lattner       m_column = 0;
336fab10e89SJim Ingham       m_func_names.clear();
3371f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
33830fdc8d8SChris Lattner       m_func_regexp.clear();
3391f746071SGreg Clayton       m_source_text_regexp.clear();
34087df91b8SJim Ingham       m_modules.Clear();
3411f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
3422411167fSJim Ingham       m_offset_addr = 0;
343c982c768SGreg Clayton       m_ignore_count = 0;
3441b54c88cSJim Ingham       m_thread_id = LLDB_INVALID_THREAD_ID;
345c982c768SGreg Clayton       m_thread_index = UINT32_MAX;
3461b54c88cSJim Ingham       m_thread_name.clear();
3471b54c88cSJim Ingham       m_queue_name.clear();
348fab10e89SJim Ingham       m_catch_bp = false;
349fab10e89SJim Ingham       m_throw_bp = true;
350eb023e75SGreg Clayton       m_hardware = false;
351a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
35223b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
353a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
354ca36cd16SJim Ingham       m_one_shot = false;
35533df7cd3SJim Ingham       m_use_dummy = false;
3565e09c8c3SJim Ingham       m_breakpoint_names.clear();
357e732052fSJim Ingham       m_all_files = false;
358a72b31c7SJim Ingham       m_exception_extra_args.Clear();
359055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
36076bb8d67SJim Ingham       m_source_regex_func_names.clear();
36130fdc8d8SChris Lattner     }
36230fdc8d8SChris Lattner 
363*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
36430fdc8d8SChris Lattner 
3655a988416SJim Ingham     // Options table: Required for subclasses of Options.
36630fdc8d8SChris Lattner 
3675a988416SJim Ingham     static OptionDefinition g_option_table[];
36830fdc8d8SChris Lattner 
3695a988416SJim Ingham     // Instance variables to hold the values for command options.
370969795f1SJim Ingham 
3715a988416SJim Ingham     std::string m_condition;
3725a988416SJim Ingham     FileSpecList m_filenames;
3735a988416SJim Ingham     uint32_t m_line_num;
3745a988416SJim Ingham     uint32_t m_column;
3755a988416SJim Ingham     std::vector<std::string> m_func_names;
3765e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
3775a988416SJim Ingham     uint32_t m_func_name_type_mask;
3785a988416SJim Ingham     std::string m_func_regexp;
3795a988416SJim Ingham     std::string m_source_text_regexp;
3805a988416SJim Ingham     FileSpecList m_modules;
3815a988416SJim Ingham     lldb::addr_t m_load_addr;
3822411167fSJim Ingham     lldb::addr_t m_offset_addr;
3835a988416SJim Ingham     uint32_t m_ignore_count;
3845a988416SJim Ingham     lldb::tid_t m_thread_id;
3855a988416SJim Ingham     uint32_t m_thread_index;
3865a988416SJim Ingham     std::string m_thread_name;
3875a988416SJim Ingham     std::string m_queue_name;
3885a988416SJim Ingham     bool m_catch_bp;
3895a988416SJim Ingham     bool m_throw_bp;
390eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
391a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
39223b1decbSDawn Perchik     lldb::LanguageType m_language;
3935a988416SJim Ingham     LazyBool m_skip_prologue;
394ca36cd16SJim Ingham     bool m_one_shot;
39533df7cd3SJim Ingham     bool m_use_dummy;
396e732052fSJim Ingham     bool m_all_files;
397a72b31c7SJim Ingham     Args m_exception_extra_args;
398055ad9beSIlia K     LazyBool m_move_to_nearest_code;
39976bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
4005a988416SJim Ingham   };
4015a988416SJim Ingham 
4025a988416SJim Ingham protected:
403*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
40433df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
40533df7cd3SJim Ingham 
406*b9c1b51eSKate Stone     if (target == nullptr) {
407*b9c1b51eSKate Stone       result.AppendError("Invalid target.  Must set target before setting "
408*b9c1b51eSKate Stone                          "breakpoints (see 'target create' command).");
40930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
41030fdc8d8SChris Lattner       return false;
41130fdc8d8SChris Lattner     }
41230fdc8d8SChris Lattner 
41330fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
41430fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
41530fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
41630fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
417*b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
418*b9c1b51eSKate Stone     //   expression)
419*b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
420*b9c1b51eSKate Stone     //   to source text)
421*b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
422*b9c1b51eSKate Stone     //   given language.)
42330fdc8d8SChris Lattner 
42430fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
42530fdc8d8SChris Lattner 
42630fdc8d8SChris Lattner     if (m_options.m_line_num != 0)
42730fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
42830fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
42930fdc8d8SChris Lattner       break_type = eSetTypeAddress;
430fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
43130fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
43230fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
43330fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
434969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
435969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
436a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
437fab10e89SJim Ingham       break_type = eSetTypeException;
43830fdc8d8SChris Lattner 
4399e85e5a8SEugene Zelenko     Breakpoint *bp = nullptr;
440274060b6SGreg Clayton     FileSpec module_spec;
441a8558b62SJim Ingham     const bool internal = false;
442a8558b62SJim Ingham 
443*b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
444*b9c1b51eSKate Stone     // that off.
445*b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
446*b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
4472411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
4482411167fSJim Ingham 
449*b9c1b51eSKate Stone     switch (break_type) {
45030fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
45130fdc8d8SChris Lattner     {
45230fdc8d8SChris Lattner       FileSpec file;
453c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
454*b9c1b51eSKate Stone       if (num_files == 0) {
455*b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
45687df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
45787df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
45887df91b8SJim Ingham           return false;
45987df91b8SJim Ingham         }
460*b9c1b51eSKate Stone       } else if (num_files > 1) {
461*b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
462*b9c1b51eSKate Stone                            "line breakpoints.");
46387df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
46487df91b8SJim Ingham         return false;
465*b9c1b51eSKate Stone       } else
46687df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
46730fdc8d8SChris Lattner 
4681f746071SGreg Clayton       // Only check for inline functions if
4691f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
4701f746071SGreg Clayton 
471*b9c1b51eSKate Stone       bp = target
472*b9c1b51eSKate Stone                ->CreateBreakpoint(&(m_options.m_modules), file,
473*b9c1b51eSKate Stone                                   m_options.m_line_num, m_options.m_offset_addr,
474*b9c1b51eSKate Stone                                   check_inlines, m_options.m_skip_prologue,
475*b9c1b51eSKate Stone                                   internal, m_options.m_hardware,
476*b9c1b51eSKate Stone                                   m_options.m_move_to_nearest_code)
477*b9c1b51eSKate Stone                .get();
478*b9c1b51eSKate Stone     } break;
4796eee5aa0SGreg Clayton 
48030fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
481055a08a4SJim Ingham     {
482*b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
483*b9c1b51eSKate Stone       // with the library, and
484*b9c1b51eSKate Stone       // use that.  That way the address breakpoint will track the load location
485*b9c1b51eSKate Stone       // of the library.
486055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
487*b9c1b51eSKate Stone       if (num_modules_specified == 1) {
488*b9c1b51eSKate Stone         const FileSpec *file_spec =
489*b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
490*b9c1b51eSKate Stone         bp = target
491*b9c1b51eSKate Stone                  ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
492*b9c1b51eSKate Stone                                                    internal, file_spec,
493*b9c1b51eSKate Stone                                                    m_options.m_hardware)
494*b9c1b51eSKate Stone                  .get();
495*b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
496*b9c1b51eSKate Stone         bp = target
497*b9c1b51eSKate Stone                  ->CreateBreakpoint(m_options.m_load_addr, internal,
498*b9c1b51eSKate Stone                                     m_options.m_hardware)
499*b9c1b51eSKate Stone                  .get();
500*b9c1b51eSKate Stone       } else {
501*b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
502*b9c1b51eSKate Stone                            "address breakpoints.");
503055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
504055a08a4SJim Ingham         return false;
505055a08a4SJim Ingham       }
50630fdc8d8SChris Lattner       break;
507055a08a4SJim Ingham     }
50830fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
5090c5cd90dSGreg Clayton     {
5100c5cd90dSGreg Clayton       uint32_t name_type_mask = m_options.m_func_name_type_mask;
5110c5cd90dSGreg Clayton 
5120c5cd90dSGreg Clayton       if (name_type_mask == 0)
513e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
5140c5cd90dSGreg Clayton 
515*b9c1b51eSKate Stone       bp = target
516*b9c1b51eSKate Stone                ->CreateBreakpoint(
517*b9c1b51eSKate Stone                    &(m_options.m_modules), &(m_options.m_filenames),
518*b9c1b51eSKate Stone                    m_options.m_func_names, name_type_mask, m_options.m_language,
519*b9c1b51eSKate Stone                    m_options.m_offset_addr, m_options.m_skip_prologue, internal,
520*b9c1b51eSKate Stone                    m_options.m_hardware)
521*b9c1b51eSKate Stone                .get();
522*b9c1b51eSKate Stone     } break;
5230c5cd90dSGreg Clayton 
524*b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
525*b9c1b51eSKate Stone                                  // name
52630fdc8d8SChris Lattner     {
52730fdc8d8SChris Lattner       RegularExpression regexp(m_options.m_func_regexp.c_str());
528*b9c1b51eSKate Stone       if (!regexp.IsValid()) {
529969795f1SJim Ingham         char err_str[1024];
530969795f1SJim Ingham         regexp.GetErrorAsCString(err_str, sizeof(err_str));
531*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
532*b9c1b51eSKate Stone             "Function name regular expression could not be compiled: \"%s\"",
533969795f1SJim Ingham             err_str);
53430fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
535969795f1SJim Ingham         return false;
53630fdc8d8SChris Lattner       }
53787df91b8SJim Ingham 
538*b9c1b51eSKate Stone       bp = target
539*b9c1b51eSKate Stone                ->CreateFuncRegexBreakpoint(
540*b9c1b51eSKate Stone                    &(m_options.m_modules), &(m_options.m_filenames), regexp,
541*b9c1b51eSKate Stone                    m_options.m_language, m_options.m_skip_prologue, internal,
542*b9c1b51eSKate Stone                    m_options.m_hardware)
543*b9c1b51eSKate Stone                .get();
544*b9c1b51eSKate Stone     } break;
545969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
546969795f1SJim Ingham     {
547c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
54887df91b8SJim Ingham 
549*b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
550969795f1SJim Ingham         FileSpec file;
551*b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
552*b9c1b51eSKate Stone           result.AppendError(
553*b9c1b51eSKate Stone               "No files provided and could not find default file.");
55487df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
55587df91b8SJim Ingham           return false;
556*b9c1b51eSKate Stone         } else {
55787df91b8SJim Ingham           m_options.m_filenames.Append(file);
55887df91b8SJim Ingham         }
55987df91b8SJim Ingham       }
5600c5cd90dSGreg Clayton 
561969795f1SJim Ingham       RegularExpression regexp(m_options.m_source_text_regexp.c_str());
562*b9c1b51eSKate Stone       if (!regexp.IsValid()) {
563969795f1SJim Ingham         char err_str[1024];
564969795f1SJim Ingham         regexp.GetErrorAsCString(err_str, sizeof(err_str));
565*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
566*b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
567969795f1SJim Ingham             err_str);
568969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
569969795f1SJim Ingham         return false;
570969795f1SJim Ingham       }
571*b9c1b51eSKate Stone       bp = target
572*b9c1b51eSKate Stone                ->CreateSourceRegexBreakpoint(
573*b9c1b51eSKate Stone                    &(m_options.m_modules), &(m_options.m_filenames),
574*b9c1b51eSKate Stone                    m_options.m_source_regex_func_names, regexp, internal,
575*b9c1b51eSKate Stone                    m_options.m_hardware, m_options.m_move_to_nearest_code)
576*b9c1b51eSKate Stone                .get();
577*b9c1b51eSKate Stone     } break;
578*b9c1b51eSKate Stone     case eSetTypeException: {
579a72b31c7SJim Ingham       Error precond_error;
580*b9c1b51eSKate Stone       bp = target
581*b9c1b51eSKate Stone                ->CreateExceptionBreakpoint(
582*b9c1b51eSKate Stone                    m_options.m_exception_language, m_options.m_catch_bp,
583*b9c1b51eSKate Stone                    m_options.m_throw_bp, internal,
584*b9c1b51eSKate Stone                    &m_options.m_exception_extra_args, &precond_error)
585*b9c1b51eSKate Stone                .get();
586*b9c1b51eSKate Stone       if (precond_error.Fail()) {
587*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
588*b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
589a72b31c7SJim Ingham             precond_error.AsCString());
590a72b31c7SJim Ingham         target->RemoveBreakpointByID(bp->GetID());
591a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
592a72b31c7SJim Ingham         return false;
593a72b31c7SJim Ingham       }
594*b9c1b51eSKate Stone     } break;
59530fdc8d8SChris Lattner     default:
59630fdc8d8SChris Lattner       break;
59730fdc8d8SChris Lattner     }
59830fdc8d8SChris Lattner 
5991b54c88cSJim Ingham     // Now set the various options that were passed in:
600*b9c1b51eSKate Stone     if (bp) {
6011b54c88cSJim Ingham       if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
6021b54c88cSJim Ingham         bp->SetThreadID(m_options.m_thread_id);
6031b54c88cSJim Ingham 
604c982c768SGreg Clayton       if (m_options.m_thread_index != UINT32_MAX)
6051b54c88cSJim Ingham         bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
6061b54c88cSJim Ingham 
6071b54c88cSJim Ingham       if (!m_options.m_thread_name.empty())
608*b9c1b51eSKate Stone         bp->GetOptions()->GetThreadSpec()->SetName(
609*b9c1b51eSKate Stone             m_options.m_thread_name.c_str());
6101b54c88cSJim Ingham 
6111b54c88cSJim Ingham       if (!m_options.m_queue_name.empty())
612*b9c1b51eSKate Stone         bp->GetOptions()->GetThreadSpec()->SetQueueName(
613*b9c1b51eSKate Stone             m_options.m_queue_name.c_str());
6141b54c88cSJim Ingham 
615c982c768SGreg Clayton       if (m_options.m_ignore_count != 0)
6161b54c88cSJim Ingham         bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
6177d49c9c8SJohnny Chen 
6187d49c9c8SJohnny Chen       if (!m_options.m_condition.empty())
6197d49c9c8SJohnny Chen         bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
620ca36cd16SJim Ingham 
621*b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
622*b9c1b51eSKate Stone         Error error; // We don't need to check the error here, since the option
623*b9c1b51eSKate Stone                      // parser checked it...
6245e09c8c3SJim Ingham         for (auto name : m_options.m_breakpoint_names)
6255e09c8c3SJim Ingham           bp->AddName(name.c_str(), error);
6265e09c8c3SJim Ingham       }
6275e09c8c3SJim Ingham 
628ca36cd16SJim Ingham       bp->SetOneShot(m_options.m_one_shot);
6291b54c88cSJim Ingham     }
6301b54c88cSJim Ingham 
631*b9c1b51eSKate Stone     if (bp) {
63285e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
6331391cc7dSJim Ingham       const bool show_locations = false;
634*b9c1b51eSKate Stone       bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
635*b9c1b51eSKate Stone                          show_locations);
6364aeb1989SJim Ingham       if (target == m_interpreter.GetDebugger().GetDummyTarget())
637*b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
638*b9c1b51eSKate Stone                              "into future targets.\n");
639*b9c1b51eSKate Stone       else {
640*b9c1b51eSKate Stone         // Don't print out this warning for exception breakpoints.  They can get
641*b9c1b51eSKate Stone         // set before the target
642*b9c1b51eSKate Stone         // is set, but we won't know how to actually set the breakpoint till we
643*b9c1b51eSKate Stone         // run.
644*b9c1b51eSKate Stone         if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
645*b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
646*b9c1b51eSKate Stone                                "actual locations.\n");
6474aeb1989SJim Ingham         }
6484aeb1989SJim Ingham       }
64930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
650*b9c1b51eSKate Stone     } else if (!bp) {
65130fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
65230fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
65330fdc8d8SChris Lattner     }
65430fdc8d8SChris Lattner 
65530fdc8d8SChris Lattner     return result.Succeeded();
65630fdc8d8SChris Lattner   }
65730fdc8d8SChris Lattner 
6585a988416SJim Ingham private:
659*b9c1b51eSKate Stone   bool GetDefaultFile(Target *target, FileSpec &file,
660*b9c1b51eSKate Stone                       CommandReturnObject &result) {
6615a988416SJim Ingham     uint32_t default_line;
6625a988416SJim Ingham     // First use the Source Manager's default file.
6635a988416SJim Ingham     // Then use the current stack frame's file.
664*b9c1b51eSKate Stone     if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
665b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
666*b9c1b51eSKate Stone       if (cur_frame == nullptr) {
667*b9c1b51eSKate Stone         result.AppendError(
668*b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
6695a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
6705a988416SJim Ingham         return false;
671*b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
672*b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
673*b9c1b51eSKate Stone                            "file, it has no debug info.");
6745a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
6755a988416SJim Ingham         return false;
676*b9c1b51eSKate Stone       } else {
677*b9c1b51eSKate Stone         const SymbolContext &sc =
678*b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
679*b9c1b51eSKate Stone         if (sc.line_entry.file) {
6805a988416SJim Ingham           file = sc.line_entry.file;
681*b9c1b51eSKate Stone         } else {
682*b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
683*b9c1b51eSKate Stone                              "use as the default file.");
6845a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
6855a988416SJim Ingham           return false;
6865a988416SJim Ingham         }
6875a988416SJim Ingham       }
6885a988416SJim Ingham     }
6895a988416SJim Ingham     return true;
6905a988416SJim Ingham   }
6915a988416SJim Ingham 
6925a988416SJim Ingham   CommandOptions m_options;
6935a988416SJim Ingham };
6949e85e5a8SEugene Zelenko 
6955a988416SJim Ingham // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
6965a988416SJim Ingham // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
6975a988416SJim Ingham #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
6985a988416SJim Ingham #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
6995a988416SJim Ingham #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
7002411167fSJim Ingham #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
701055ad9beSIlia K #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
7020fcdac36SJim Ingham #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
7035a988416SJim Ingham 
704*b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
7055a988416SJim Ingham     {
706ac9c3a62SKate Stone         // clang-format off
707ac9c3a62SKate Stone   {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 "
708ac9c3a62SKate Stone                                                                                                                                                                                                    "multiple times to specify multiple shared libraries."},
709ac9c3a62SKate Stone   {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." },
710ac9c3a62SKate Stone   {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." },
711ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL,              false, "condition",              'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeExpression,          "The breakpoint stops only if this condition expression evaluates to true."},
712ac9c3a62SKate Stone   {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."},
713ac9c3a62SKate Stone   {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."},
714ac9c3a62SKate Stone   {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 "
715ac9c3a62SKate Stone                                                                                                                                                                                                    "argument."},
716ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL,              false, "hardware",               'H', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "Require the breakpoint to use hardware breakpoints."},
717ac9c3a62SKate Stone   {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 "
718ac9c3a62SKate Stone                                                                                                                                                                                                    "this argument."},
719ac9c3a62SKate Stone   {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 "
720ac9c3a62SKate Stone                                                                                                                                                                                                    "lldb only looks for files that are #included if they use the standard include "
721ac9c3a62SKate Stone                                                                                                                                                                                                    "file extensions.  To set breakpoints on .c/.cpp/.m/.mm files that are "
722ac9c3a62SKate Stone                                                                                                                                                                                                    "#included, set target.inline-breakpoint-strategy to \"always\"."},
723ac9c3a62SKate Stone   {LLDB_OPT_SET_1,                true,  "line",                   'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,             "Specifies the line number on which to set this breakpoint."},
7245a988416SJim Ingham 
7255a988416SJim Ingham     // Comment out this option for the moment, as we don't actually use it, but will in the future.
7265a988416SJim Ingham     // This way users won't see it, but the infrastructure is left in place.
7279e85e5a8SEugene Zelenko     //    { 0, false, "column",     'C', OptionParser::eRequiredArgument, nullptr, "<column>",
7285a988416SJim Ingham     //    "Set the breakpoint by source location at this particular column."},
7295a988416SJim Ingham 
730ac9c3a62SKate Stone   {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 "
731ac9c3a62SKate Stone                                                                                                                                                                                                    "a particular binary, then the address will be converted to a \"file\" "
732ac9c3a62SKate Stone                                                                                                                                                                                                    "address, so that the breakpoint will track that binary+offset no matter where "
733ac9c3a62SKate Stone                                                                                                                                                                                                    "the binary eventually loads.  Alternately, if you also specify the module - "
734ac9c3a62SKate Stone                                                                                                                                                                                                    "with the -s option - then the address will be treated as a file address in "
735ac9c3a62SKate Stone                                                                                                                                                                                                    "that module, and resolved accordingly.  Again, this will allow lldb to track "
736ac9c3a62SKate Stone                                                                                                                                                                                                    "that offset on subsequent reloads.  The module need not have been loaded at "
737ac9c3a62SKate Stone                                                                                                                                                                                                    "the time you specify this breakpoint, and will get resolved when the module "
738ac9c3a62SKate Stone                                                                                                                                                                                                    "is loaded."},
739ac9c3a62SKate Stone   {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 "
740ac9c3a62SKate Stone                                                                                                                                                                                                    "one breakpoint for multiple names"},
741ac9c3a62SKate Stone   {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 "
742ac9c3a62SKate Stone                                                                                                                                                                                                    "functions.  Can be repeated multiple times."},
743ac9c3a62SKate Stone   {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 "
744ac9c3a62SKate Stone                                                                                                                                                                                                    "namespaces and all arguments, and for Objective C this means a full function "
745ac9c3a62SKate Stone                                                                                                                                                                                                    "prototype with class and selector.  Can be repeated multiple times to make "
746ac9c3a62SKate Stone                                                                                                                                                                                                    "one breakpoint for multiple names."},
747ac9c3a62SKate Stone   {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 "
748ac9c3a62SKate Stone                                                                                                                                                                                                    "make one breakpoint for multiple Selectors."},
749ac9c3a62SKate Stone   {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 "
750ac9c3a62SKate Stone                                                                                                                                                                                                    "make one breakpoint for multiple methods."},
751ac9c3a62SKate Stone   {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 "
752ac9c3a62SKate Stone                                                                                                                                                                                                    "the function name(s)."},
753ac9c3a62SKate Stone   {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 "
754ac9c3a62SKate Stone                                                                                                                                                                                                    "ignored).  Can be repeated multiple times to make one breakpoint for multiple "
755ac9c3a62SKate Stone                                                                                                                                                                                                    "symbols."},
756ac9c3a62SKate Stone   {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 "
757ac9c3a62SKate Stone                                                                                                                                                                                                    "against the source text in a source file or files specified with the -f "
758ac9c3a62SKate Stone                                                                                                                                                                                                    "option.  The -f option can be specified more than once.  If no source files "
759ac9c3a62SKate Stone                                                                                                                                                                                                    "are specified, uses the current \"default source file\".  If you want to "
760ac9c3a62SKate Stone                                                                                                                                                                                                    "match against all source files, pass the \"--all-files\" option."},
761ac9c3a62SKate Stone   {LLDB_OPT_SET_9,                false, "all-files",              'A', OptionParser::eNoArgument,       nullptr, nullptr, 0,                                         eArgTypeNone,                "All files are searched for source pattern matches."},
762ac9c3a62SKate Stone   {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 "
763ac9c3a62SKate Stone                                                                                                                                                                                                    "options, on throw but not catch.)"},
764ac9c3a62SKate Stone   {LLDB_OPT_SET_10,               false, "on-throw",               'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception throW."},
765ac9c3a62SKate Stone   {LLDB_OPT_SET_10,               false, "on-catch",               'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBoolean,             "Set the breakpoint on exception catcH."},
7665a988416SJim Ingham 
767a72b31c7SJim Ingham //  Don't add this option till it actually does something useful...
7689e85e5a8SEugene Zelenko //    { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
769a72b31c7SJim Ingham //        "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" },
770a72b31c7SJim Ingham 
771ac9c3a62SKate Stone   {LLDB_OPT_EXPR_LANGUAGE,        false, "language",               'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLanguage,            "Specifies the Language to use when interpreting the breakpoint's expression "
772ac9c3a62SKate Stone                                                                                                                                                                                                    "(note: currently only implemented for setting breakpoints on identifiers).  "
773ac9c3a62SKate Stone                                                                                                                                                                                                    "If not set the target.language setting is used."},
774ac9c3a62SKate Stone   {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.  "
775ac9c3a62SKate Stone                                                                                                                                                                                                    "If not set the target.skip-prologue setting is used."},
776ac9c3a62SKate Stone   {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, "
777ac9c3a62SKate Stone                                                                                                                                                                                                    "which prime new targets."},
778ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL,              false, "breakpoint-name",        'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeBreakpointName,      "Adds this to the list of names for this breakpoint."},
779ac9c3a62SKate Stone   {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.  "
7802411167fSJim Ingham         "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries."},
781ac9c3a62SKate Stone   {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 "
782ac9c3a62SKate Stone                                                                                                                                                                                                    "setting is used."},
7839e85e5a8SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
784ac9c3a62SKate Stone         // clang-format on
7855a988416SJim Ingham };
7865a988416SJim Ingham 
7875a988416SJim Ingham //-------------------------------------------------------------------------
7885a988416SJim Ingham // CommandObjectBreakpointModify
7895a988416SJim Ingham //-------------------------------------------------------------------------
7905a988416SJim Ingham #pragma mark Modify
7915a988416SJim Ingham 
792*b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
7935a988416SJim Ingham public:
794*b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
795*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
796*b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
797*b9c1b51eSKate Stone                             "breakpoints in the executable.  "
798*b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
799*b9c1b51eSKate Stone                             "created breakpoint.  "
800*b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
801*b9c1b51eSKate Stone                             "empty argument clears the modification.",
8029e85e5a8SEugene Zelenko                             nullptr),
803*b9c1b51eSKate Stone         m_options() {
8045a988416SJim Ingham     CommandArgumentEntry arg;
805*b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
806*b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
807*b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
808*b9c1b51eSKate Stone     // arguments vector.
8095a988416SJim Ingham     m_arguments.push_back(arg);
8105a988416SJim Ingham   }
8115a988416SJim Ingham 
8129e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8135a988416SJim Ingham 
814*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8155a988416SJim Ingham 
816*b9c1b51eSKate Stone   class CommandOptions : public Options {
8175a988416SJim Ingham   public:
818*b9c1b51eSKate Stone     CommandOptions()
819*b9c1b51eSKate Stone         : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
820*b9c1b51eSKate Stone           m_thread_id_passed(false), m_thread_index(UINT32_MAX),
821*b9c1b51eSKate Stone           m_thread_index_passed(false), m_thread_name(), m_queue_name(),
822*b9c1b51eSKate Stone           m_condition(), m_one_shot(false), m_enable_passed(false),
823*b9c1b51eSKate Stone           m_enable_value(false), m_name_passed(false), m_queue_passed(false),
824*b9c1b51eSKate Stone           m_condition_passed(false), m_one_shot_passed(false),
825*b9c1b51eSKate Stone           m_use_dummy(false) {}
8265a988416SJim Ingham 
8279e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
8285a988416SJim Ingham 
829*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
830*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
8315a988416SJim Ingham       Error error;
8323bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
8335a988416SJim Ingham 
834*b9c1b51eSKate Stone       switch (short_option) {
8355a988416SJim Ingham       case 'c':
8369e85e5a8SEugene Zelenko         if (option_arg != nullptr)
8375a988416SJim Ingham           m_condition.assign(option_arg);
8385a988416SJim Ingham         else
8395a988416SJim Ingham           m_condition.clear();
8405a988416SJim Ingham         m_condition_passed = true;
8415a988416SJim Ingham         break;
8425a988416SJim Ingham       case 'd':
8435a988416SJim Ingham         m_enable_passed = true;
8445a988416SJim Ingham         m_enable_value = false;
8455a988416SJim Ingham         break;
84633df7cd3SJim Ingham       case 'D':
84733df7cd3SJim Ingham         m_use_dummy = true;
84833df7cd3SJim Ingham         break;
8495a988416SJim Ingham       case 'e':
8505a988416SJim Ingham         m_enable_passed = true;
8515a988416SJim Ingham         m_enable_value = true;
8525a988416SJim Ingham         break;
8535a988416SJim Ingham       case 'i':
8545275aaa0SVince Harron         m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
8555a988416SJim Ingham         if (m_ignore_count == UINT32_MAX)
856*b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid ignore count '%s'",
857*b9c1b51eSKate Stone                                          option_arg);
8585a988416SJim Ingham         break;
859*b9c1b51eSKate Stone       case 'o': {
860ca36cd16SJim Ingham         bool value, success;
861ca36cd16SJim Ingham         value = Args::StringToBoolean(option_arg, false, &success);
862*b9c1b51eSKate Stone         if (success) {
863ca36cd16SJim Ingham           m_one_shot_passed = true;
864ca36cd16SJim Ingham           m_one_shot = value;
865*b9c1b51eSKate Stone         } else
866*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
867*b9c1b51eSKate Stone               "invalid boolean value '%s' passed for -o option", option_arg);
868*b9c1b51eSKate Stone       } break;
8695a988416SJim Ingham       case 't':
870*b9c1b51eSKate Stone         if (option_arg[0] == '\0') {
8715a988416SJim Ingham           m_thread_id = LLDB_INVALID_THREAD_ID;
8725a988416SJim Ingham           m_thread_id_passed = true;
873*b9c1b51eSKate Stone         } else {
874*b9c1b51eSKate Stone           m_thread_id =
875*b9c1b51eSKate Stone               StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
8765a988416SJim Ingham           if (m_thread_id == LLDB_INVALID_THREAD_ID)
877*b9c1b51eSKate Stone             error.SetErrorStringWithFormat("invalid thread id string '%s'",
878*b9c1b51eSKate Stone                                            option_arg);
8795a988416SJim Ingham           else
8805a988416SJim Ingham             m_thread_id_passed = true;
8815a988416SJim Ingham         }
8825a988416SJim Ingham         break;
8835a988416SJim Ingham       case 'T':
8849e85e5a8SEugene Zelenko         if (option_arg != nullptr)
8855a988416SJim Ingham           m_thread_name.assign(option_arg);
8865a988416SJim Ingham         else
8875a988416SJim Ingham           m_thread_name.clear();
8885a988416SJim Ingham         m_name_passed = true;
8895a988416SJim Ingham         break;
8905a988416SJim Ingham       case 'q':
8919e85e5a8SEugene Zelenko         if (option_arg != nullptr)
8925a988416SJim Ingham           m_queue_name.assign(option_arg);
8935a988416SJim Ingham         else
8945a988416SJim Ingham           m_queue_name.clear();
8955a988416SJim Ingham         m_queue_passed = true;
8965a988416SJim Ingham         break;
8975a988416SJim Ingham       case 'x':
898*b9c1b51eSKate Stone         if (option_arg[0] == '\n') {
8995a988416SJim Ingham           m_thread_index = UINT32_MAX;
9005a988416SJim Ingham           m_thread_index_passed = true;
901*b9c1b51eSKate Stone         } else {
9025275aaa0SVince Harron           m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
9035a988416SJim Ingham           if (m_thread_id == UINT32_MAX)
904*b9c1b51eSKate Stone             error.SetErrorStringWithFormat("invalid thread index string '%s'",
905*b9c1b51eSKate Stone                                            option_arg);
9065a988416SJim Ingham           else
9075a988416SJim Ingham             m_thread_index_passed = true;
9085a988416SJim Ingham         }
9095a988416SJim Ingham         break;
9105a988416SJim Ingham       default:
911*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
912*b9c1b51eSKate Stone                                        short_option);
9135a988416SJim Ingham         break;
9145a988416SJim Ingham       }
9155a988416SJim Ingham 
9165a988416SJim Ingham       return error;
9175a988416SJim Ingham     }
9189e85e5a8SEugene Zelenko 
919*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
9205a988416SJim Ingham       m_ignore_count = 0;
9215a988416SJim Ingham       m_thread_id = LLDB_INVALID_THREAD_ID;
9225a988416SJim Ingham       m_thread_id_passed = false;
9235a988416SJim Ingham       m_thread_index = UINT32_MAX;
9245a988416SJim Ingham       m_thread_index_passed = false;
9255a988416SJim Ingham       m_thread_name.clear();
9265a988416SJim Ingham       m_queue_name.clear();
9275a988416SJim Ingham       m_condition.clear();
928ca36cd16SJim Ingham       m_one_shot = false;
9295a988416SJim Ingham       m_enable_passed = false;
9305a988416SJim Ingham       m_queue_passed = false;
9315a988416SJim Ingham       m_name_passed = false;
9325a988416SJim Ingham       m_condition_passed = false;
933ca36cd16SJim Ingham       m_one_shot_passed = false;
93433df7cd3SJim Ingham       m_use_dummy = false;
9355a988416SJim Ingham     }
9365a988416SJim Ingham 
937*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
9385a988416SJim Ingham 
9395a988416SJim Ingham     // Options table: Required for subclasses of Options.
9405a988416SJim Ingham 
9415a988416SJim Ingham     static OptionDefinition g_option_table[];
9425a988416SJim Ingham 
9435a988416SJim Ingham     // Instance variables to hold the values for command options.
9445a988416SJim Ingham 
9455a988416SJim Ingham     uint32_t m_ignore_count;
9465a988416SJim Ingham     lldb::tid_t m_thread_id;
9475a988416SJim Ingham     bool m_thread_id_passed;
9485a988416SJim Ingham     uint32_t m_thread_index;
9495a988416SJim Ingham     bool m_thread_index_passed;
9505a988416SJim Ingham     std::string m_thread_name;
9515a988416SJim Ingham     std::string m_queue_name;
9525a988416SJim Ingham     std::string m_condition;
953ca36cd16SJim Ingham     bool m_one_shot;
9545a988416SJim Ingham     bool m_enable_passed;
9555a988416SJim Ingham     bool m_enable_value;
9565a988416SJim Ingham     bool m_name_passed;
9575a988416SJim Ingham     bool m_queue_passed;
9585a988416SJim Ingham     bool m_condition_passed;
959ca36cd16SJim Ingham     bool m_one_shot_passed;
96033df7cd3SJim Ingham     bool m_use_dummy;
9615a988416SJim Ingham   };
9625a988416SJim Ingham 
9635a988416SJim Ingham protected:
964*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
96533df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
966*b9c1b51eSKate Stone     if (target == nullptr) {
9675a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
9685a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9695a988416SJim Ingham       return false;
9705a988416SJim Ingham     }
9715a988416SJim Ingham 
972bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
973bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
9745a988416SJim Ingham 
9755a988416SJim Ingham     BreakpointIDList valid_bp_ids;
9765a988416SJim Ingham 
977*b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
978*b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
9795a988416SJim Ingham 
980*b9c1b51eSKate Stone     if (result.Succeeded()) {
9815a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
982*b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
9835a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9845a988416SJim Ingham 
985*b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
986*b9c1b51eSKate Stone           Breakpoint *bp =
987*b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
988*b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
989*b9c1b51eSKate Stone             BreakpointLocation *location =
990*b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
991*b9c1b51eSKate Stone             if (location) {
9925a988416SJim Ingham               if (m_options.m_thread_id_passed)
9935a988416SJim Ingham                 location->SetThreadID(m_options.m_thread_id);
9945a988416SJim Ingham 
9955a988416SJim Ingham               if (m_options.m_thread_index_passed)
9965a988416SJim Ingham                 location->SetThreadIndex(m_options.m_thread_index);
9975a988416SJim Ingham 
9985a988416SJim Ingham               if (m_options.m_name_passed)
9995a988416SJim Ingham                 location->SetThreadName(m_options.m_thread_name.c_str());
10005a988416SJim Ingham 
10015a988416SJim Ingham               if (m_options.m_queue_passed)
10025a988416SJim Ingham                 location->SetQueueName(m_options.m_queue_name.c_str());
10035a988416SJim Ingham 
10045a988416SJim Ingham               if (m_options.m_ignore_count != 0)
10055a988416SJim Ingham                 location->SetIgnoreCount(m_options.m_ignore_count);
10065a988416SJim Ingham 
10075a988416SJim Ingham               if (m_options.m_enable_passed)
10085a988416SJim Ingham                 location->SetEnabled(m_options.m_enable_value);
10095a988416SJim Ingham 
10105a988416SJim Ingham               if (m_options.m_condition_passed)
10115a988416SJim Ingham                 location->SetCondition(m_options.m_condition.c_str());
10125a988416SJim Ingham             }
1013*b9c1b51eSKate Stone           } else {
10145a988416SJim Ingham             if (m_options.m_thread_id_passed)
10155a988416SJim Ingham               bp->SetThreadID(m_options.m_thread_id);
10165a988416SJim Ingham 
10175a988416SJim Ingham             if (m_options.m_thread_index_passed)
10185a988416SJim Ingham               bp->SetThreadIndex(m_options.m_thread_index);
10195a988416SJim Ingham 
10205a988416SJim Ingham             if (m_options.m_name_passed)
10215a988416SJim Ingham               bp->SetThreadName(m_options.m_thread_name.c_str());
10225a988416SJim Ingham 
10235a988416SJim Ingham             if (m_options.m_queue_passed)
10245a988416SJim Ingham               bp->SetQueueName(m_options.m_queue_name.c_str());
10255a988416SJim Ingham 
10265a988416SJim Ingham             if (m_options.m_ignore_count != 0)
10275a988416SJim Ingham               bp->SetIgnoreCount(m_options.m_ignore_count);
10285a988416SJim Ingham 
10295a988416SJim Ingham             if (m_options.m_enable_passed)
10305a988416SJim Ingham               bp->SetEnabled(m_options.m_enable_value);
10315a988416SJim Ingham 
10325a988416SJim Ingham             if (m_options.m_condition_passed)
10335a988416SJim Ingham               bp->SetCondition(m_options.m_condition.c_str());
10345a988416SJim Ingham           }
10355a988416SJim Ingham         }
10365a988416SJim Ingham       }
10375a988416SJim Ingham     }
10385a988416SJim Ingham 
10395a988416SJim Ingham     return result.Succeeded();
10405a988416SJim Ingham   }
10415a988416SJim Ingham 
10425a988416SJim Ingham private:
10435a988416SJim Ingham   CommandOptions m_options;
10445a988416SJim Ingham };
10455a988416SJim Ingham 
10465a988416SJim Ingham #pragma mark Modify::CommandOptions
10475a988416SJim Ingham OptionDefinition
1048*b9c1b51eSKate Stone     CommandObjectBreakpointModify::CommandOptions::g_option_table[] = {
1049ac9c3a62SKate Stone         // clang-format off
10509e85e5a8SEugene Zelenko   {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."},
10519e85e5a8SEugene Zelenko   {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."},
10529e85e5a8SEugene Zelenko   {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."},
10539e85e5a8SEugene Zelenko   {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."},
10549e85e5a8SEugene Zelenko   {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."},
10559e85e5a8SEugene Zelenko   {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."},
10569e85e5a8SEugene Zelenko   {LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression,  "The breakpoint stops only if this condition expression evaluates to true."},
10579e85e5a8SEugene Zelenko   {LLDB_OPT_SET_1,   false, "enable",       'e', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Enable the breakpoint."},
10589e85e5a8SEugene Zelenko   {LLDB_OPT_SET_2,   false, "disable",      'd', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,        "Disable the breakpoint."},
10599e85e5a8SEugene Zelenko   {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."},
10609e85e5a8SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1061ac9c3a62SKate Stone         // clang-format on
10625a988416SJim Ingham };
10635a988416SJim Ingham 
10645a988416SJim Ingham //-------------------------------------------------------------------------
10655a988416SJim Ingham // CommandObjectBreakpointEnable
10665a988416SJim Ingham //-------------------------------------------------------------------------
10675a988416SJim Ingham #pragma mark Enable
10685a988416SJim Ingham 
1069*b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
10705a988416SJim Ingham public:
1071*b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1072*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
1073*b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
1074*b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
1075*b9c1b51eSKate Stone                             nullptr) {
10765a988416SJim Ingham     CommandArgumentEntry arg;
1077*b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1078*b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1079*b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1080*b9c1b51eSKate Stone     // arguments vector.
10815a988416SJim Ingham     m_arguments.push_back(arg);
10825a988416SJim Ingham   }
10835a988416SJim Ingham 
10849e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
10855a988416SJim Ingham 
10865a988416SJim Ingham protected:
1087*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1088893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1089*b9c1b51eSKate Stone     if (target == nullptr) {
10905a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
10915a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10925a988416SJim Ingham       return false;
10935a988416SJim Ingham     }
10945a988416SJim Ingham 
1095bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1096bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
10975a988416SJim Ingham 
10985a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
10995a988416SJim Ingham 
11005a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11015a988416SJim Ingham 
1102*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11035a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
11045a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
11055a988416SJim Ingham       return false;
11065a988416SJim Ingham     }
11075a988416SJim Ingham 
1108*b9c1b51eSKate Stone     if (command.GetArgumentCount() == 0) {
11095a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
11105a988416SJim Ingham       target->EnableAllBreakpoints();
1111*b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1112*b9c1b51eSKate Stone                                      " breakpoints)\n",
1113*b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
11145a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1115*b9c1b51eSKate Stone     } else {
11165a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
11175a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1118*b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1119*b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
11205a988416SJim Ingham 
1121*b9c1b51eSKate Stone       if (result.Succeeded()) {
11225a988416SJim Ingham         int enable_count = 0;
11235a988416SJim Ingham         int loc_count = 0;
11245a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1125*b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
11265a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
11275a988416SJim Ingham 
1128*b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1129*b9c1b51eSKate Stone             Breakpoint *breakpoint =
1130*b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1131*b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1132*b9c1b51eSKate Stone               BreakpointLocation *location =
1133*b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1134*b9c1b51eSKate Stone               if (location) {
11355a988416SJim Ingham                 location->SetEnabled(true);
11365a988416SJim Ingham                 ++loc_count;
11375a988416SJim Ingham               }
1138*b9c1b51eSKate Stone             } else {
11395a988416SJim Ingham               breakpoint->SetEnabled(true);
11405a988416SJim Ingham               ++enable_count;
11415a988416SJim Ingham             }
11425a988416SJim Ingham           }
11435a988416SJim Ingham         }
1144*b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1145*b9c1b51eSKate Stone                                        enable_count + loc_count);
11465a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
11475a988416SJim Ingham       }
11485a988416SJim Ingham     }
11495a988416SJim Ingham 
11505a988416SJim Ingham     return result.Succeeded();
11515a988416SJim Ingham   }
11525a988416SJim Ingham };
11535a988416SJim Ingham 
11545a988416SJim Ingham //-------------------------------------------------------------------------
11555a988416SJim Ingham // CommandObjectBreakpointDisable
11565a988416SJim Ingham //-------------------------------------------------------------------------
11575a988416SJim Ingham #pragma mark Disable
11585a988416SJim Ingham 
1159*b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
11605a988416SJim Ingham public:
11617428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1162*b9c1b51eSKate Stone       : CommandObjectParsed(
1163*b9c1b51eSKate Stone             interpreter, "breakpoint disable",
1164*b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
11657428a18cSKate Stone             "them.  If none are specified, disable all "
11667428a18cSKate Stone             "breakpoints.",
1167*b9c1b51eSKate Stone             nullptr) {
1168*b9c1b51eSKate Stone     SetHelpLong(
1169*b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
11707428a18cSKate Stone If none are specified, disable all breakpoints."
11717428a18cSKate Stone         R"(
1172ea671fbdSKate Stone 
11737428a18cSKate Stone )"
11747428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
11757428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
11767428a18cSKate Stone         R"(
1177ea671fbdSKate Stone 
1178ea671fbdSKate Stone     (lldb) break disable 1
1179ea671fbdSKate Stone     (lldb) break enable 1.1
1180ea671fbdSKate Stone 
1181ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1182ea671fbdSKate Stone 
1183ea671fbdSKate Stone     (lldb) break disable 1.*
1184ea671fbdSKate Stone     (lldb) break enable 1.1
1185ea671fbdSKate Stone 
11867428a18cSKate Stone )"
11877428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
11887428a18cSKate Stone the second re-enables the first location.");
1189b0fac509SJim Ingham 
11905a988416SJim Ingham     CommandArgumentEntry arg;
1191*b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1192*b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1193*b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1194*b9c1b51eSKate Stone     // arguments vector.
11955a988416SJim Ingham     m_arguments.push_back(arg);
11965a988416SJim Ingham   }
11975a988416SJim Ingham 
11989e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
11995a988416SJim Ingham 
12005a988416SJim Ingham protected:
1201*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1202893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1203*b9c1b51eSKate Stone     if (target == nullptr) {
12045a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
12055a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
12065a988416SJim Ingham       return false;
12075a988416SJim Ingham     }
12085a988416SJim Ingham 
1209bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1210bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
12115a988416SJim Ingham 
12125a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
12135a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
12145a988416SJim Ingham 
1215*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
12165a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
12175a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
12185a988416SJim Ingham       return false;
12195a988416SJim Ingham     }
12205a988416SJim Ingham 
1221*b9c1b51eSKate Stone     if (command.GetArgumentCount() == 0) {
12225a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
12235a988416SJim Ingham       target->DisableAllBreakpoints();
1224*b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1225*b9c1b51eSKate Stone                                      " breakpoints)\n",
1226*b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
12275a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1228*b9c1b51eSKate Stone     } else {
12295a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
12305a988416SJim Ingham       BreakpointIDList valid_bp_ids;
12315a988416SJim Ingham 
1232*b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1233*b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
12345a988416SJim Ingham 
1235*b9c1b51eSKate Stone       if (result.Succeeded()) {
12365a988416SJim Ingham         int disable_count = 0;
12375a988416SJim Ingham         int loc_count = 0;
12385a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1239*b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
12405a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
12415a988416SJim Ingham 
1242*b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1243*b9c1b51eSKate Stone             Breakpoint *breakpoint =
1244*b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1245*b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1246*b9c1b51eSKate Stone               BreakpointLocation *location =
1247*b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1248*b9c1b51eSKate Stone               if (location) {
12495a988416SJim Ingham                 location->SetEnabled(false);
12505a988416SJim Ingham                 ++loc_count;
12515a988416SJim Ingham               }
1252*b9c1b51eSKate Stone             } else {
12535a988416SJim Ingham               breakpoint->SetEnabled(false);
12545a988416SJim Ingham               ++disable_count;
12555a988416SJim Ingham             }
12565a988416SJim Ingham           }
12575a988416SJim Ingham         }
1258*b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1259*b9c1b51eSKate Stone                                        disable_count + loc_count);
12605a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
12615a988416SJim Ingham       }
12625a988416SJim Ingham     }
12635a988416SJim Ingham 
12645a988416SJim Ingham     return result.Succeeded();
12655a988416SJim Ingham   }
12665a988416SJim Ingham };
12675a988416SJim Ingham 
12685a988416SJim Ingham //-------------------------------------------------------------------------
12695a988416SJim Ingham // CommandObjectBreakpointList
12705a988416SJim Ingham //-------------------------------------------------------------------------
12715a988416SJim Ingham #pragma mark List
12725a988416SJim Ingham 
1273*b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
12745a988416SJim Ingham public:
1275*b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1276*b9c1b51eSKate Stone       : CommandObjectParsed(
1277*b9c1b51eSKate Stone             interpreter, "breakpoint list",
12785a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
12799e85e5a8SEugene Zelenko             nullptr),
1280*b9c1b51eSKate 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 
1288*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1289*b9c1b51eSKate 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 
1298*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12995a988416SJim Ingham 
1300*b9c1b51eSKate Stone   class CommandOptions : public Options {
13015a988416SJim Ingham   public:
1302*b9c1b51eSKate Stone     CommandOptions()
1303*b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
13045a988416SJim Ingham     }
13055a988416SJim Ingham 
13069e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
13075a988416SJim Ingham 
1308*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1309*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
13105a988416SJim Ingham       Error error;
13113bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
13125a988416SJim Ingham 
1313*b9c1b51eSKate 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:
1330*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1331*b9c1b51eSKate Stone                                        short_option);
13325a988416SJim Ingham         break;
13335a988416SJim Ingham       }
13345a988416SJim Ingham 
13355a988416SJim Ingham       return error;
13365a988416SJim Ingham     }
13375a988416SJim Ingham 
1338*b9c1b51eSKate 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 
1344*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
13455a988416SJim Ingham 
13465a988416SJim Ingham     // Options table: Required for subclasses of Options.
13475a988416SJim Ingham 
13485a988416SJim Ingham     static OptionDefinition g_option_table[];
13495a988416SJim Ingham 
13505a988416SJim Ingham     // Instance variables to hold the values for command options.
13515a988416SJim Ingham 
13525a988416SJim Ingham     lldb::DescriptionLevel m_level;
13535a988416SJim Ingham 
13545a988416SJim Ingham     bool m_internal;
135533df7cd3SJim Ingham     bool m_use_dummy;
13565a988416SJim Ingham   };
13575a988416SJim Ingham 
13585a988416SJim Ingham protected:
1359*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
136033df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
136133df7cd3SJim Ingham 
1362*b9c1b51eSKate Stone     if (target == nullptr) {
13635a988416SJim Ingham       result.AppendError("Invalid target. No current target or breakpoints.");
13645a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
13655a988416SJim Ingham       return true;
13665a988416SJim Ingham     }
13675a988416SJim Ingham 
1368*b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1369*b9c1b51eSKate Stone         target->GetBreakpointList(m_options.m_internal);
1370bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1371bb19a13cSSaleem Abdulrasool     target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
13725a988416SJim Ingham 
13735a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13745a988416SJim Ingham 
1375*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13765a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
13775a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
13785a988416SJim Ingham       return true;
13795a988416SJim Ingham     }
13805a988416SJim Ingham 
13815a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
13825a988416SJim Ingham 
1383*b9c1b51eSKate Stone     if (command.GetArgumentCount() == 0) {
13845a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
13855a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1386*b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13875a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
13885a988416SJim Ingham         AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
13895a988416SJim Ingham       }
13905a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1391*b9c1b51eSKate Stone     } else {
13925a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
13935a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1394*b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1395*b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
13965a988416SJim Ingham 
1397*b9c1b51eSKate Stone       if (result.Succeeded()) {
1398*b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
13995a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1400*b9c1b51eSKate Stone           Breakpoint *breakpoint =
1401*b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1402*b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1403*b9c1b51eSKate Stone                                    m_options.m_level);
14045a988416SJim Ingham         }
14055a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1406*b9c1b51eSKate Stone       } else {
14077428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
14085a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
14095a988416SJim Ingham       }
14105a988416SJim Ingham     }
14115a988416SJim Ingham 
14125a988416SJim Ingham     return result.Succeeded();
14135a988416SJim Ingham   }
14145a988416SJim Ingham 
14155a988416SJim Ingham private:
14165a988416SJim Ingham   CommandOptions m_options;
14175a988416SJim Ingham };
14185a988416SJim Ingham 
14195a988416SJim Ingham #pragma mark List::CommandOptions
1420*b9c1b51eSKate Stone OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] =
14215a988416SJim Ingham     {
1422ac9c3a62SKate Stone         // clang-format off
1423ac9c3a62SKate Stone     {LLDB_OPT_SET_ALL, false, "internal",          'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1424ac9c3a62SKate Stone     {LLDB_OPT_SET_1,   false, "brief",             'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."},
14255a988416SJim Ingham     // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
14265a988416SJim Ingham     // But I need to see it for now, and don't want to wait.
1427ac9c3a62SKate Stone     {LLDB_OPT_SET_2,   false, "full",              'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."},
1428ac9c3a62SKate Stone     {LLDB_OPT_SET_3,   false, "verbose",           'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)."},
1429ac9c3a62SKate Stone     {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."},
14309e85e5a8SEugene Zelenko     {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1431ac9c3a62SKate Stone         // clang-format on
14325a988416SJim Ingham };
14335a988416SJim Ingham 
14345a988416SJim Ingham //-------------------------------------------------------------------------
14355a988416SJim Ingham // CommandObjectBreakpointClear
14365a988416SJim Ingham //-------------------------------------------------------------------------
14375a988416SJim Ingham #pragma mark Clear
14385a988416SJim Ingham 
1439*b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
14405a988416SJim Ingham public:
1441*b9c1b51eSKate Stone   typedef enum BreakpointClearType {
14425a988416SJim Ingham     eClearTypeInvalid,
14435a988416SJim Ingham     eClearTypeFileAndLine
14445a988416SJim Ingham   } BreakpointClearType;
14455a988416SJim Ingham 
14467428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
14477428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1448*b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1449*b9c1b51eSKate Stone                             "specified source file and line.",
14505a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1451*b9c1b51eSKate Stone         m_options() {}
14525a988416SJim Ingham 
14539e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
14545a988416SJim Ingham 
1455*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
14565a988416SJim Ingham 
1457*b9c1b51eSKate Stone   class CommandOptions : public Options {
14585a988416SJim Ingham   public:
1459*b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
14605a988416SJim Ingham 
14619e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
14625a988416SJim Ingham 
1463*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1464*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
14655a988416SJim Ingham       Error error;
14663bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
14675a988416SJim Ingham 
1468*b9c1b51eSKate Stone       switch (short_option) {
14695a988416SJim Ingham       case 'f':
14705a988416SJim Ingham         m_filename.assign(option_arg);
14715a988416SJim Ingham         break;
14725a988416SJim Ingham 
14735a988416SJim Ingham       case 'l':
14745275aaa0SVince Harron         m_line_num = StringConvert::ToUInt32(option_arg, 0);
14755a988416SJim Ingham         break;
14765a988416SJim Ingham 
14775a988416SJim Ingham       default:
1478*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1479*b9c1b51eSKate Stone                                        short_option);
14805a988416SJim Ingham         break;
14815a988416SJim Ingham       }
14825a988416SJim Ingham 
14835a988416SJim Ingham       return error;
14845a988416SJim Ingham     }
14855a988416SJim Ingham 
1486*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
14875a988416SJim Ingham       m_filename.clear();
14885a988416SJim Ingham       m_line_num = 0;
14895a988416SJim Ingham     }
14905a988416SJim Ingham 
1491*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
14925a988416SJim Ingham 
14935a988416SJim Ingham     // Options table: Required for subclasses of Options.
14945a988416SJim Ingham 
14955a988416SJim Ingham     static OptionDefinition g_option_table[];
14965a988416SJim Ingham 
14975a988416SJim Ingham     // Instance variables to hold the values for command options.
14985a988416SJim Ingham 
14995a988416SJim Ingham     std::string m_filename;
15005a988416SJim Ingham     uint32_t m_line_num;
15015a988416SJim Ingham   };
15025a988416SJim Ingham 
15035a988416SJim Ingham protected:
1504*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1505893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1506*b9c1b51eSKate Stone     if (target == nullptr) {
15075a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
15085a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15095a988416SJim Ingham       return false;
15105a988416SJim Ingham     }
15115a988416SJim Ingham 
15125a988416SJim Ingham     // The following are the various types of breakpoints that could be cleared:
15135a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
15145a988416SJim Ingham 
15155a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
15165a988416SJim Ingham 
15175a988416SJim Ingham     if (m_options.m_line_num != 0)
15185a988416SJim Ingham       break_type = eClearTypeFileAndLine;
15195a988416SJim Ingham 
1520bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1521bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
15225a988416SJim Ingham 
15235a988416SJim Ingham     BreakpointList &breakpoints = target->GetBreakpointList();
15245a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
15255a988416SJim Ingham 
15265a988416SJim Ingham     // Early return if there's no breakpoint at all.
1527*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
15285a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
15295a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15305a988416SJim Ingham       return result.Succeeded();
15315a988416SJim Ingham     }
15325a988416SJim Ingham 
15335a988416SJim Ingham     // Find matching breakpoints and delete them.
15345a988416SJim Ingham 
15355a988416SJim Ingham     // First create a copy of all the IDs.
15365a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
15375a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
15389e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
15395a988416SJim Ingham 
15405a988416SJim Ingham     int num_cleared = 0;
15415a988416SJim Ingham     StreamString ss;
1542*b9c1b51eSKate Stone     switch (break_type) {
15435a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
15445a988416SJim Ingham     {
15455a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
15465a988416SJim Ingham       BreakpointLocationCollection loc_coll;
15475a988416SJim Ingham 
1548*b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
15495a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
15505a988416SJim Ingham 
1551*b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1552*b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1553*b9c1b51eSKate Stone           // remove the breakpoint.
1554*b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
15555a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
15565a988416SJim Ingham             ss.EOL();
15575a988416SJim Ingham             target->RemoveBreakpointByID(bp->GetID());
15585a988416SJim Ingham             ++num_cleared;
15595a988416SJim Ingham           }
15605a988416SJim Ingham         }
15615a988416SJim Ingham       }
1562*b9c1b51eSKate Stone     } break;
15635a988416SJim Ingham 
15645a988416SJim Ingham     default:
15655a988416SJim Ingham       break;
15665a988416SJim Ingham     }
15675a988416SJim Ingham 
1568*b9c1b51eSKate Stone     if (num_cleared > 0) {
15695a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
15705a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
15715a988416SJim Ingham       output_stream << ss.GetData();
15725a988416SJim Ingham       output_stream.EOL();
15735a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1574*b9c1b51eSKate Stone     } else {
15755a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
15765a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15775a988416SJim Ingham     }
15785a988416SJim Ingham 
15795a988416SJim Ingham     return result.Succeeded();
15805a988416SJim Ingham   }
15815a988416SJim Ingham 
15825a988416SJim Ingham private:
15835a988416SJim Ingham   CommandOptions m_options;
15845a988416SJim Ingham };
15855a988416SJim Ingham 
15865a988416SJim Ingham #pragma mark Clear::CommandOptions
15875a988416SJim Ingham 
15885a988416SJim Ingham OptionDefinition
1589*b9c1b51eSKate Stone     CommandObjectBreakpointClear::CommandOptions::g_option_table[] = {
1590ac9c3a62SKate Stone         // clang-format off
1591ac9c3a62SKate Stone   {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."},
1592ac9c3a62SKate Stone   {LLDB_OPT_SET_1, true,  "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0,                                         eArgTypeLineNum,  "Specify the breakpoint by source location at this particular line."},
15939e85e5a8SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1594ac9c3a62SKate Stone         // clang-format on
15955a988416SJim Ingham };
15965a988416SJim Ingham 
15975a988416SJim Ingham //-------------------------------------------------------------------------
15985a988416SJim Ingham // CommandObjectBreakpointDelete
15995a988416SJim Ingham //-------------------------------------------------------------------------
16005a988416SJim Ingham #pragma mark Delete
16015a988416SJim Ingham 
1602*b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
16035a988416SJim Ingham public:
1604*b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1605*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1606*b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1607*b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
16089e85e5a8SEugene Zelenko                             nullptr),
1609*b9c1b51eSKate Stone         m_options() {
16105a988416SJim Ingham     CommandArgumentEntry arg;
1611*b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1612*b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1613*b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1614*b9c1b51eSKate Stone     // arguments vector.
16155a988416SJim Ingham     m_arguments.push_back(arg);
16165a988416SJim Ingham   }
16175a988416SJim Ingham 
16189e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
16195a988416SJim Ingham 
1620*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
162133df7cd3SJim Ingham 
1622*b9c1b51eSKate Stone   class CommandOptions : public Options {
162333df7cd3SJim Ingham   public:
1624*b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
162533df7cd3SJim Ingham 
16269e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
162733df7cd3SJim Ingham 
1628*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1629*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
163033df7cd3SJim Ingham       Error error;
163133df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
163233df7cd3SJim Ingham 
1633*b9c1b51eSKate Stone       switch (short_option) {
163433df7cd3SJim Ingham       case 'f':
163533df7cd3SJim Ingham         m_force = true;
163633df7cd3SJim Ingham         break;
163733df7cd3SJim Ingham 
163833df7cd3SJim Ingham       case 'D':
163933df7cd3SJim Ingham         m_use_dummy = true;
164033df7cd3SJim Ingham         break;
164133df7cd3SJim Ingham 
164233df7cd3SJim Ingham       default:
1643*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1644*b9c1b51eSKate Stone                                        short_option);
164533df7cd3SJim Ingham         break;
164633df7cd3SJim Ingham       }
164733df7cd3SJim Ingham 
164833df7cd3SJim Ingham       return error;
164933df7cd3SJim Ingham     }
165033df7cd3SJim Ingham 
1651*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
165233df7cd3SJim Ingham       m_use_dummy = false;
165333df7cd3SJim Ingham       m_force = false;
165433df7cd3SJim Ingham     }
165533df7cd3SJim Ingham 
1656*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
165733df7cd3SJim Ingham 
165833df7cd3SJim Ingham     // Options table: Required for subclasses of Options.
165933df7cd3SJim Ingham 
166033df7cd3SJim Ingham     static OptionDefinition g_option_table[];
166133df7cd3SJim Ingham 
166233df7cd3SJim Ingham     // Instance variables to hold the values for command options.
166333df7cd3SJim Ingham     bool m_use_dummy;
166433df7cd3SJim Ingham     bool m_force;
166533df7cd3SJim Ingham   };
166633df7cd3SJim Ingham 
16675a988416SJim Ingham protected:
1668*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
166933df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
167033df7cd3SJim Ingham 
1671*b9c1b51eSKate Stone     if (target == nullptr) {
16725a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
16735a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
16745a988416SJim Ingham       return false;
16755a988416SJim Ingham     }
16765a988416SJim Ingham 
1677bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1678bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
16795a988416SJim Ingham 
16805a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
16815a988416SJim Ingham 
16825a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
16835a988416SJim Ingham 
1684*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
16855a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
16865a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
16875a988416SJim Ingham       return false;
16885a988416SJim Ingham     }
16895a988416SJim Ingham 
1690*b9c1b51eSKate Stone     if (command.GetArgumentCount() == 0) {
1691*b9c1b51eSKate Stone       if (!m_options.m_force &&
1692*b9c1b51eSKate Stone           !m_interpreter.Confirm(
1693*b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1694*b9c1b51eSKate Stone               true)) {
16955a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1696*b9c1b51eSKate Stone       } else {
16975a988416SJim Ingham         target->RemoveAllBreakpoints();
1698*b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1699*b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1700*b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
17015a988416SJim Ingham       }
17025a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1703*b9c1b51eSKate Stone     } else {
17045a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
17055a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1706*b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1707*b9c1b51eSKate Stone           command, target, result, &valid_bp_ids);
17085a988416SJim Ingham 
1709*b9c1b51eSKate Stone       if (result.Succeeded()) {
17105a988416SJim Ingham         int delete_count = 0;
17115a988416SJim Ingham         int disable_count = 0;
17125a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1713*b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
17145a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
17155a988416SJim Ingham 
1716*b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1717*b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1718*b9c1b51eSKate Stone               Breakpoint *breakpoint =
1719*b9c1b51eSKate Stone                   target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1720*b9c1b51eSKate Stone               BreakpointLocation *location =
1721*b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1722*b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1723*b9c1b51eSKate Stone               // disable them instead.
1724*b9c1b51eSKate Stone               if (location) {
17255a988416SJim Ingham                 location->SetEnabled(false);
17265a988416SJim Ingham                 ++disable_count;
17275a988416SJim Ingham               }
1728*b9c1b51eSKate Stone             } else {
17295a988416SJim Ingham               target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
17305a988416SJim Ingham               ++delete_count;
17315a988416SJim Ingham             }
17325a988416SJim Ingham           }
17335a988416SJim Ingham         }
1734*b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1735*b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
17365a988416SJim Ingham             delete_count, disable_count);
17375a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
17385a988416SJim Ingham       }
17395a988416SJim Ingham     }
17405a988416SJim Ingham     return result.Succeeded();
17415a988416SJim Ingham   }
17429e85e5a8SEugene Zelenko 
174333df7cd3SJim Ingham private:
174433df7cd3SJim Ingham   CommandOptions m_options;
174533df7cd3SJim Ingham };
174633df7cd3SJim Ingham 
174733df7cd3SJim Ingham OptionDefinition
1748*b9c1b51eSKate Stone     CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = {
1749ac9c3a62SKate Stone         // clang-format off
1750ac9c3a62SKate Stone   {LLDB_OPT_SET_1, false, "force",             'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation."},
1751ac9c3a62SKate Stone   {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."},
17529e85e5a8SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1753ac9c3a62SKate Stone         // clang-format on
17545a988416SJim Ingham };
17555a988416SJim Ingham 
175630fdc8d8SChris Lattner //-------------------------------------------------------------------------
17575e09c8c3SJim Ingham // CommandObjectBreakpointName
17585e09c8c3SJim Ingham //-------------------------------------------------------------------------
17595e09c8c3SJim Ingham 
17607428a18cSKate Stone static OptionDefinition g_breakpoint_name_options[] = {
1761ac9c3a62SKate Stone     // clang-format off
1762ac9c3a62SKate Stone   {LLDB_OPT_SET_1,   false, "name",              'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1763ac9c3a62SKate Stone   {LLDB_OPT_SET_2,   false, "breakpoint-id",     'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID,   "Specify a breakpoint ID to use."},
1764ac9c3a62SKate 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."},
1765ac9c3a62SKate Stone     // clang-format on
17665e09c8c3SJim Ingham };
1767*b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
17685e09c8c3SJim Ingham public:
1769*b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1770*b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
17715e09c8c3SJim Ingham   }
17725e09c8c3SJim Ingham 
17739e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
17745e09c8c3SJim Ingham 
1775*b9c1b51eSKate Stone   uint32_t GetNumDefinitions() override {
17765e09c8c3SJim Ingham     return sizeof(g_breakpoint_name_options) / sizeof(OptionDefinition);
17775e09c8c3SJim Ingham   }
17785e09c8c3SJim Ingham 
1779*b9c1b51eSKate Stone   const OptionDefinition *GetDefinitions() override {
17805e09c8c3SJim Ingham     return g_breakpoint_name_options;
17815e09c8c3SJim Ingham   }
17825e09c8c3SJim Ingham 
1783*b9c1b51eSKate Stone   Error SetOptionValue(uint32_t option_idx, const char *option_value,
1784*b9c1b51eSKate Stone                        ExecutionContext *execution_context) override {
17855e09c8c3SJim Ingham     Error error;
17865e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
17875e09c8c3SJim Ingham 
1788*b9c1b51eSKate Stone     switch (short_option) {
17895e09c8c3SJim Ingham     case 'N':
1790*b9c1b51eSKate Stone       if (BreakpointID::StringIsBreakpointName(option_value, error) &&
1791*b9c1b51eSKate Stone           error.Success())
1792c95f7e2aSPavel Labath         m_name.SetValueFromString(option_value);
17935e09c8c3SJim Ingham       break;
17945e09c8c3SJim Ingham 
17955e09c8c3SJim Ingham     case 'B':
1796c95f7e2aSPavel Labath       if (m_breakpoint.SetValueFromString(option_value).Fail())
1797*b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
1798*b9c1b51eSKate Stone             "unrecognized value \"%s\" for breakpoint", option_value);
17995e09c8c3SJim Ingham       break;
18005e09c8c3SJim Ingham     case 'D':
1801c95f7e2aSPavel Labath       if (m_use_dummy.SetValueFromString(option_value).Fail())
1802*b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
1803*b9c1b51eSKate Stone             "unrecognized value \"%s\" for use-dummy", option_value);
18045e09c8c3SJim Ingham       break;
18055e09c8c3SJim Ingham 
18065e09c8c3SJim Ingham     default:
1807*b9c1b51eSKate Stone       error.SetErrorStringWithFormat("unrecognized short option '%c'",
1808*b9c1b51eSKate Stone                                      short_option);
18095e09c8c3SJim Ingham       break;
18105e09c8c3SJim Ingham     }
18115e09c8c3SJim Ingham     return error;
18125e09c8c3SJim Ingham   }
18135e09c8c3SJim Ingham 
1814*b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
18155e09c8c3SJim Ingham     m_name.Clear();
18165e09c8c3SJim Ingham     m_breakpoint.Clear();
18175e09c8c3SJim Ingham     m_use_dummy.Clear();
18185e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
18195e09c8c3SJim Ingham   }
18205e09c8c3SJim Ingham 
18215e09c8c3SJim Ingham   OptionValueString m_name;
18225e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
18235e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
18245e09c8c3SJim Ingham };
18255e09c8c3SJim Ingham 
1826*b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
18275e09c8c3SJim Ingham public:
1828*b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1829*b9c1b51eSKate Stone       : CommandObjectParsed(
1830*b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
18315e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1832*b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1833*b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1834*b9c1b51eSKate Stone     // command.
18355e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18365e09c8c3SJim Ingham     CommandArgumentData id_arg;
18375e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18385e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18395e09c8c3SJim Ingham     arg1.push_back(id_arg);
18405e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18415e09c8c3SJim Ingham 
18425e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18435e09c8c3SJim Ingham     m_option_group.Finalize();
18445e09c8c3SJim Ingham   }
18455e09c8c3SJim Ingham 
18469e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
18475e09c8c3SJim Ingham 
1848*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18495e09c8c3SJim Ingham 
18505e09c8c3SJim Ingham protected:
1851*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1852*b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18535e09c8c3SJim Ingham       result.SetError("No name option provided.");
18545e09c8c3SJim Ingham       return false;
18555e09c8c3SJim Ingham     }
18565e09c8c3SJim Ingham 
1857*b9c1b51eSKate Stone     Target *target =
1858*b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18595e09c8c3SJim Ingham 
1860*b9c1b51eSKate Stone     if (target == nullptr) {
18615e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
18625e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18635e09c8c3SJim Ingham       return false;
18645e09c8c3SJim Ingham     }
18655e09c8c3SJim Ingham 
1866bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1867bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
18685e09c8c3SJim Ingham 
18695e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
18705e09c8c3SJim Ingham 
18715e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1872*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18735e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18745e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18755e09c8c3SJim Ingham       return false;
18765e09c8c3SJim Ingham     }
18775e09c8c3SJim Ingham 
18785e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18795e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1880*b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1881*b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
18825e09c8c3SJim Ingham 
1883*b9c1b51eSKate Stone     if (result.Succeeded()) {
1884*b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18855e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18865e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18875e09c8c3SJim Ingham         return false;
18885e09c8c3SJim Ingham       }
18895e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1890*b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1891*b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1892*b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18935e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1894*b9c1b51eSKate Stone         Error error; // We don't need to check the error here, since the option
1895*b9c1b51eSKate Stone                      // parser checked it...
18965e09c8c3SJim Ingham         bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
18975e09c8c3SJim Ingham       }
18985e09c8c3SJim Ingham     }
18995e09c8c3SJim Ingham 
19005e09c8c3SJim Ingham     return true;
19015e09c8c3SJim Ingham   }
19025e09c8c3SJim Ingham 
19035e09c8c3SJim Ingham private:
19045e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19055e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19065e09c8c3SJim Ingham };
19075e09c8c3SJim Ingham 
1908*b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
19095e09c8c3SJim Ingham public:
1910*b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1911*b9c1b51eSKate Stone       : CommandObjectParsed(
1912*b9c1b51eSKate Stone             interpreter, "delete",
19135e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
19145e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1915*b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1916*b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1917*b9c1b51eSKate Stone     // command.
19185e09c8c3SJim Ingham     CommandArgumentEntry arg1;
19195e09c8c3SJim Ingham     CommandArgumentData id_arg;
19205e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
19215e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
19225e09c8c3SJim Ingham     arg1.push_back(id_arg);
19235e09c8c3SJim Ingham     m_arguments.push_back(arg1);
19245e09c8c3SJim Ingham 
19255e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
19265e09c8c3SJim Ingham     m_option_group.Finalize();
19275e09c8c3SJim Ingham   }
19285e09c8c3SJim Ingham 
19299e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
19305e09c8c3SJim Ingham 
1931*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19325e09c8c3SJim Ingham 
19335e09c8c3SJim Ingham protected:
1934*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1935*b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
19365e09c8c3SJim Ingham       result.SetError("No name option provided.");
19375e09c8c3SJim Ingham       return false;
19385e09c8c3SJim Ingham     }
19395e09c8c3SJim Ingham 
1940*b9c1b51eSKate Stone     Target *target =
1941*b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19425e09c8c3SJim Ingham 
1943*b9c1b51eSKate Stone     if (target == nullptr) {
19445e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
19455e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19465e09c8c3SJim Ingham       return false;
19475e09c8c3SJim Ingham     }
19485e09c8c3SJim Ingham 
1949bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1950bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
19515e09c8c3SJim Ingham 
19525e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
19535e09c8c3SJim Ingham 
19545e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1955*b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19565e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
19575e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19585e09c8c3SJim Ingham       return false;
19595e09c8c3SJim Ingham     }
19605e09c8c3SJim Ingham 
19615e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19625e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1963*b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1964*b9c1b51eSKate Stone         command, target, result, &valid_bp_ids);
19655e09c8c3SJim Ingham 
1966*b9c1b51eSKate Stone     if (result.Succeeded()) {
1967*b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19685e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
19695e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19705e09c8c3SJim Ingham         return false;
19715e09c8c3SJim Ingham       }
19725e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1973*b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1974*b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1975*b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19765e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
19775e09c8c3SJim Ingham         bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
19785e09c8c3SJim Ingham       }
19795e09c8c3SJim Ingham     }
19805e09c8c3SJim Ingham 
19815e09c8c3SJim Ingham     return true;
19825e09c8c3SJim Ingham   }
19835e09c8c3SJim Ingham 
19845e09c8c3SJim Ingham private:
19855e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19865e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19875e09c8c3SJim Ingham };
19885e09c8c3SJim Ingham 
1989*b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19905e09c8c3SJim Ingham public:
1991*b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1992*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1993*b9c1b51eSKate Stone                             "List either the names for a breakpoint or the "
1994*b9c1b51eSKate Stone                             "breakpoints for a given name.",
19955e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1996*b9c1b51eSKate Stone         m_name_options(), m_option_group() {
19975e09c8c3SJim Ingham     m_option_group.Append(&m_name_options);
19985e09c8c3SJim Ingham     m_option_group.Finalize();
19995e09c8c3SJim Ingham   }
20005e09c8c3SJim Ingham 
20019e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
20025e09c8c3SJim Ingham 
2003*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
20045e09c8c3SJim Ingham 
20055e09c8c3SJim Ingham protected:
2006*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
2007*b9c1b51eSKate Stone     Target *target =
2008*b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
20095e09c8c3SJim Ingham 
2010*b9c1b51eSKate Stone     if (target == nullptr) {
20115e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
20125e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
20135e09c8c3SJim Ingham       return false;
20145e09c8c3SJim Ingham     }
20155e09c8c3SJim Ingham 
2016*b9c1b51eSKate Stone     if (m_name_options.m_name.OptionWasSet()) {
20175e09c8c3SJim Ingham       const char *name = m_name_options.m_name.GetCurrentValue();
2018bb19a13cSSaleem Abdulrasool       std::unique_lock<std::recursive_mutex> lock;
2019bb19a13cSSaleem Abdulrasool       target->GetBreakpointList().GetListMutex(lock);
20205e09c8c3SJim Ingham 
20215e09c8c3SJim Ingham       BreakpointList &breakpoints = target->GetBreakpointList();
2022*b9c1b51eSKate Stone       for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2023*b9c1b51eSKate Stone         if (bp_sp->MatchesName(name)) {
20245e09c8c3SJim Ingham           StreamString s;
20255e09c8c3SJim Ingham           bp_sp->GetDescription(&s, eDescriptionLevelBrief);
20265e09c8c3SJim Ingham           s.EOL();
20275e09c8c3SJim Ingham           result.AppendMessage(s.GetData());
20285e09c8c3SJim Ingham         }
20295e09c8c3SJim Ingham       }
20305e09c8c3SJim Ingham 
2031*b9c1b51eSKate Stone     } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2032*b9c1b51eSKate Stone       BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2033*b9c1b51eSKate Stone           m_name_options.m_breakpoint.GetCurrentValue());
2034*b9c1b51eSKate Stone       if (bp_sp) {
20355e09c8c3SJim Ingham         std::vector<std::string> names;
20365e09c8c3SJim Ingham         bp_sp->GetNames(names);
20375e09c8c3SJim Ingham         result.AppendMessage("Names:");
20385e09c8c3SJim Ingham         for (auto name : names)
20395e09c8c3SJim Ingham           result.AppendMessageWithFormat("    %s\n", name.c_str());
2040*b9c1b51eSKate Stone       } else {
2041*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2042*b9c1b51eSKate Stone             "Could not find breakpoint %" PRId64 ".\n",
20435e09c8c3SJim Ingham             m_name_options.m_breakpoint.GetCurrentValue());
20445e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
20455e09c8c3SJim Ingham         return false;
20465e09c8c3SJim Ingham       }
2047*b9c1b51eSKate Stone     } else {
20485e09c8c3SJim Ingham       result.SetError("Must specify -N or -B option to list.");
20495e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
20505e09c8c3SJim Ingham       return false;
20515e09c8c3SJim Ingham     }
20525e09c8c3SJim Ingham     return true;
20535e09c8c3SJim Ingham   }
20545e09c8c3SJim Ingham 
20555e09c8c3SJim Ingham private:
20565e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20575e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20585e09c8c3SJim Ingham };
20595e09c8c3SJim Ingham 
20605e09c8c3SJim Ingham //-------------------------------------------------------------------------
20615e09c8c3SJim Ingham // CommandObjectMultiwordBreakpoint
20625e09c8c3SJim Ingham //-------------------------------------------------------------------------
2063*b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20645e09c8c3SJim Ingham public:
20657428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2066*b9c1b51eSKate Stone       : CommandObjectMultiword(
2067*b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2068*b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2069*b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2070*b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2071*b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2072*b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2073*b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2074*b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
20755e09c8c3SJim Ingham 
20765e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20775e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20785e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
20795e09c8c3SJim Ingham   }
20805e09c8c3SJim Ingham 
20819e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20825e09c8c3SJim Ingham };
20835e09c8c3SJim Ingham 
20845e09c8c3SJim Ingham //-------------------------------------------------------------------------
208530fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
208630fdc8d8SChris Lattner //-------------------------------------------------------------------------
2087ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
208830fdc8d8SChris Lattner 
2089*b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2090*b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2091*b9c1b51eSKate Stone     : CommandObjectMultiword(
2092*b9c1b51eSKate Stone           interpreter, "breakpoint",
20937428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2094*b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2095*b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2096*b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2097*b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2098*b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2099*b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2100*b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2101*b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2102*b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2103*b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2104*b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2105*b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2106*b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2107*b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2108*b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2109*b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2110*b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2111*b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2112*b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
211330fdc8d8SChris Lattner 
2114b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
211530fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
211630fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2117b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2118b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2119ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2120b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2121b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
21225e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
212330fdc8d8SChris Lattner 
212423f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
212523f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
212623f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
212723f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
212823f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
212923f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
213023f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
213123f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
21325e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
213330fdc8d8SChris Lattner }
213430fdc8d8SChris Lattner 
21359e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
213630fdc8d8SChris Lattner 
2137*b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
21385e09c8c3SJim Ingham                                                  bool allow_locations,
21395e09c8c3SJim Ingham                                                  CommandReturnObject &result,
2140*b9c1b51eSKate Stone                                                  BreakpointIDList *valid_ids) {
214130fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2142*b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2143*b9c1b51eSKate Stone   //                                  canonical representation
2144*b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2145*b9c1b51eSKate Stone   //                                  representing a range (in which case there
2146*b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2147*b9c1b51eSKate Stone   //                                      after of one of the first two types.
21485e09c8c3SJim Ingham   //                                  4). A breakpoint name
2149*b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2150*b9c1b51eSKate Stone   // one.)
215130fdc8d8SChris Lattner 
215230fdc8d8SChris Lattner   Args temp_args;
215330fdc8d8SChris Lattner 
2154*b9c1b51eSKate Stone   if (args.GetArgumentCount() == 0) {
2155*b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2156*b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2157*b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
215836f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2159*b9c1b51eSKate Stone     } else {
2160*b9c1b51eSKate Stone       result.AppendError(
2161*b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
216236f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
216336f3b369SJim Ingham     }
216436f3b369SJim Ingham     return;
216536f3b369SJim Ingham   }
216636f3b369SJim Ingham 
2167*b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2168*b9c1b51eSKate Stone   // directly from the old ARGS to
2169*b9c1b51eSKate Stone   // the new TEMP_ARGS.  Do not copy breakpoint id range strings over; instead
2170*b9c1b51eSKate Stone   // generate a list of strings for
2171*b9c1b51eSKate Stone   // all the breakpoint ids in the range, and shove all of those breakpoint id
2172*b9c1b51eSKate Stone   // strings into TEMP_ARGS.
217330fdc8d8SChris Lattner 
2174*b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2175*b9c1b51eSKate Stone                                            result, temp_args);
217630fdc8d8SChris Lattner 
2177*b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2178*b9c1b51eSKate Stone   // BreakpointIDList:
217930fdc8d8SChris Lattner 
2180*b9c1b51eSKate Stone   valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2181*b9c1b51eSKate Stone                                temp_args.GetArgumentCount(), result);
218230fdc8d8SChris Lattner 
2183*b9c1b51eSKate Stone   // At this point,  all of the breakpoint ids that the user passed in have been
2184*b9c1b51eSKate Stone   // converted to breakpoint IDs
218530fdc8d8SChris Lattner   // and put into valid_ids.
218630fdc8d8SChris Lattner 
2187*b9c1b51eSKate Stone   if (result.Succeeded()) {
2188*b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
2189*b9c1b51eSKate Stone     // ids, go through our tentative list
2190*b9c1b51eSKate Stone     // of breakpoint id's and verify that they correspond to valid/currently set
2191*b9c1b51eSKate Stone     // breakpoints.
219230fdc8d8SChris Lattner 
2193c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2194*b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
219530fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2196*b9c1b51eSKate Stone       Breakpoint *breakpoint =
2197*b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2198*b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2199c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2200*b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
220130fdc8d8SChris Lattner           StreamString id_str;
2202*b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2203*b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2204c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2205*b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2206*b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
220730fdc8d8SChris Lattner               id_str.GetData());
220830fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
220930fdc8d8SChris Lattner         }
2210*b9c1b51eSKate Stone       } else {
2211c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2212*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2213*b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
22147428a18cSKate Stone             cur_bp_id.GetBreakpointID());
221530fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
221630fdc8d8SChris Lattner       }
221730fdc8d8SChris Lattner     }
221830fdc8d8SChris Lattner   }
221930fdc8d8SChris Lattner }
2220