180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h"
109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1747cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
18943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
230e0984eeSJim Ingham #include "lldb/Target/Language.h"
24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
25b9c1b51eSKate Stone #include "lldb/Target/Target.h"
261b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
27bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
28bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
2930fdc8d8SChris Lattner 
30796ac80bSJonas Devlieghere #include <memory>
31796ac80bSJonas Devlieghere #include <vector>
32796ac80bSJonas Devlieghere 
3330fdc8d8SChris Lattner using namespace lldb;
3430fdc8d8SChris Lattner using namespace lldb_private;
3530fdc8d8SChris Lattner 
36b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
37b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
3830fdc8d8SChris Lattner   s->IndentMore();
3930fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4030fdc8d8SChris Lattner   s->IndentLess();
4130fdc8d8SChris Lattner   s->EOL();
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
44b842f2ecSJim Ingham // Modifiable Breakpoint Options
45b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
46f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
47f94668e3SRaphael Isemann #include "CommandOptions.inc"
48bd68a052SRaphael Isemann 
49a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup {
50b842f2ecSJim Ingham public:
51a925974bSAdrian Prantl   BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
52b842f2ecSJim Ingham 
53b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
54b842f2ecSJim Ingham 
55b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
56b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
57b842f2ecSJim Ingham   }
58b842f2ecSJim Ingham 
59b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
60b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
61b842f2ecSJim Ingham     Status error;
62a925974bSAdrian Prantl     const int short_option =
63a925974bSAdrian Prantl         g_breakpoint_modify_options[option_idx].short_option;
64b842f2ecSJim Ingham 
65b842f2ecSJim Ingham     switch (short_option) {
66b842f2ecSJim Ingham     case 'c':
6705097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
6805097246SAdrian Prantl       // to say it was passed in.
69b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
70b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
71b842f2ecSJim Ingham       break;
72b842f2ecSJim Ingham     case 'C':
73adcd0268SBenjamin Kramer       m_commands.push_back(std::string(option_arg));
74b842f2ecSJim Ingham       break;
75b842f2ecSJim Ingham     case 'd':
76b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
77b842f2ecSJim Ingham       break;
78b842f2ecSJim Ingham     case 'e':
79b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
80b842f2ecSJim Ingham       break;
81b842f2ecSJim Ingham     case 'G': {
82b842f2ecSJim Ingham       bool value, success;
8347cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
84b842f2ecSJim Ingham       if (success) {
85b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
86b842f2ecSJim Ingham       } else
87b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
88b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
89b842f2ecSJim Ingham             option_arg.str().c_str());
90a925974bSAdrian Prantl     } break;
91a925974bSAdrian Prantl     case 'i': {
92b842f2ecSJim Ingham       uint32_t ignore_count;
93b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
94b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
95b842f2ecSJim Ingham                                        option_arg.str().c_str());
96b842f2ecSJim Ingham       else
97b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
98a925974bSAdrian Prantl     } break;
99b842f2ecSJim Ingham     case 'o': {
100b842f2ecSJim Ingham       bool value, success;
10147cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
102b842f2ecSJim Ingham       if (success) {
103b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
104b842f2ecSJim Ingham       } else
105b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
106b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
107b842f2ecSJim Ingham             option_arg.str().c_str());
108b842f2ecSJim Ingham     } break;
109a925974bSAdrian Prantl     case 't': {
110b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
111b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
112b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
113b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
114b842f2ecSJim Ingham                                          option_arg.str().c_str());
115b842f2ecSJim Ingham       }
116b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
117a925974bSAdrian Prantl     } break;
118b842f2ecSJim Ingham     case 'T':
119b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
120b842f2ecSJim Ingham       break;
121b842f2ecSJim Ingham     case 'q':
122b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
123b842f2ecSJim Ingham       break;
124a925974bSAdrian Prantl     case 'x': {
125b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
126b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
127b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
128b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
129b842f2ecSJim Ingham                                          option_arg.str().c_str());
130b842f2ecSJim Ingham       }
131b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
132a925974bSAdrian Prantl     } break;
133b842f2ecSJim Ingham     default:
13436162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
135b842f2ecSJim Ingham     }
136b842f2ecSJim Ingham 
137b842f2ecSJim Ingham     return error;
138b842f2ecSJim Ingham   }
139b842f2ecSJim Ingham 
140b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
141b842f2ecSJim Ingham     m_bp_opts.Clear();
142b842f2ecSJim Ingham     m_commands.clear();
143b842f2ecSJim Ingham   }
144b842f2ecSJim Ingham 
145b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
146a925974bSAdrian Prantl     if (!m_commands.empty()) {
147a8f3ae7cSJonas Devlieghere       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
148b842f2ecSJim Ingham 
149b842f2ecSJim Ingham       for (std::string &str : m_commands)
150b842f2ecSJim Ingham         cmd_data->user_source.AppendString(str);
151b842f2ecSJim Ingham 
152b842f2ecSJim Ingham       cmd_data->stop_on_error = true;
153b842f2ecSJim Ingham       m_bp_opts.SetCommandDataCallback(cmd_data);
154b842f2ecSJim Ingham     }
155b842f2ecSJim Ingham     return Status();
156b842f2ecSJim Ingham   }
157b842f2ecSJim Ingham 
158a925974bSAdrian Prantl   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
159b842f2ecSJim Ingham 
160b842f2ecSJim Ingham   std::vector<std::string> m_commands;
161b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
162b842f2ecSJim Ingham };
163bd68a052SRaphael Isemann 
164f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
165f94668e3SRaphael Isemann #include "CommandOptions.inc"
166b842f2ecSJim Ingham 
167a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
168b842f2ecSJim Ingham public:
169a925974bSAdrian Prantl   BreakpointDummyOptionGroup() : OptionGroup() {}
170b842f2ecSJim Ingham 
171b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
172b842f2ecSJim Ingham 
173b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
174b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
175b842f2ecSJim Ingham   }
176b842f2ecSJim Ingham 
177b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
178b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
179b842f2ecSJim Ingham     Status error;
180a925974bSAdrian Prantl     const int short_option =
181f1539b9dSJim Ingham         g_breakpoint_dummy_options[option_idx].short_option;
182b842f2ecSJim Ingham 
183b842f2ecSJim Ingham     switch (short_option) {
184b842f2ecSJim Ingham     case 'D':
185b842f2ecSJim Ingham       m_use_dummy = true;
186b842f2ecSJim Ingham       break;
187b842f2ecSJim Ingham     default:
18836162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
189b842f2ecSJim Ingham     }
190b842f2ecSJim Ingham 
191b842f2ecSJim Ingham     return error;
192b842f2ecSJim Ingham   }
193b842f2ecSJim Ingham 
194b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
195b842f2ecSJim Ingham     m_use_dummy = false;
196b842f2ecSJim Ingham   }
197b842f2ecSJim Ingham 
198b842f2ecSJim Ingham   bool m_use_dummy;
199b842f2ecSJim Ingham };
200b842f2ecSJim Ingham 
201f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
202f94668e3SRaphael Isemann #include "CommandOptions.inc"
2031f0f5b5bSZachary Turner 
2045a988416SJim Ingham // CommandObjectBreakpointSet
20530fdc8d8SChris Lattner 
206b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2075a988416SJim Ingham public:
208efe8e7e3SFangrui Song   enum BreakpointSetType {
2095a988416SJim Ingham     eSetTypeInvalid,
2105a988416SJim Ingham     eSetTypeFileAndLine,
2115a988416SJim Ingham     eSetTypeAddress,
2125a988416SJim Ingham     eSetTypeFunctionName,
2135a988416SJim Ingham     eSetTypeFunctionRegexp,
2145a988416SJim Ingham     eSetTypeSourceRegexp,
2153815e702SJim Ingham     eSetTypeException,
2163815e702SJim Ingham     eSetTypeScripted,
217efe8e7e3SFangrui Song   };
2185a988416SJim Ingham 
219b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
220b9c1b51eSKate Stone       : CommandObjectParsed(
221b9c1b51eSKate Stone             interpreter, "breakpoint set",
2225a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2235a988416SJim Ingham             "breakpoint set <cmd-options>"),
224738af7a6SJim Ingham         m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
225f6a2086dSSam McCall         m_options() {
226b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
227a925974bSAdrian Prantl     m_all_options.Append(&m_python_class_options,
228a925974bSAdrian Prantl                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
229b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
230b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
231b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
232f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
233b842f2ecSJim Ingham     m_all_options.Append(&m_options);
234b842f2ecSJim Ingham     m_all_options.Finalize();
235b842f2ecSJim Ingham   }
2365a988416SJim Ingham 
2379e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2385a988416SJim Ingham 
239b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2405a988416SJim Ingham 
241b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2425a988416SJim Ingham   public:
243b9c1b51eSKate Stone     CommandOptions()
244a925974bSAdrian Prantl         : OptionGroup(), m_condition(), m_filenames(), m_line_num(0),
245a925974bSAdrian Prantl           m_column(0), m_func_names(),
246a925974bSAdrian Prantl           m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(),
247a925974bSAdrian Prantl           m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false),
248a925974bSAdrian Prantl           m_throw_bp(true), m_hardware(false),
249a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
25023b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
251a925974bSAdrian Prantl           m_skip_prologue(eLazyBoolCalculate), m_all_files(false),
252a925974bSAdrian Prantl           m_move_to_nearest_code(eLazyBoolCalculate) {}
25330fdc8d8SChris Lattner 
2549e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
25587df91b8SJim Ingham 
25697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
257b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
25897206d57SZachary Turner       Status error;
259a925974bSAdrian Prantl       const int short_option =
260a925974bSAdrian Prantl           g_breakpoint_set_options[option_idx].short_option;
26130fdc8d8SChris Lattner 
262b9c1b51eSKate Stone       switch (short_option) {
263b9c1b51eSKate Stone       case 'a': {
26447cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
265e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
266b9c1b51eSKate Stone       } break;
26730fdc8d8SChris Lattner 
268e732052fSJim Ingham       case 'A':
269e732052fSJim Ingham         m_all_files = true;
270e732052fSJim Ingham         break;
271e732052fSJim Ingham 
272ca36cd16SJim Ingham       case 'b':
273adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
274ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
275ca36cd16SJim Ingham         break;
276ca36cd16SJim Ingham 
2776672a4f5SJonas Devlieghere       case 'u':
278fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
279b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
280fe11483bSZachary Turner                                          option_arg.str().c_str());
28130fdc8d8SChris Lattner         break;
2829e85e5a8SEugene Zelenko 
283b9c1b51eSKate Stone       case 'E': {
284fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
285fab10e89SJim Ingham 
286b9c1b51eSKate Stone         switch (language) {
287fab10e89SJim Ingham         case eLanguageTypeC89:
288fab10e89SJim Ingham         case eLanguageTypeC:
289fab10e89SJim Ingham         case eLanguageTypeC99:
2901d0089faSBruce Mitchener         case eLanguageTypeC11:
291a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
292fab10e89SJim Ingham           break;
293fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2941d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2951d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
2962ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
297a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
298fab10e89SJim Ingham           break;
299fab10e89SJim Ingham         case eLanguageTypeObjC:
300a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
301fab10e89SJim Ingham           break;
302fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
303b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
304b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
305fab10e89SJim Ingham           break;
306fab10e89SJim Ingham         case eLanguageTypeUnknown:
307b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
308b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
309fe11483bSZachary Turner               option_arg.str().c_str());
310fab10e89SJim Ingham           break;
311fab10e89SJim Ingham         default:
312b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
313b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
314fe11483bSZachary Turner               option_arg.str().c_str());
315fab10e89SJim Ingham         }
316b9c1b51eSKate Stone       } break;
317ca36cd16SJim Ingham 
318ca36cd16SJim Ingham       case 'f':
3198f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
320fab10e89SJim Ingham         break;
321ca36cd16SJim Ingham 
322ca36cd16SJim Ingham       case 'F':
323adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
324ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
325ca36cd16SJim Ingham         break;
326ca36cd16SJim Ingham 
327b9c1b51eSKate Stone       case 'h': {
328fab10e89SJim Ingham         bool success;
32947cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
330fab10e89SJim Ingham         if (!success)
331b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
332fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
333fe11483bSZachary Turner               option_arg.str().c_str());
334b9c1b51eSKate Stone       } break;
335eb023e75SGreg Clayton 
336eb023e75SGreg Clayton       case 'H':
337eb023e75SGreg Clayton         m_hardware = true;
338eb023e75SGreg Clayton         break;
339eb023e75SGreg Clayton 
340b9c1b51eSKate Stone       case 'K': {
341a8558b62SJim Ingham         bool success;
342a8558b62SJim Ingham         bool value;
34347cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
344a8558b62SJim Ingham         if (value)
345a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
346a8558b62SJim Ingham         else
347a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
348a8558b62SJim Ingham 
349a8558b62SJim Ingham         if (!success)
350b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
351b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
352fe11483bSZachary Turner               option_arg.str().c_str());
353b9c1b51eSKate Stone       } break;
354ca36cd16SJim Ingham 
355fe11483bSZachary Turner       case 'l':
356fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
357b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
358fe11483bSZachary Turner                                          option_arg.str().c_str());
359ca36cd16SJim Ingham         break;
360055ad9beSIlia K 
36123b1decbSDawn Perchik       case 'L':
362fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
36323b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
364b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
365fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
366fe11483bSZachary Turner               option_arg.str().c_str());
36723b1decbSDawn Perchik         break;
36823b1decbSDawn Perchik 
369b9c1b51eSKate Stone       case 'm': {
370055ad9beSIlia K         bool success;
371055ad9beSIlia K         bool value;
37247cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
373055ad9beSIlia K         if (value)
374055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
375055ad9beSIlia K         else
376055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
377055ad9beSIlia K 
378055ad9beSIlia K         if (!success)
379b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
380b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
381fe11483bSZachary Turner               option_arg.str().c_str());
382055ad9beSIlia K         break;
383055ad9beSIlia K       }
384055ad9beSIlia K 
385ca36cd16SJim Ingham       case 'M':
386adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
387ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
388ca36cd16SJim Ingham         break;
389ca36cd16SJim Ingham 
390ca36cd16SJim Ingham       case 'n':
391adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
392ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
393ca36cd16SJim Ingham         break;
394ca36cd16SJim Ingham 
3956fa7681bSZachary Turner       case 'N': {
396fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
397adcd0268SBenjamin Kramer           m_breakpoint_names.push_back(std::string(option_arg));
398ff9a91eaSJim Ingham         else
399ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
400fe11483bSZachary Turner                                          option_arg.str().c_str());
4015e09c8c3SJim Ingham         break;
4026fa7681bSZachary Turner       }
4035e09c8c3SJim Ingham 
404b9c1b51eSKate Stone       case 'R': {
4052411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
40647cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
40747cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4082411167fSJim Ingham         if (error.Success())
4092411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
410b9c1b51eSKate Stone       } break;
4112411167fSJim Ingham 
412a72b31c7SJim Ingham       case 'O':
413fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
414fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
415a72b31c7SJim Ingham         break;
416a72b31c7SJim Ingham 
417ca36cd16SJim Ingham       case 'p':
418adcd0268SBenjamin Kramer         m_source_text_regexp.assign(std::string(option_arg));
419ca36cd16SJim Ingham         break;
420ca36cd16SJim Ingham 
421ca36cd16SJim Ingham       case 'r':
422adcd0268SBenjamin Kramer         m_func_regexp.assign(std::string(option_arg));
423ca36cd16SJim Ingham         break;
424ca36cd16SJim Ingham 
425ca36cd16SJim Ingham       case 's':
4268f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
427ca36cd16SJim Ingham         break;
428ca36cd16SJim Ingham 
429ca36cd16SJim Ingham       case 'S':
430adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
431ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
432ca36cd16SJim Ingham         break;
433ca36cd16SJim Ingham 
434b9c1b51eSKate Stone       case 'w': {
435ca36cd16SJim Ingham         bool success;
43647cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
437ca36cd16SJim Ingham         if (!success)
438b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
439fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
440fe11483bSZachary Turner               option_arg.str().c_str());
441b9c1b51eSKate Stone       } break;
442ca36cd16SJim Ingham 
44376bb8d67SJim Ingham       case 'X':
444adcd0268SBenjamin Kramer         m_source_regex_func_names.insert(std::string(option_arg));
44576bb8d67SJim Ingham         break;
44676bb8d67SJim Ingham 
44730fdc8d8SChris Lattner       default:
44836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
44930fdc8d8SChris Lattner       }
45030fdc8d8SChris Lattner 
45130fdc8d8SChris Lattner       return error;
45230fdc8d8SChris Lattner     }
4539e85e5a8SEugene Zelenko 
454b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
45587df91b8SJim Ingham       m_filenames.Clear();
45630fdc8d8SChris Lattner       m_line_num = 0;
45730fdc8d8SChris Lattner       m_column = 0;
458fab10e89SJim Ingham       m_func_names.clear();
4591f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
46030fdc8d8SChris Lattner       m_func_regexp.clear();
4611f746071SGreg Clayton       m_source_text_regexp.clear();
46287df91b8SJim Ingham       m_modules.Clear();
4631f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4642411167fSJim Ingham       m_offset_addr = 0;
465fab10e89SJim Ingham       m_catch_bp = false;
466fab10e89SJim Ingham       m_throw_bp = true;
467eb023e75SGreg Clayton       m_hardware = false;
468a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
46923b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
470a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4715e09c8c3SJim Ingham       m_breakpoint_names.clear();
472e732052fSJim Ingham       m_all_files = false;
473a72b31c7SJim Ingham       m_exception_extra_args.Clear();
474055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
47576bb8d67SJim Ingham       m_source_regex_func_names.clear();
4763815e702SJim Ingham       m_current_key.clear();
47730fdc8d8SChris Lattner     }
47830fdc8d8SChris Lattner 
4791f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
48070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
4811f0f5b5bSZachary Turner     }
48230fdc8d8SChris Lattner 
4835a988416SJim Ingham     // Instance variables to hold the values for command options.
484969795f1SJim Ingham 
4855a988416SJim Ingham     std::string m_condition;
4865a988416SJim Ingham     FileSpecList m_filenames;
4875a988416SJim Ingham     uint32_t m_line_num;
4885a988416SJim Ingham     uint32_t m_column;
4895a988416SJim Ingham     std::vector<std::string> m_func_names;
4905e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
491117b1fa1SZachary Turner     lldb::FunctionNameType m_func_name_type_mask;
4925a988416SJim Ingham     std::string m_func_regexp;
4935a988416SJim Ingham     std::string m_source_text_regexp;
4945a988416SJim Ingham     FileSpecList m_modules;
4955a988416SJim Ingham     lldb::addr_t m_load_addr;
4962411167fSJim Ingham     lldb::addr_t m_offset_addr;
4975a988416SJim Ingham     bool m_catch_bp;
4985a988416SJim Ingham     bool m_throw_bp;
499eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
500a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
50123b1decbSDawn Perchik     lldb::LanguageType m_language;
5025a988416SJim Ingham     LazyBool m_skip_prologue;
503e732052fSJim Ingham     bool m_all_files;
504a72b31c7SJim Ingham     Args m_exception_extra_args;
505055ad9beSIlia K     LazyBool m_move_to_nearest_code;
50676bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5073815e702SJim Ingham     std::string m_current_key;
5085a988416SJim Ingham   };
5095a988416SJim Ingham 
5105a988416SJim Ingham protected:
511b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
512cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
51330fdc8d8SChris Lattner 
51430fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
51530fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
51630fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
51730fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
518b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
519b9c1b51eSKate Stone     //   expression)
520b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
521b9c1b51eSKate Stone     //   to source text)
522b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
523b9c1b51eSKate Stone     //   given language.)
52430fdc8d8SChris Lattner 
52530fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
52630fdc8d8SChris Lattner 
527738af7a6SJim Ingham     if (!m_python_class_options.GetName().empty())
5283815e702SJim Ingham       break_type = eSetTypeScripted;
5293815e702SJim Ingham     else if (m_options.m_line_num != 0)
53030fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
53130fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
53230fdc8d8SChris Lattner       break_type = eSetTypeAddress;
533fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
53430fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
53530fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
53630fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
537969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
538969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
539a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
540fab10e89SJim Ingham       break_type = eSetTypeException;
54130fdc8d8SChris Lattner 
542b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
543274060b6SGreg Clayton     FileSpec module_spec;
544a8558b62SJim Ingham     const bool internal = false;
545a8558b62SJim Ingham 
546b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
547b9c1b51eSKate Stone     // that off.
548b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
549b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5502411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5512411167fSJim Ingham 
552b9c1b51eSKate Stone     switch (break_type) {
55330fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
55430fdc8d8SChris Lattner     {
55530fdc8d8SChris Lattner       FileSpec file;
556c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
557b9c1b51eSKate Stone       if (num_files == 0) {
558b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
55987df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
56087df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
56187df91b8SJim Ingham           return false;
56287df91b8SJim Ingham         }
563b9c1b51eSKate Stone       } else if (num_files > 1) {
564b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
565b9c1b51eSKate Stone                            "line breakpoints.");
56687df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
56787df91b8SJim Ingham         return false;
568b9c1b51eSKate Stone       } else
56987df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
57030fdc8d8SChris Lattner 
5711f746071SGreg Clayton       // Only check for inline functions if
5721f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5731f746071SGreg Clayton 
574cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
575cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
576cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
577cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
578b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
579b9c1b51eSKate Stone     } break;
5806eee5aa0SGreg Clayton 
58130fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
582055a08a4SJim Ingham     {
583b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
584b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
585b842f2ecSJim Ingham       //  will track the load location of the library.
586055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
587b9c1b51eSKate Stone       if (num_modules_specified == 1) {
588b9c1b51eSKate Stone         const FileSpec *file_spec =
589b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
590cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
591cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
592b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
593cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
594b842f2ecSJim Ingham                                         m_options.m_hardware);
595b9c1b51eSKate Stone       } else {
596b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
597b9c1b51eSKate Stone                            "address breakpoints.");
598055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
599055a08a4SJim Ingham         return false;
600055a08a4SJim Ingham       }
60130fdc8d8SChris Lattner       break;
602055a08a4SJim Ingham     }
60330fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6040c5cd90dSGreg Clayton     {
605117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6060c5cd90dSGreg Clayton 
6070c5cd90dSGreg Clayton       if (name_type_mask == 0)
608e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6090c5cd90dSGreg Clayton 
610cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
611cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
612cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
613cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
614b842f2ecSJim Ingham           m_options.m_hardware);
615b9c1b51eSKate Stone     } break;
6160c5cd90dSGreg Clayton 
617b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
618b9c1b51eSKate Stone                                  // name
61930fdc8d8SChris Lattner     {
62095eae423SZachary Turner       RegularExpression regexp(m_options.m_func_regexp);
6213af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
622b9c1b51eSKate Stone         result.AppendErrorWithFormat(
623b58af8d2SRaphael Isemann             "Function name regular expression could not be compiled: %s",
6243af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
625aaf68cd9SRaphael Isemann         // Check if the incorrect regex looks like a globbing expression and
626aaf68cd9SRaphael Isemann         // warn the user about it.
627aaf68cd9SRaphael Isemann         if (!m_options.m_func_regexp.empty()) {
628aaf68cd9SRaphael Isemann           if (m_options.m_func_regexp[0] == '*' ||
629aaf68cd9SRaphael Isemann               m_options.m_func_regexp[0] == '?')
630aaf68cd9SRaphael Isemann             result.AppendWarning(
631aaf68cd9SRaphael Isemann                 "Function name regex does not accept glob patterns.");
632aaf68cd9SRaphael Isemann         }
63330fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
634969795f1SJim Ingham         return false;
63530fdc8d8SChris Lattner       }
63687df91b8SJim Ingham 
637cb2380c9SRaphael Isemann       bp_sp = target.CreateFuncRegexBreakpoint(
6385aa1d819SJan Kratochvil           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
639cb2380c9SRaphael Isemann           m_options.m_language, m_options.m_skip_prologue, internal,
640b842f2ecSJim Ingham           m_options.m_hardware);
641a925974bSAdrian Prantl     } break;
642969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
643969795f1SJim Ingham     {
644c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
64587df91b8SJim Ingham 
646b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
647969795f1SJim Ingham         FileSpec file;
648b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
649b9c1b51eSKate Stone           result.AppendError(
650b9c1b51eSKate Stone               "No files provided and could not find default file.");
65187df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
65287df91b8SJim Ingham           return false;
653b9c1b51eSKate Stone         } else {
65487df91b8SJim Ingham           m_options.m_filenames.Append(file);
65587df91b8SJim Ingham         }
65687df91b8SJim Ingham       }
6570c5cd90dSGreg Clayton 
65895eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6593af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
660b9c1b51eSKate Stone         result.AppendErrorWithFormat(
661b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6623af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
663969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
664969795f1SJim Ingham         return false;
665969795f1SJim Ingham       }
666cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
667cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6685aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
669cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
670b9c1b51eSKate Stone     } break;
671b9c1b51eSKate Stone     case eSetTypeException: {
67297206d57SZachary Turner       Status precond_error;
673cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
674cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
675cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
676b842f2ecSJim Ingham           &precond_error);
677b9c1b51eSKate Stone       if (precond_error.Fail()) {
678b9c1b51eSKate Stone         result.AppendErrorWithFormat(
679b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
680a72b31c7SJim Ingham             precond_error.AsCString());
681cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
682a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
683a72b31c7SJim Ingham         return false;
684a72b31c7SJim Ingham       }
685b9c1b51eSKate Stone     } break;
6863815e702SJim Ingham     case eSetTypeScripted: {
6873815e702SJim Ingham 
6883815e702SJim Ingham       Status error;
689cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
690738af7a6SJim Ingham           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
691cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
692943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
6933815e702SJim Ingham       if (error.Fail()) {
6943815e702SJim Ingham         result.AppendErrorWithFormat(
695a925974bSAdrian Prantl             "Error setting extra exception arguments: %s", error.AsCString());
696cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
6973815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
6983815e702SJim Ingham         return false;
6993815e702SJim Ingham       }
7003815e702SJim Ingham     } break;
70130fdc8d8SChris Lattner     default:
70230fdc8d8SChris Lattner       break;
70330fdc8d8SChris Lattner     }
70430fdc8d8SChris Lattner 
7051b54c88cSJim Ingham     // Now set the various options that were passed in:
706b842f2ecSJim Ingham     if (bp_sp) {
707b842f2ecSJim Ingham       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
708ca36cd16SJim Ingham 
709b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
71097206d57SZachary Turner         Status name_error;
711ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
712cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
713ff9a91eaSJim Ingham           if (name_error.Fail()) {
714ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
715ff9a91eaSJim Ingham                                          name.c_str());
716cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
717ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
718ff9a91eaSJim Ingham             return false;
719ff9a91eaSJim Ingham           }
720ff9a91eaSJim Ingham         }
7215e09c8c3SJim Ingham       }
7221b54c88cSJim Ingham     }
7231b54c88cSJim Ingham 
724b842f2ecSJim Ingham     if (bp_sp) {
72585e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7261391cc7dSJim Ingham       const bool show_locations = false;
727b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
728b9c1b51eSKate Stone                             show_locations);
729cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
730b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
731b9c1b51eSKate Stone                              "into future targets.\n");
732b9c1b51eSKate Stone       else {
73305097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
73405097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
73505097246SAdrian Prantl         // set the breakpoint till we run.
736b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
737b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
738b9c1b51eSKate Stone                                "actual locations.\n");
7394aeb1989SJim Ingham         }
7404aeb1989SJim Ingham       }
74130fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
742b842f2ecSJim Ingham     } else if (!bp_sp) {
74330fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
74430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
74530fdc8d8SChris Lattner     }
74630fdc8d8SChris Lattner 
74730fdc8d8SChris Lattner     return result.Succeeded();
74830fdc8d8SChris Lattner   }
74930fdc8d8SChris Lattner 
7505a988416SJim Ingham private:
751cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
752b9c1b51eSKate Stone                       CommandReturnObject &result) {
7535a988416SJim Ingham     uint32_t default_line;
75405097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
75505097246SAdrian Prantl     // frame's file.
756cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
757b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
758b9c1b51eSKate Stone       if (cur_frame == nullptr) {
759b9c1b51eSKate Stone         result.AppendError(
760b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7615a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7625a988416SJim Ingham         return false;
763b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
764b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
765b9c1b51eSKate Stone                            "file, it has no debug info.");
7665a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7675a988416SJim Ingham         return false;
768b9c1b51eSKate Stone       } else {
769b9c1b51eSKate Stone         const SymbolContext &sc =
770b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
771b9c1b51eSKate Stone         if (sc.line_entry.file) {
7725a988416SJim Ingham           file = sc.line_entry.file;
773b9c1b51eSKate Stone         } else {
774b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
775b9c1b51eSKate Stone                              "use as the default file.");
7765a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
7775a988416SJim Ingham           return false;
7785a988416SJim Ingham         }
7795a988416SJim Ingham       }
7805a988416SJim Ingham     }
7815a988416SJim Ingham     return true;
7825a988416SJim Ingham   }
7835a988416SJim Ingham 
784b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
785b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
786943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
7875a988416SJim Ingham   CommandOptions m_options;
788b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
7895a988416SJim Ingham };
7909e85e5a8SEugene Zelenko 
7915a988416SJim Ingham // CommandObjectBreakpointModify
7925a988416SJim Ingham #pragma mark Modify
7935a988416SJim Ingham 
794b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
7955a988416SJim Ingham public:
796b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
797b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
798b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
799b9c1b51eSKate Stone                             "breakpoints in the executable.  "
800b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
801b9c1b51eSKate Stone                             "created breakpoint.  "
802b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
803b9c1b51eSKate Stone                             "empty argument clears the modification.",
8049e85e5a8SEugene Zelenko                             nullptr),
805b9c1b51eSKate Stone         m_options() {
8065a988416SJim Ingham     CommandArgumentEntry arg;
807b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
808b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
809b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
810b9c1b51eSKate Stone     // arguments vector.
8115a988416SJim Ingham     m_arguments.push_back(arg);
812b842f2ecSJim Ingham 
813b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
814b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
815b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
816b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
817b842f2ecSJim Ingham     m_options.Finalize();
8185a988416SJim Ingham   }
8195a988416SJim Ingham 
8209e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8215a988416SJim Ingham 
8220e50b9a4SGongyu Deng   void
8230e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8240e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8250e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
8260e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8270e50b9a4SGongyu Deng         request, nullptr);
8280e50b9a4SGongyu Deng   }
8290e50b9a4SGongyu Deng 
830b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8315a988416SJim Ingham 
8325a988416SJim Ingham protected:
833b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
834cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8355a988416SJim Ingham 
836bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
837cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8385a988416SJim Ingham 
8395a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8405a988416SJim Ingham 
841b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
842cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
843b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8445a988416SJim Ingham 
845b9c1b51eSKate Stone     if (result.Succeeded()) {
8465a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
847b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8485a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8495a988416SJim Ingham 
850b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
851b9c1b51eSKate Stone           Breakpoint *bp =
852cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
853b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
854b9c1b51eSKate Stone             BreakpointLocation *location =
855b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
856b842f2ecSJim Ingham             if (location)
857a925974bSAdrian Prantl               location->GetLocationOptions()->CopyOverSetOptions(
858a925974bSAdrian Prantl                   m_bp_opts.GetBreakpointOptions());
859b9c1b51eSKate Stone           } else {
860a925974bSAdrian Prantl             bp->GetOptions()->CopyOverSetOptions(
861a925974bSAdrian Prantl                 m_bp_opts.GetBreakpointOptions());
8625a988416SJim Ingham           }
8635a988416SJim Ingham         }
8645a988416SJim Ingham       }
8655a988416SJim Ingham     }
8665a988416SJim Ingham 
8675a988416SJim Ingham     return result.Succeeded();
8685a988416SJim Ingham   }
8695a988416SJim Ingham 
8705a988416SJim Ingham private:
871b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
872b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
873b842f2ecSJim Ingham   OptionGroupOptions m_options;
8745a988416SJim Ingham };
8755a988416SJim Ingham 
8765a988416SJim Ingham // CommandObjectBreakpointEnable
8775a988416SJim Ingham #pragma mark Enable
8785a988416SJim Ingham 
879b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8805a988416SJim Ingham public:
881b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
882b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
883b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
884b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
885b9c1b51eSKate Stone                             nullptr) {
8865a988416SJim Ingham     CommandArgumentEntry arg;
887b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
888b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
889b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
890b9c1b51eSKate Stone     // arguments vector.
8915a988416SJim Ingham     m_arguments.push_back(arg);
8925a988416SJim Ingham   }
8935a988416SJim Ingham 
8949e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
8955a988416SJim Ingham 
8960e50b9a4SGongyu Deng   void
8970e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8980e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8990e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
9000e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9010e50b9a4SGongyu Deng         request, nullptr);
9020e50b9a4SGongyu Deng   }
9030e50b9a4SGongyu Deng 
9045a988416SJim Ingham protected:
905b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
906cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9075a988416SJim Ingham 
908bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
909cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9105a988416SJim Ingham 
911cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9125a988416SJim Ingham 
9135a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9145a988416SJim Ingham 
915b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9165a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9175a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9185a988416SJim Ingham       return false;
9195a988416SJim Ingham     }
9205a988416SJim Ingham 
92111eb9c64SZachary Turner     if (command.empty()) {
9225a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
923cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
924b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
925b9c1b51eSKate Stone                                      " breakpoints)\n",
926b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9275a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
928b9c1b51eSKate Stone     } else {
9295a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9305a988416SJim Ingham       BreakpointIDList valid_bp_ids;
931b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
932cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
933b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9345a988416SJim Ingham 
935b9c1b51eSKate Stone       if (result.Succeeded()) {
9365a988416SJim Ingham         int enable_count = 0;
9375a988416SJim Ingham         int loc_count = 0;
9385a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
939b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9405a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9415a988416SJim Ingham 
942b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
943b9c1b51eSKate Stone             Breakpoint *breakpoint =
944cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
945b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
946b9c1b51eSKate Stone               BreakpointLocation *location =
947b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
948b9c1b51eSKate Stone               if (location) {
9495a988416SJim Ingham                 location->SetEnabled(true);
9505a988416SJim Ingham                 ++loc_count;
9515a988416SJim Ingham               }
952b9c1b51eSKate Stone             } else {
9535a988416SJim Ingham               breakpoint->SetEnabled(true);
9545a988416SJim Ingham               ++enable_count;
9555a988416SJim Ingham             }
9565a988416SJim Ingham           }
9575a988416SJim Ingham         }
958b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
959b9c1b51eSKate Stone                                        enable_count + loc_count);
9605a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9615a988416SJim Ingham       }
9625a988416SJim Ingham     }
9635a988416SJim Ingham 
9645a988416SJim Ingham     return result.Succeeded();
9655a988416SJim Ingham   }
9665a988416SJim Ingham };
9675a988416SJim Ingham 
9685a988416SJim Ingham // CommandObjectBreakpointDisable
9695a988416SJim Ingham #pragma mark Disable
9705a988416SJim Ingham 
971b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9725a988416SJim Ingham public:
9737428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
974b9c1b51eSKate Stone       : CommandObjectParsed(
975b9c1b51eSKate Stone             interpreter, "breakpoint disable",
976b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9777428a18cSKate Stone             "them.  If none are specified, disable all "
9787428a18cSKate Stone             "breakpoints.",
979b9c1b51eSKate Stone             nullptr) {
980b9c1b51eSKate Stone     SetHelpLong(
981b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9827428a18cSKate Stone If none are specified, disable all breakpoints."
9837428a18cSKate Stone         R"(
984ea671fbdSKate Stone 
9857428a18cSKate Stone )"
9867428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
9877428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
9887428a18cSKate Stone         R"(
989ea671fbdSKate Stone 
990ea671fbdSKate Stone     (lldb) break disable 1
991ea671fbdSKate Stone     (lldb) break enable 1.1
992ea671fbdSKate Stone 
993ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
994ea671fbdSKate Stone 
995ea671fbdSKate Stone     (lldb) break disable 1.*
996ea671fbdSKate Stone     (lldb) break enable 1.1
997ea671fbdSKate Stone 
9987428a18cSKate Stone )"
9997428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10007428a18cSKate Stone the second re-enables the first location.");
1001b0fac509SJim Ingham 
10025a988416SJim Ingham     CommandArgumentEntry arg;
1003b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1004b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1005b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1006b9c1b51eSKate Stone     // arguments vector.
10075a988416SJim Ingham     m_arguments.push_back(arg);
10085a988416SJim Ingham   }
10095a988416SJim Ingham 
10109e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10115a988416SJim Ingham 
10120e50b9a4SGongyu Deng   void
10130e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
10140e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
10150e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
10160e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10170e50b9a4SGongyu Deng         request, nullptr);
10180e50b9a4SGongyu Deng   }
10190e50b9a4SGongyu Deng 
10205a988416SJim Ingham protected:
1021b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1022cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1023bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1024cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10255a988416SJim Ingham 
1026cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10275a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10285a988416SJim Ingham 
1029b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10305a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10315a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10325a988416SJim Ingham       return false;
10335a988416SJim Ingham     }
10345a988416SJim Ingham 
103511eb9c64SZachary Turner     if (command.empty()) {
10365a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1037cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1038b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1039b9c1b51eSKate Stone                                      " breakpoints)\n",
1040b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10415a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1042b9c1b51eSKate Stone     } else {
10435a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10445a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10455a988416SJim Ingham 
1046b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1047cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1048b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10495a988416SJim Ingham 
1050b9c1b51eSKate Stone       if (result.Succeeded()) {
10515a988416SJim Ingham         int disable_count = 0;
10525a988416SJim Ingham         int loc_count = 0;
10535a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1054b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10555a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10565a988416SJim Ingham 
1057b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1058b9c1b51eSKate Stone             Breakpoint *breakpoint =
1059cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1060b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1061b9c1b51eSKate Stone               BreakpointLocation *location =
1062b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1063b9c1b51eSKate Stone               if (location) {
10645a988416SJim Ingham                 location->SetEnabled(false);
10655a988416SJim Ingham                 ++loc_count;
10665a988416SJim Ingham               }
1067b9c1b51eSKate Stone             } else {
10685a988416SJim Ingham               breakpoint->SetEnabled(false);
10695a988416SJim Ingham               ++disable_count;
10705a988416SJim Ingham             }
10715a988416SJim Ingham           }
10725a988416SJim Ingham         }
1073b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1074b9c1b51eSKate Stone                                        disable_count + loc_count);
10755a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10765a988416SJim Ingham       }
10775a988416SJim Ingham     }
10785a988416SJim Ingham 
10795a988416SJim Ingham     return result.Succeeded();
10805a988416SJim Ingham   }
10815a988416SJim Ingham };
10825a988416SJim Ingham 
10835a988416SJim Ingham // CommandObjectBreakpointList
10841f0f5b5bSZachary Turner 
10851f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10866f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1087c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10881f0f5b5bSZachary Turner 
10895a988416SJim Ingham #pragma mark List
10905a988416SJim Ingham 
1091b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
10925a988416SJim Ingham public:
1093b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1094b9c1b51eSKate Stone       : CommandObjectParsed(
1095b9c1b51eSKate Stone             interpreter, "breakpoint list",
10965a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
10979e85e5a8SEugene Zelenko             nullptr),
1098b9c1b51eSKate Stone         m_options() {
10995a988416SJim Ingham     CommandArgumentEntry arg;
11005a988416SJim Ingham     CommandArgumentData bp_id_arg;
11015a988416SJim Ingham 
11025a988416SJim Ingham     // Define the first (and only) variant of this arg.
11035a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11045a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11055a988416SJim Ingham 
1106b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1107b9c1b51eSKate Stone     // argument entry.
11085a988416SJim Ingham     arg.push_back(bp_id_arg);
11095a988416SJim Ingham 
11105a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11115a988416SJim Ingham     m_arguments.push_back(arg);
11125a988416SJim Ingham   }
11135a988416SJim Ingham 
11149e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11155a988416SJim Ingham 
1116b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11175a988416SJim Ingham 
1118b9c1b51eSKate Stone   class CommandOptions : public Options {
11195a988416SJim Ingham   public:
1120b9c1b51eSKate Stone     CommandOptions()
1121b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
11225a988416SJim Ingham     }
11235a988416SJim Ingham 
11249e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11255a988416SJim Ingham 
112697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1127b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
112897206d57SZachary Turner       Status error;
11293bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11305a988416SJim Ingham 
1131b9c1b51eSKate Stone       switch (short_option) {
11325a988416SJim Ingham       case 'b':
11335a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11345a988416SJim Ingham         break;
113533df7cd3SJim Ingham       case 'D':
113633df7cd3SJim Ingham         m_use_dummy = true;
113733df7cd3SJim Ingham         break;
11385a988416SJim Ingham       case 'f':
11395a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11405a988416SJim Ingham         break;
11415a988416SJim Ingham       case 'v':
11425a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11435a988416SJim Ingham         break;
11445a988416SJim Ingham       case 'i':
11455a988416SJim Ingham         m_internal = true;
11465a988416SJim Ingham         break;
11475a988416SJim Ingham       default:
114836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11495a988416SJim Ingham       }
11505a988416SJim Ingham 
11515a988416SJim Ingham       return error;
11525a988416SJim Ingham     }
11535a988416SJim Ingham 
1154b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11555a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11565a988416SJim Ingham       m_internal = false;
115733df7cd3SJim Ingham       m_use_dummy = false;
11585a988416SJim Ingham     }
11595a988416SJim Ingham 
11601f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11621f0f5b5bSZachary Turner     }
11635a988416SJim Ingham 
11645a988416SJim Ingham     // Instance variables to hold the values for command options.
11655a988416SJim Ingham 
11665a988416SJim Ingham     lldb::DescriptionLevel m_level;
11675a988416SJim Ingham 
11685a988416SJim Ingham     bool m_internal;
116933df7cd3SJim Ingham     bool m_use_dummy;
11705a988416SJim Ingham   };
11715a988416SJim Ingham 
11725a988416SJim Ingham protected:
1173b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1174cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11755a988416SJim Ingham 
1176b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1177cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1178bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1179cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11805a988416SJim Ingham 
11815a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11825a988416SJim Ingham 
1183b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11845a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11855a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11865a988416SJim Ingham       return true;
11875a988416SJim Ingham     }
11885a988416SJim Ingham 
11895a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
11905a988416SJim Ingham 
119111eb9c64SZachary Turner     if (command.empty()) {
11925a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
11935a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1194b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
11955a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1196b842f2ecSJim Ingham         if (breakpoint->AllowList())
1197b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1198b842f2ecSJim Ingham                                    m_options.m_level);
11995a988416SJim Ingham       }
12005a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1201b9c1b51eSKate Stone     } else {
12025a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12035a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1204b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1205cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1206b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12075a988416SJim Ingham 
1208b9c1b51eSKate Stone       if (result.Succeeded()) {
1209b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12105a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1211b9c1b51eSKate Stone           Breakpoint *breakpoint =
1212cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1213b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1214b9c1b51eSKate Stone                                    m_options.m_level);
12155a988416SJim Ingham         }
12165a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1217b9c1b51eSKate Stone       } else {
12187428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12195a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
12205a988416SJim Ingham       }
12215a988416SJim Ingham     }
12225a988416SJim Ingham 
12235a988416SJim Ingham     return result.Succeeded();
12245a988416SJim Ingham   }
12255a988416SJim Ingham 
12265a988416SJim Ingham private:
12275a988416SJim Ingham   CommandOptions m_options;
12285a988416SJim Ingham };
12295a988416SJim Ingham 
12305a988416SJim Ingham // CommandObjectBreakpointClear
12311f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12321f0f5b5bSZachary Turner 
1233f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1234f94668e3SRaphael Isemann #include "CommandOptions.inc"
12351f0f5b5bSZachary Turner 
12365a988416SJim Ingham #pragma mark Clear
12375a988416SJim Ingham 
1238b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12395a988416SJim Ingham public:
1240efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12415a988416SJim Ingham 
12427428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12437428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1244b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1245b9c1b51eSKate Stone                             "specified source file and line.",
12465a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1247b9c1b51eSKate Stone         m_options() {}
12485a988416SJim Ingham 
12499e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12505a988416SJim Ingham 
1251b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12525a988416SJim Ingham 
1253b9c1b51eSKate Stone   class CommandOptions : public Options {
12545a988416SJim Ingham   public:
1255b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
12565a988416SJim Ingham 
12579e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12585a988416SJim Ingham 
125997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1260b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
126197206d57SZachary Turner       Status error;
12623bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12635a988416SJim Ingham 
1264b9c1b51eSKate Stone       switch (short_option) {
12655a988416SJim Ingham       case 'f':
1266adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
12675a988416SJim Ingham         break;
12685a988416SJim Ingham 
12695a988416SJim Ingham       case 'l':
1270fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12715a988416SJim Ingham         break;
12725a988416SJim Ingham 
12735a988416SJim Ingham       default:
127436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12755a988416SJim Ingham       }
12765a988416SJim Ingham 
12775a988416SJim Ingham       return error;
12785a988416SJim Ingham     }
12795a988416SJim Ingham 
1280b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12815a988416SJim Ingham       m_filename.clear();
12825a988416SJim Ingham       m_line_num = 0;
12835a988416SJim Ingham     }
12845a988416SJim Ingham 
12851f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
128670602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12871f0f5b5bSZachary Turner     }
12885a988416SJim Ingham 
12895a988416SJim Ingham     // Instance variables to hold the values for command options.
12905a988416SJim Ingham 
12915a988416SJim Ingham     std::string m_filename;
12925a988416SJim Ingham     uint32_t m_line_num;
12935a988416SJim Ingham   };
12945a988416SJim Ingham 
12955a988416SJim Ingham protected:
1296b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1297cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
12985a988416SJim Ingham 
129905097246SAdrian Prantl     // The following are the various types of breakpoints that could be
130005097246SAdrian Prantl     // cleared:
13015a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13025a988416SJim Ingham 
13035a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13045a988416SJim Ingham 
13055a988416SJim Ingham     if (m_options.m_line_num != 0)
13065a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13075a988416SJim Ingham 
1308bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1309cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13105a988416SJim Ingham 
1311cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13125a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13135a988416SJim Ingham 
13145a988416SJim Ingham     // Early return if there's no breakpoint at all.
1315b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13165a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13175a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13185a988416SJim Ingham       return result.Succeeded();
13195a988416SJim Ingham     }
13205a988416SJim Ingham 
13215a988416SJim Ingham     // Find matching breakpoints and delete them.
13225a988416SJim Ingham 
13235a988416SJim Ingham     // First create a copy of all the IDs.
13245a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13255a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13269e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13275a988416SJim Ingham 
13285a988416SJim Ingham     int num_cleared = 0;
13295a988416SJim Ingham     StreamString ss;
1330b9c1b51eSKate Stone     switch (break_type) {
13315a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13325a988416SJim Ingham     {
13335a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13345a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13355a988416SJim Ingham 
1336b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13375a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13385a988416SJim Ingham 
1339b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1340b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1341b9c1b51eSKate Stone           // remove the breakpoint.
1342b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13435a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13445a988416SJim Ingham             ss.EOL();
1345cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13465a988416SJim Ingham             ++num_cleared;
13475a988416SJim Ingham           }
13485a988416SJim Ingham         }
13495a988416SJim Ingham       }
1350b9c1b51eSKate Stone     } break;
13515a988416SJim Ingham 
13525a988416SJim Ingham     default:
13535a988416SJim Ingham       break;
13545a988416SJim Ingham     }
13555a988416SJim Ingham 
1356b9c1b51eSKate Stone     if (num_cleared > 0) {
13575a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13585a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1359c156427dSZachary Turner       output_stream << ss.GetString();
13605a988416SJim Ingham       output_stream.EOL();
13615a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1362b9c1b51eSKate Stone     } else {
13635a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13645a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13655a988416SJim Ingham     }
13665a988416SJim Ingham 
13675a988416SJim Ingham     return result.Succeeded();
13685a988416SJim Ingham   }
13695a988416SJim Ingham 
13705a988416SJim Ingham private:
13715a988416SJim Ingham   CommandOptions m_options;
13725a988416SJim Ingham };
13735a988416SJim Ingham 
13745a988416SJim Ingham // CommandObjectBreakpointDelete
1375f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1376f94668e3SRaphael Isemann #include "CommandOptions.inc"
13771f0f5b5bSZachary Turner 
13785a988416SJim Ingham #pragma mark Delete
13795a988416SJim Ingham 
1380b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13815a988416SJim Ingham public:
1382b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1383b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1384b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1385b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
13869e85e5a8SEugene Zelenko                             nullptr),
1387b9c1b51eSKate Stone         m_options() {
13885a988416SJim Ingham     CommandArgumentEntry arg;
1389b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1390b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1391b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1392b9c1b51eSKate Stone     // arguments vector.
13935a988416SJim Ingham     m_arguments.push_back(arg);
13945a988416SJim Ingham   }
13955a988416SJim Ingham 
13969e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
13975a988416SJim Ingham 
13980e50b9a4SGongyu Deng   void
13990e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
14000e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
14010e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
14020e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
14030e50b9a4SGongyu Deng         request, nullptr);
14040e50b9a4SGongyu Deng   }
14050e50b9a4SGongyu Deng 
1406b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
140733df7cd3SJim Ingham 
1408b9c1b51eSKate Stone   class CommandOptions : public Options {
140933df7cd3SJim Ingham   public:
1410b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
141133df7cd3SJim Ingham 
14129e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
141333df7cd3SJim Ingham 
141497206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1415b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
141697206d57SZachary Turner       Status error;
141733df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
141833df7cd3SJim Ingham 
1419b9c1b51eSKate Stone       switch (short_option) {
142033df7cd3SJim Ingham       case 'f':
142133df7cd3SJim Ingham         m_force = true;
142233df7cd3SJim Ingham         break;
142333df7cd3SJim Ingham 
142433df7cd3SJim Ingham       case 'D':
142533df7cd3SJim Ingham         m_use_dummy = true;
142633df7cd3SJim Ingham         break;
142733df7cd3SJim Ingham 
142833df7cd3SJim Ingham       default:
142936162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
143033df7cd3SJim Ingham       }
143133df7cd3SJim Ingham 
143233df7cd3SJim Ingham       return error;
143333df7cd3SJim Ingham     }
143433df7cd3SJim Ingham 
1435b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
143633df7cd3SJim Ingham       m_use_dummy = false;
143733df7cd3SJim Ingham       m_force = false;
143833df7cd3SJim Ingham     }
143933df7cd3SJim Ingham 
14401f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
144170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14421f0f5b5bSZachary Turner     }
144333df7cd3SJim Ingham 
144433df7cd3SJim Ingham     // Instance variables to hold the values for command options.
144533df7cd3SJim Ingham     bool m_use_dummy;
144633df7cd3SJim Ingham     bool m_force;
144733df7cd3SJim Ingham   };
144833df7cd3SJim Ingham 
14495a988416SJim Ingham protected:
1450b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1451cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14525a988416SJim Ingham 
1453bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1454cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14555a988416SJim Ingham 
1456cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
14575a988416SJim Ingham 
14585a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14595a988416SJim Ingham 
1460b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14615a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14625a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14635a988416SJim Ingham       return false;
14645a988416SJim Ingham     }
14655a988416SJim Ingham 
146611eb9c64SZachary Turner     if (command.empty()) {
1467b9c1b51eSKate Stone       if (!m_options.m_force &&
1468b9c1b51eSKate Stone           !m_interpreter.Confirm(
1469b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1470b9c1b51eSKate Stone               true)) {
14715a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1472b9c1b51eSKate Stone       } else {
1473cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1474b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1475b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1476b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14775a988416SJim Ingham       }
14785a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1479b9c1b51eSKate Stone     } else {
14805a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
14815a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1482b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1483cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1484b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
14855a988416SJim Ingham 
1486b9c1b51eSKate Stone       if (result.Succeeded()) {
14875a988416SJim Ingham         int delete_count = 0;
14885a988416SJim Ingham         int disable_count = 0;
14895a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1490b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
14915a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
14925a988416SJim Ingham 
1493b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1494b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1495b9c1b51eSKate Stone               Breakpoint *breakpoint =
1496cb2380c9SRaphael Isemann                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1497b9c1b51eSKate Stone               BreakpointLocation *location =
1498b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1499b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1500b9c1b51eSKate Stone               // disable them instead.
1501b9c1b51eSKate Stone               if (location) {
15025a988416SJim Ingham                 location->SetEnabled(false);
15035a988416SJim Ingham                 ++disable_count;
15045a988416SJim Ingham               }
1505b9c1b51eSKate Stone             } else {
1506cb2380c9SRaphael Isemann               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15075a988416SJim Ingham               ++delete_count;
15085a988416SJim Ingham             }
15095a988416SJim Ingham           }
15105a988416SJim Ingham         }
1511b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1512b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15135a988416SJim Ingham             delete_count, disable_count);
15145a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
15155a988416SJim Ingham       }
15165a988416SJim Ingham     }
15175a988416SJim Ingham     return result.Succeeded();
15185a988416SJim Ingham   }
15199e85e5a8SEugene Zelenko 
152033df7cd3SJim Ingham private:
152133df7cd3SJim Ingham   CommandOptions m_options;
152233df7cd3SJim Ingham };
152333df7cd3SJim Ingham 
15245e09c8c3SJim Ingham // CommandObjectBreakpointName
1525f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1526f94668e3SRaphael Isemann #include "CommandOptions.inc"
1527bd68a052SRaphael Isemann 
1528b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15295e09c8c3SJim Ingham public:
1530b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1531b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15325e09c8c3SJim Ingham   }
15335e09c8c3SJim Ingham 
15349e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15355e09c8c3SJim Ingham 
15361f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
153770602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15385e09c8c3SJim Ingham   }
15395e09c8c3SJim Ingham 
154097206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1541b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
154297206d57SZachary Turner     Status error;
15435e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15445e09c8c3SJim Ingham 
1545b9c1b51eSKate Stone     switch (short_option) {
15465e09c8c3SJim Ingham     case 'N':
1547fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1548b9c1b51eSKate Stone           error.Success())
1549fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15505e09c8c3SJim Ingham       break;
15515e09c8c3SJim Ingham     case 'B':
1552fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1553b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15548cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1555fe11483bSZachary Turner             option_arg.str().c_str());
15565e09c8c3SJim Ingham       break;
15575e09c8c3SJim Ingham     case 'D':
1558fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1559b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15608cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1561fe11483bSZachary Turner             option_arg.str().c_str());
15625e09c8c3SJim Ingham       break;
1563e9632ebaSJim Ingham     case 'H':
1564e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1565e9632ebaSJim Ingham       break;
15665e09c8c3SJim Ingham 
15675e09c8c3SJim Ingham     default:
156836162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15695e09c8c3SJim Ingham     }
15705e09c8c3SJim Ingham     return error;
15715e09c8c3SJim Ingham   }
15725e09c8c3SJim Ingham 
1573b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
15745e09c8c3SJim Ingham     m_name.Clear();
15755e09c8c3SJim Ingham     m_breakpoint.Clear();
15765e09c8c3SJim Ingham     m_use_dummy.Clear();
15775e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1578e9632ebaSJim Ingham     m_help_string.Clear();
15795e09c8c3SJim Ingham   }
15805e09c8c3SJim Ingham 
15815e09c8c3SJim Ingham   OptionValueString m_name;
15825e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
15835e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1584e9632ebaSJim Ingham   OptionValueString m_help_string;
15855e09c8c3SJim Ingham };
15865e09c8c3SJim Ingham 
1587f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1588f94668e3SRaphael Isemann #include "CommandOptions.inc"
1589b842f2ecSJim Ingham 
15908fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1591b842f2ecSJim Ingham public:
15928fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1593b842f2ecSJim Ingham 
1594b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1595b842f2ecSJim Ingham 
1596b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1597b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1598b842f2ecSJim Ingham   }
1599b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1600b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1601b842f2ecSJim Ingham     Status error;
1602a925974bSAdrian Prantl     const int short_option =
1603a925974bSAdrian Prantl         g_breakpoint_access_options[option_idx].short_option;
1604b842f2ecSJim Ingham 
1605b842f2ecSJim Ingham     switch (short_option) {
1606b842f2ecSJim Ingham     case 'L': {
1607b842f2ecSJim Ingham       bool value, success;
160847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1609b842f2ecSJim Ingham       if (success) {
1610b842f2ecSJim Ingham         m_permissions.SetAllowList(value);
1611b842f2ecSJim Ingham       } else
1612b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1613b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1614b842f2ecSJim Ingham             option_arg.str().c_str());
1615b842f2ecSJim Ingham     } break;
1616b842f2ecSJim Ingham     case 'A': {
1617b842f2ecSJim Ingham       bool value, success;
161847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1619b842f2ecSJim Ingham       if (success) {
1620b842f2ecSJim Ingham         m_permissions.SetAllowDisable(value);
1621b842f2ecSJim Ingham       } else
1622b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1623b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1624b842f2ecSJim Ingham             option_arg.str().c_str());
1625b842f2ecSJim Ingham     } break;
1626b842f2ecSJim Ingham     case 'D': {
1627b842f2ecSJim Ingham       bool value, success;
162847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1629b842f2ecSJim Ingham       if (success) {
1630b842f2ecSJim Ingham         m_permissions.SetAllowDelete(value);
1631b842f2ecSJim Ingham       } else
1632b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1633b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1634b842f2ecSJim Ingham             option_arg.str().c_str());
1635b842f2ecSJim Ingham     } break;
163636162014SRaphael Isemann     default:
163736162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
1638b842f2ecSJim Ingham     }
1639b842f2ecSJim Ingham 
1640b842f2ecSJim Ingham     return error;
1641b842f2ecSJim Ingham   }
1642b842f2ecSJim Ingham 
1643a925974bSAdrian Prantl   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1644b842f2ecSJim Ingham 
1645a925974bSAdrian Prantl   const BreakpointName::Permissions &GetPermissions() const {
1646b842f2ecSJim Ingham     return m_permissions;
1647b842f2ecSJim Ingham   }
1648b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1649b842f2ecSJim Ingham };
1650b842f2ecSJim Ingham 
1651b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1652b842f2ecSJim Ingham public:
1653b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1654b842f2ecSJim Ingham       : CommandObjectParsed(
1655a925974bSAdrian Prantl             interpreter, "configure",
1656a925974bSAdrian Prantl             "Configure the options for the breakpoint"
1657b842f2ecSJim Ingham             " name provided.  "
1658b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1659b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1660b842f2ecSJim Ingham             "on the name.",
1661b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1662b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1663b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1664b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1665b842f2ecSJim Ingham     // command.
1666b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1667b842f2ecSJim Ingham     CommandArgumentData id_arg;
1668b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1669b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1670b842f2ecSJim Ingham     arg1.push_back(id_arg);
1671b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1672b842f2ecSJim Ingham 
1673a925974bSAdrian Prantl     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1674a925974bSAdrian Prantl     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1675b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1676a925974bSAdrian Prantl     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1677e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1678b842f2ecSJim Ingham     m_option_group.Finalize();
1679b842f2ecSJim Ingham   }
1680b842f2ecSJim Ingham 
1681b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1682b842f2ecSJim Ingham 
1683b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1684b842f2ecSJim Ingham 
1685b842f2ecSJim Ingham protected:
1686b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1687b842f2ecSJim Ingham 
1688b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1689b842f2ecSJim Ingham     if (argc == 0) {
1690b842f2ecSJim Ingham       result.AppendError("No names provided.");
1691b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1692b842f2ecSJim Ingham       return false;
1693b842f2ecSJim Ingham     }
1694b842f2ecSJim Ingham 
1695cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1696b842f2ecSJim Ingham 
1697b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1698cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1699b842f2ecSJim Ingham 
1700b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1701b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1702b842f2ecSJim Ingham       Status error;
1703a925974bSAdrian Prantl       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1704b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1705b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1706b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1707b842f2ecSJim Ingham         return false;
1708b842f2ecSJim Ingham       }
1709b842f2ecSJim Ingham     }
171005097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
171105097246SAdrian Prantl     // check the error:
1712b842f2ecSJim Ingham     BreakpointSP bp_sp;
1713a925974bSAdrian Prantl     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1714b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1715cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1716a925974bSAdrian Prantl       if (!bp_sp) {
1717b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1718b842f2ecSJim Ingham                                       bp_id);
1719b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1720b842f2ecSJim Ingham         return false;
1721b842f2ecSJim Ingham       }
1722b842f2ecSJim Ingham     }
1723b842f2ecSJim Ingham 
1724b842f2ecSJim Ingham     Status error;
1725b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1726b842f2ecSJim Ingham       ConstString name(entry.c_str());
1727cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1728b842f2ecSJim Ingham       if (!bp_name)
1729b842f2ecSJim Ingham         continue;
1730e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1731e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1732e9632ebaSJim Ingham 
1733b842f2ecSJim Ingham       if (bp_sp)
1734cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1735b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1736b842f2ecSJim Ingham       else
1737cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1738b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1739b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1740b842f2ecSJim Ingham     }
1741b842f2ecSJim Ingham     return true;
1742b842f2ecSJim Ingham   }
1743b842f2ecSJim Ingham 
1744b842f2ecSJim Ingham private:
1745b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1746b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1747b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1748b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1749b842f2ecSJim Ingham };
1750b842f2ecSJim Ingham 
1751b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17525e09c8c3SJim Ingham public:
1753b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1754b9c1b51eSKate Stone       : CommandObjectParsed(
1755b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
17565e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1757b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1758b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1759b9c1b51eSKate Stone     // command.
17605e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17615e09c8c3SJim Ingham     CommandArgumentData id_arg;
17625e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17635e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17645e09c8c3SJim Ingham     arg1.push_back(id_arg);
17655e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17665e09c8c3SJim Ingham 
17675e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17685e09c8c3SJim Ingham     m_option_group.Finalize();
17695e09c8c3SJim Ingham   }
17705e09c8c3SJim Ingham 
17719e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17725e09c8c3SJim Ingham 
1773*e87362e6SGongyu Deng   void
1774*e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1775*e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1776*e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1777*e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1778*e87362e6SGongyu Deng         request, nullptr);
1779*e87362e6SGongyu Deng   }
1780*e87362e6SGongyu Deng 
1781b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
17825e09c8c3SJim Ingham 
17835e09c8c3SJim Ingham protected:
1784b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1785b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
17865e09c8c3SJim Ingham       result.SetError("No name option provided.");
17875e09c8c3SJim Ingham       return false;
17885e09c8c3SJim Ingham     }
17895e09c8c3SJim Ingham 
1790cb2380c9SRaphael Isemann     Target &target =
1791b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
17925e09c8c3SJim Ingham 
1793bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1794cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
17955e09c8c3SJim Ingham 
1796cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
17975e09c8c3SJim Ingham 
17985e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1799b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18005e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18015e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18025e09c8c3SJim Ingham       return false;
18035e09c8c3SJim Ingham     }
18045e09c8c3SJim Ingham 
18055e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18065e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1807b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1808cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1809b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18105e09c8c3SJim Ingham 
1811b9c1b51eSKate Stone     if (result.Succeeded()) {
1812b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18135e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18145e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18155e09c8c3SJim Ingham         return false;
18165e09c8c3SJim Ingham       }
18175e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1818b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1819b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1820b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1821b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1822b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1823b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18245e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1825cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18265e09c8c3SJim Ingham       }
18275e09c8c3SJim Ingham     }
18285e09c8c3SJim Ingham 
18295e09c8c3SJim Ingham     return true;
18305e09c8c3SJim Ingham   }
18315e09c8c3SJim Ingham 
18325e09c8c3SJim Ingham private:
18335e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18345e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18355e09c8c3SJim Ingham };
18365e09c8c3SJim Ingham 
1837b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18385e09c8c3SJim Ingham public:
1839b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1840b9c1b51eSKate Stone       : CommandObjectParsed(
1841b9c1b51eSKate Stone             interpreter, "delete",
18425e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18435e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1844b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1845b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1846b9c1b51eSKate Stone     // command.
18475e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18485e09c8c3SJim Ingham     CommandArgumentData id_arg;
18495e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18505e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18515e09c8c3SJim Ingham     arg1.push_back(id_arg);
18525e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18535e09c8c3SJim Ingham 
18545e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18555e09c8c3SJim Ingham     m_option_group.Finalize();
18565e09c8c3SJim Ingham   }
18575e09c8c3SJim Ingham 
18589e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18595e09c8c3SJim Ingham 
1860*e87362e6SGongyu Deng   void
1861*e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1862*e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1863*e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1864*e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1865*e87362e6SGongyu Deng         request, nullptr);
1866*e87362e6SGongyu Deng   }
1867*e87362e6SGongyu Deng 
1868b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18695e09c8c3SJim Ingham 
18705e09c8c3SJim Ingham protected:
1871b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1872b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18735e09c8c3SJim Ingham       result.SetError("No name option provided.");
18745e09c8c3SJim Ingham       return false;
18755e09c8c3SJim Ingham     }
18765e09c8c3SJim Ingham 
1877cb2380c9SRaphael Isemann     Target &target =
1878b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18795e09c8c3SJim Ingham 
1880bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1881cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18825e09c8c3SJim Ingham 
1883cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18845e09c8c3SJim Ingham 
18855e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1886b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18875e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
18885e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18895e09c8c3SJim Ingham       return false;
18905e09c8c3SJim Ingham     }
18915e09c8c3SJim Ingham 
18925e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18935e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1894b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1895cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1896b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
18975e09c8c3SJim Ingham 
1898b9c1b51eSKate Stone     if (result.Succeeded()) {
1899b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19005e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
19015e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19025e09c8c3SJim Ingham         return false;
19035e09c8c3SJim Ingham       }
1904b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19055e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1906b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1907b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1908b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19095e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1910cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19115e09c8c3SJim Ingham       }
19125e09c8c3SJim Ingham     }
19135e09c8c3SJim Ingham 
19145e09c8c3SJim Ingham     return true;
19155e09c8c3SJim Ingham   }
19165e09c8c3SJim Ingham 
19175e09c8c3SJim Ingham private:
19185e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19195e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19205e09c8c3SJim Ingham };
19215e09c8c3SJim Ingham 
1922b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19235e09c8c3SJim Ingham public:
1924b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1925b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1926b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1927b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1928b842f2ecSJim Ingham                             "names",
19295e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1930b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1931b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19325e09c8c3SJim Ingham     m_option_group.Finalize();
19335e09c8c3SJim Ingham   }
19345e09c8c3SJim Ingham 
19359e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19365e09c8c3SJim Ingham 
1937b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19385e09c8c3SJim Ingham 
19395e09c8c3SJim Ingham protected:
1940b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1941cb2380c9SRaphael Isemann     Target &target =
1942b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19435e09c8c3SJim Ingham 
1944b842f2ecSJim Ingham     std::vector<std::string> name_list;
1945b842f2ecSJim Ingham     if (command.empty()) {
1946cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1947b842f2ecSJim Ingham     } else {
1948a925974bSAdrian Prantl       for (const Args::ArgEntry &arg : command) {
1949b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1950b842f2ecSJim Ingham       }
1951b842f2ecSJim Ingham     }
1952b842f2ecSJim Ingham 
1953b842f2ecSJim Ingham     if (name_list.empty()) {
1954b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1955b842f2ecSJim Ingham     } else {
1956b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1957b842f2ecSJim Ingham         const char *name = name_str.c_str();
1958b842f2ecSJim Ingham         // First print out the options for the name:
1959b842f2ecSJim Ingham         Status error;
1960cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1961cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1962a925974bSAdrian Prantl         if (bp_name) {
1963b842f2ecSJim Ingham           StreamString s;
1964b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1965a925974bSAdrian Prantl           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1966b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1967b842f2ecSJim Ingham           }
1968b842f2ecSJim Ingham 
1969bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1970cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19715e09c8c3SJim Ingham 
1972cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1973b842f2ecSJim Ingham           bool any_set = false;
1974b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1975b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19765e09c8c3SJim Ingham               StreamString s;
1977b842f2ecSJim Ingham               any_set = true;
19785e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19795e09c8c3SJim Ingham               s.EOL();
1980c156427dSZachary Turner               result.AppendMessage(s.GetString());
19815e09c8c3SJim Ingham             }
19825e09c8c3SJim Ingham           }
1983b842f2ecSJim Ingham           if (!any_set)
1984b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
1985b9c1b51eSKate Stone         } else {
1986b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
19875e09c8c3SJim Ingham         }
1988b842f2ecSJim Ingham       }
19895e09c8c3SJim Ingham     }
19905e09c8c3SJim Ingham     return true;
19915e09c8c3SJim Ingham   }
19925e09c8c3SJim Ingham 
19935e09c8c3SJim Ingham private:
19945e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19955e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19965e09c8c3SJim Ingham };
19975e09c8c3SJim Ingham 
1998e14dc268SJim Ingham // CommandObjectBreakpointName
1999b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20005e09c8c3SJim Ingham public:
20017428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2002b9c1b51eSKate Stone       : CommandObjectMultiword(
2003b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2004b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2005b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2006b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2007b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2008b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2009b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2010b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2011b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2012b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
20135e09c8c3SJim Ingham 
20145e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20155e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20165e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2017b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
20185e09c8c3SJim Ingham   }
20195e09c8c3SJim Ingham 
20209e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20215e09c8c3SJim Ingham };
20225e09c8c3SJim Ingham 
2023e14dc268SJim Ingham // CommandObjectBreakpointRead
20243acdf385SJim Ingham #pragma mark Read::CommandOptions
2025f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2026f94668e3SRaphael Isemann #include "CommandOptions.inc"
20271f0f5b5bSZachary Turner 
20281f0f5b5bSZachary Turner #pragma mark Read
2029e14dc268SJim Ingham 
2030e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2031e14dc268SJim Ingham public:
2032e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2033e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2034e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2035e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2036e14dc268SJim Ingham                             nullptr),
2037e14dc268SJim Ingham         m_options() {
2038e14dc268SJim Ingham     CommandArgumentEntry arg;
2039e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2040e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2041e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2042e14dc268SJim Ingham     // arguments vector.
2043e14dc268SJim Ingham     m_arguments.push_back(arg);
2044e14dc268SJim Ingham   }
2045e14dc268SJim Ingham 
2046e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2047e14dc268SJim Ingham 
2048e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2049e14dc268SJim Ingham 
2050e14dc268SJim Ingham   class CommandOptions : public Options {
2051e14dc268SJim Ingham   public:
2052e14dc268SJim Ingham     CommandOptions() : Options() {}
2053e14dc268SJim Ingham 
2054e14dc268SJim Ingham     ~CommandOptions() override = default;
2055e14dc268SJim Ingham 
205697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2057e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
205897206d57SZachary Turner       Status error;
2059e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2060e14dc268SJim Ingham 
2061e14dc268SJim Ingham       switch (short_option) {
2062e14dc268SJim Ingham       case 'f':
2063adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2064e14dc268SJim Ingham         break;
20653acdf385SJim Ingham       case 'N': {
206697206d57SZachary Turner         Status name_error;
20673acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20683acdf385SJim Ingham                                                   name_error)) {
20693acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20703acdf385SJim Ingham                                          name_error.AsCString());
20713acdf385SJim Ingham         }
2072adcd0268SBenjamin Kramer         m_names.push_back(std::string(option_arg));
20733acdf385SJim Ingham         break;
20743acdf385SJim Ingham       }
2075e14dc268SJim Ingham       default:
207636162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2077e14dc268SJim Ingham       }
2078e14dc268SJim Ingham 
2079e14dc268SJim Ingham       return error;
2080e14dc268SJim Ingham     }
2081e14dc268SJim Ingham 
2082e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2083e14dc268SJim Ingham       m_filename.clear();
20843acdf385SJim Ingham       m_names.clear();
2085e14dc268SJim Ingham     }
2086e14dc268SJim Ingham 
20871f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
208870602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
20891f0f5b5bSZachary Turner     }
2090e14dc268SJim Ingham 
2091e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2092e14dc268SJim Ingham 
2093e14dc268SJim Ingham     std::string m_filename;
20943acdf385SJim Ingham     std::vector<std::string> m_names;
2095e14dc268SJim Ingham   };
2096e14dc268SJim Ingham 
2097e14dc268SJim Ingham protected:
2098e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2099cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2100e14dc268SJim Ingham 
21013acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2102cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
21033acdf385SJim Ingham 
21048f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
21058f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
210601f16664SJim Ingham     BreakpointIDList new_bps;
2107cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2108cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2109e14dc268SJim Ingham 
2110e14dc268SJim Ingham     if (!error.Success()) {
211101f16664SJim Ingham       result.AppendError(error.AsCString());
2112e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
211301f16664SJim Ingham       return false;
2114e14dc268SJim Ingham     }
21153acdf385SJim Ingham 
21163acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
21173acdf385SJim Ingham 
21183acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
21193acdf385SJim Ingham     if (num_breakpoints == 0) {
21203acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
21213acdf385SJim Ingham     } else {
21223acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
21233acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
21243acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
21253acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2126cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
21273acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
21283acdf385SJim Ingham                              .get();
21293acdf385SJim Ingham         if (bp)
21303acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
21313acdf385SJim Ingham                              false);
21323acdf385SJim Ingham       }
21333acdf385SJim Ingham     }
2134e14dc268SJim Ingham     return result.Succeeded();
2135e14dc268SJim Ingham   }
2136e14dc268SJim Ingham 
2137e14dc268SJim Ingham private:
2138e14dc268SJim Ingham   CommandOptions m_options;
2139e14dc268SJim Ingham };
2140e14dc268SJim Ingham 
2141e14dc268SJim Ingham // CommandObjectBreakpointWrite
21421f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2143f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2144f94668e3SRaphael Isemann #include "CommandOptions.inc"
21451f0f5b5bSZachary Turner 
21461f0f5b5bSZachary Turner #pragma mark Write
2147e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2148e14dc268SJim Ingham public:
2149e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2150e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2151e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2152e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2153e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2154e14dc268SJim Ingham                             nullptr),
2155e14dc268SJim Ingham         m_options() {
2156e14dc268SJim Ingham     CommandArgumentEntry arg;
2157e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2158e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2159e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2160e14dc268SJim Ingham     // arguments vector.
2161e14dc268SJim Ingham     m_arguments.push_back(arg);
2162e14dc268SJim Ingham   }
2163e14dc268SJim Ingham 
2164e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2165e14dc268SJim Ingham 
2166*e87362e6SGongyu Deng   void
2167*e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
2168*e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
2169*e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
2170*e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2171*e87362e6SGongyu Deng         request, nullptr);
2172*e87362e6SGongyu Deng   }
2173*e87362e6SGongyu Deng 
2174e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2175e14dc268SJim Ingham 
2176e14dc268SJim Ingham   class CommandOptions : public Options {
2177e14dc268SJim Ingham   public:
2178e14dc268SJim Ingham     CommandOptions() : Options() {}
2179e14dc268SJim Ingham 
2180e14dc268SJim Ingham     ~CommandOptions() override = default;
2181e14dc268SJim Ingham 
218297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2183e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
218497206d57SZachary Turner       Status error;
2185e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2186e14dc268SJim Ingham 
2187e14dc268SJim Ingham       switch (short_option) {
2188e14dc268SJim Ingham       case 'f':
2189adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2190e14dc268SJim Ingham         break;
21912d3628e1SJim Ingham       case 'a':
21922d3628e1SJim Ingham         m_append = true;
21932d3628e1SJim Ingham         break;
2194e14dc268SJim Ingham       default:
219536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2196e14dc268SJim Ingham       }
2197e14dc268SJim Ingham 
2198e14dc268SJim Ingham       return error;
2199e14dc268SJim Ingham     }
2200e14dc268SJim Ingham 
2201e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2202e14dc268SJim Ingham       m_filename.clear();
22032d3628e1SJim Ingham       m_append = false;
2204e14dc268SJim Ingham     }
2205e14dc268SJim Ingham 
22061f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
220770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
22081f0f5b5bSZachary Turner     }
2209e14dc268SJim Ingham 
2210e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2211e14dc268SJim Ingham 
2212e14dc268SJim Ingham     std::string m_filename;
22132d3628e1SJim Ingham     bool m_append = false;
2214e14dc268SJim Ingham   };
2215e14dc268SJim Ingham 
2216e14dc268SJim Ingham protected:
2217e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2218cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2219e14dc268SJim Ingham 
2220e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2221cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2222e14dc268SJim Ingham 
2223e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
222411eb9c64SZachary Turner     if (!command.empty()) {
2225e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2226cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2227b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2228e14dc268SJim Ingham 
222901f16664SJim Ingham       if (!result.Succeeded()) {
2230e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2231e14dc268SJim Ingham         return false;
2232e14dc268SJim Ingham       }
2233e14dc268SJim Ingham     }
22348f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
22358f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2236cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
22378f3be7a3SJonas Devlieghere                                                      m_options.m_append);
223801f16664SJim Ingham     if (!error.Success()) {
223901f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
224001f16664SJim Ingham                                    error.AsCString());
224101f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2242e14dc268SJim Ingham     }
2243e14dc268SJim Ingham     return result.Succeeded();
2244e14dc268SJim Ingham   }
2245e14dc268SJim Ingham 
2246e14dc268SJim Ingham private:
2247e14dc268SJim Ingham   CommandOptions m_options;
2248e14dc268SJim Ingham };
2249e14dc268SJim Ingham 
225030fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2251ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
225230fdc8d8SChris Lattner 
2253b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2254b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2255b9c1b51eSKate Stone     : CommandObjectMultiword(
2256b9c1b51eSKate Stone           interpreter, "breakpoint",
22577428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2258b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2259b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2260b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2261b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2262b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2263b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2264b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2265b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2266b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2267b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2268b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2269b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2270b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2271b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2272b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2273b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2274b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2275b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2276b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2277e14dc268SJim Ingham   CommandObjectSP write_command_object(
2278e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2279e14dc268SJim Ingham   CommandObjectSP read_command_object(
2280e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
228130fdc8d8SChris Lattner 
2282b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
228330fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
228430fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2285b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2286b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2287ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2288b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2289b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
22905e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2291e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2292e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
229330fdc8d8SChris Lattner 
229423f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
229523f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
229623f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
229723f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
229823f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
229923f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
230023f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
230123f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
23025e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2303e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2304e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
230530fdc8d8SChris Lattner }
230630fdc8d8SChris Lattner 
23079e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
230830fdc8d8SChris Lattner 
2309a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2310a925974bSAdrian Prantl     Args &args, Target *target, bool allow_locations,
2311a925974bSAdrian Prantl     CommandReturnObject &result, BreakpointIDList *valid_ids,
2312a925974bSAdrian Prantl     BreakpointName::Permissions ::PermissionKinds purpose) {
231330fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2314b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2315b9c1b51eSKate Stone   //                                  canonical representation
2316b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2317b9c1b51eSKate Stone   //                                  representing a range (in which case there
2318b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2319b9c1b51eSKate Stone   //                                      after of one of the first two types.
23205e09c8c3SJim Ingham   //                                  4). A breakpoint name
2321b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2322b9c1b51eSKate Stone   // one.)
232330fdc8d8SChris Lattner 
232430fdc8d8SChris Lattner   Args temp_args;
232530fdc8d8SChris Lattner 
232611eb9c64SZachary Turner   if (args.empty()) {
2327b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2328b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2329b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
233036f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2331b9c1b51eSKate Stone     } else {
2332b9c1b51eSKate Stone       result.AppendError(
2333b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
233436f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
233536f3b369SJim Ingham     }
233636f3b369SJim Ingham     return;
233736f3b369SJim Ingham   }
233836f3b369SJim Ingham 
2339b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
234005097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
234105097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
234205097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
234305097246SAdrian Prantl   // into TEMP_ARGS.
234430fdc8d8SChris Lattner 
2345b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2346b842f2ecSJim Ingham                                            purpose, result, temp_args);
234730fdc8d8SChris Lattner 
2348b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2349b9c1b51eSKate Stone   // BreakpointIDList:
235030fdc8d8SChris Lattner 
235116662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
235230fdc8d8SChris Lattner 
235305097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
235405097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
235530fdc8d8SChris Lattner 
2356b9c1b51eSKate Stone   if (result.Succeeded()) {
2357b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
235805097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
235905097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
236030fdc8d8SChris Lattner 
2361c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2362b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
236330fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2364b9c1b51eSKate Stone       Breakpoint *breakpoint =
2365b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2366b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2367c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2368b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
236930fdc8d8SChris Lattner           StreamString id_str;
2370b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2371b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2372c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2373b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2374b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
237530fdc8d8SChris Lattner               id_str.GetData());
237630fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
237730fdc8d8SChris Lattner         }
2378b9c1b51eSKate Stone       } else {
2379c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2380b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2381b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
23827428a18cSKate Stone             cur_bp_id.GetBreakpointID());
238330fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
238430fdc8d8SChris Lattner       }
238530fdc8d8SChris Lattner     }
238630fdc8d8SChris Lattner   }
238730fdc8d8SChris Lattner }
2388