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"
20bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h"
215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
23b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
240e0984eeSJim Ingham #include "lldb/Target/Language.h"
25b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
26b9c1b51eSKate Stone #include "lldb/Target/Target.h"
271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3030fdc8d8SChris Lattner 
31796ac80bSJonas Devlieghere #include <memory>
32796ac80bSJonas Devlieghere #include <vector>
33796ac80bSJonas Devlieghere 
3430fdc8d8SChris Lattner using namespace lldb;
3530fdc8d8SChris Lattner using namespace lldb_private;
3630fdc8d8SChris Lattner 
37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
3930fdc8d8SChris Lattner   s->IndentMore();
4030fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4130fdc8d8SChris Lattner   s->IndentLess();
4230fdc8d8SChris Lattner   s->EOL();
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
45b842f2ecSJim Ingham // Modifiable Breakpoint Options
46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
47f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
48f94668e3SRaphael Isemann #include "CommandOptions.inc"
49bd68a052SRaphael Isemann 
50a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup {
51b842f2ecSJim Ingham public:
52a925974bSAdrian Prantl   BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
53b842f2ecSJim Ingham 
54b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
55b842f2ecSJim Ingham 
56b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
57b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
58b842f2ecSJim Ingham   }
59b842f2ecSJim Ingham 
60b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
61b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
62b842f2ecSJim Ingham     Status error;
63a925974bSAdrian Prantl     const int short_option =
64a925974bSAdrian Prantl         g_breakpoint_modify_options[option_idx].short_option;
65b842f2ecSJim Ingham 
66b842f2ecSJim Ingham     switch (short_option) {
67b842f2ecSJim Ingham     case 'c':
6805097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
6905097246SAdrian Prantl       // to say it was passed in.
70b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
71b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
72b842f2ecSJim Ingham       break;
73b842f2ecSJim Ingham     case 'C':
74adcd0268SBenjamin Kramer       m_commands.push_back(std::string(option_arg));
75b842f2ecSJim Ingham       break;
76b842f2ecSJim Ingham     case 'd':
77b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
78b842f2ecSJim Ingham       break;
79b842f2ecSJim Ingham     case 'e':
80b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
81b842f2ecSJim Ingham       break;
82b842f2ecSJim Ingham     case 'G': {
83b842f2ecSJim Ingham       bool value, success;
8447cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
85b842f2ecSJim Ingham       if (success) {
86b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
87b842f2ecSJim Ingham       } else
88b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
89b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
90b842f2ecSJim Ingham             option_arg.str().c_str());
91a925974bSAdrian Prantl     } break;
92a925974bSAdrian Prantl     case 'i': {
93b842f2ecSJim Ingham       uint32_t ignore_count;
94b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
95b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
96b842f2ecSJim Ingham                                        option_arg.str().c_str());
97b842f2ecSJim Ingham       else
98b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
99a925974bSAdrian Prantl     } break;
100b842f2ecSJim Ingham     case 'o': {
101b842f2ecSJim Ingham       bool value, success;
10247cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
103b842f2ecSJim Ingham       if (success) {
104b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
105b842f2ecSJim Ingham       } else
106b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
107b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
108b842f2ecSJim Ingham             option_arg.str().c_str());
109b842f2ecSJim Ingham     } break;
110a925974bSAdrian Prantl     case 't': {
111b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
112b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
113b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
114b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
115b842f2ecSJim Ingham                                          option_arg.str().c_str());
116b842f2ecSJim Ingham       }
117b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
118a925974bSAdrian Prantl     } break;
119b842f2ecSJim Ingham     case 'T':
120b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
121b842f2ecSJim Ingham       break;
122b842f2ecSJim Ingham     case 'q':
123b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
124b842f2ecSJim Ingham       break;
125a925974bSAdrian Prantl     case 'x': {
126b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
127b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
128b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
129b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
130b842f2ecSJim Ingham                                          option_arg.str().c_str());
131b842f2ecSJim Ingham       }
132b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
133a925974bSAdrian Prantl     } break;
134b842f2ecSJim Ingham     default:
13536162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
136b842f2ecSJim Ingham     }
137b842f2ecSJim Ingham 
138b842f2ecSJim Ingham     return error;
139b842f2ecSJim Ingham   }
140b842f2ecSJim Ingham 
141b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
142b842f2ecSJim Ingham     m_bp_opts.Clear();
143b842f2ecSJim Ingham     m_commands.clear();
144b842f2ecSJim Ingham   }
145b842f2ecSJim Ingham 
146b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
147a925974bSAdrian Prantl     if (!m_commands.empty()) {
148a8f3ae7cSJonas Devlieghere       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
149b842f2ecSJim Ingham 
150b842f2ecSJim Ingham       for (std::string &str : m_commands)
151b842f2ecSJim Ingham         cmd_data->user_source.AppendString(str);
152b842f2ecSJim Ingham 
153b842f2ecSJim Ingham       cmd_data->stop_on_error = true;
154b842f2ecSJim Ingham       m_bp_opts.SetCommandDataCallback(cmd_data);
155b842f2ecSJim Ingham     }
156b842f2ecSJim Ingham     return Status();
157b842f2ecSJim Ingham   }
158b842f2ecSJim Ingham 
159a925974bSAdrian Prantl   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
160b842f2ecSJim Ingham 
161b842f2ecSJim Ingham   std::vector<std::string> m_commands;
162b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
163b842f2ecSJim Ingham };
164bd68a052SRaphael Isemann 
165f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
166f94668e3SRaphael Isemann #include "CommandOptions.inc"
167b842f2ecSJim Ingham 
168a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
169b842f2ecSJim Ingham public:
170a925974bSAdrian Prantl   BreakpointDummyOptionGroup() : OptionGroup() {}
171b842f2ecSJim Ingham 
172b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
173b842f2ecSJim Ingham 
174b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
175b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
176b842f2ecSJim Ingham   }
177b842f2ecSJim Ingham 
178b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
179b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
180b842f2ecSJim Ingham     Status error;
181a925974bSAdrian Prantl     const int short_option =
182f1539b9dSJim Ingham         g_breakpoint_dummy_options[option_idx].short_option;
183b842f2ecSJim Ingham 
184b842f2ecSJim Ingham     switch (short_option) {
185b842f2ecSJim Ingham     case 'D':
186b842f2ecSJim Ingham       m_use_dummy = true;
187b842f2ecSJim Ingham       break;
188b842f2ecSJim Ingham     default:
18936162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
190b842f2ecSJim Ingham     }
191b842f2ecSJim Ingham 
192b842f2ecSJim Ingham     return error;
193b842f2ecSJim Ingham   }
194b842f2ecSJim Ingham 
195b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
196b842f2ecSJim Ingham     m_use_dummy = false;
197b842f2ecSJim Ingham   }
198b842f2ecSJim Ingham 
199b842f2ecSJim Ingham   bool m_use_dummy;
200b842f2ecSJim Ingham };
201b842f2ecSJim Ingham 
202f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
203f94668e3SRaphael Isemann #include "CommandOptions.inc"
2041f0f5b5bSZachary Turner 
2055a988416SJim Ingham // CommandObjectBreakpointSet
20630fdc8d8SChris Lattner 
207b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2085a988416SJim Ingham public:
209efe8e7e3SFangrui Song   enum BreakpointSetType {
2105a988416SJim Ingham     eSetTypeInvalid,
2115a988416SJim Ingham     eSetTypeFileAndLine,
2125a988416SJim Ingham     eSetTypeAddress,
2135a988416SJim Ingham     eSetTypeFunctionName,
2145a988416SJim Ingham     eSetTypeFunctionRegexp,
2155a988416SJim Ingham     eSetTypeSourceRegexp,
2163815e702SJim Ingham     eSetTypeException,
2173815e702SJim Ingham     eSetTypeScripted,
218efe8e7e3SFangrui Song   };
2195a988416SJim Ingham 
220b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
221b9c1b51eSKate Stone       : CommandObjectParsed(
222b9c1b51eSKate Stone             interpreter, "breakpoint set",
2235a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2245a988416SJim Ingham             "breakpoint set <cmd-options>"),
225738af7a6SJim Ingham         m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
226f6a2086dSSam McCall         m_options() {
227b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
228a925974bSAdrian Prantl     m_all_options.Append(&m_python_class_options,
229a925974bSAdrian Prantl                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
230b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
231b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
232b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
233f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
234b842f2ecSJim Ingham     m_all_options.Append(&m_options);
235b842f2ecSJim Ingham     m_all_options.Finalize();
236b842f2ecSJim Ingham   }
2375a988416SJim Ingham 
2389e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2395a988416SJim Ingham 
240b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2415a988416SJim Ingham 
242b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2435a988416SJim Ingham   public:
244b9c1b51eSKate Stone     CommandOptions()
245a925974bSAdrian Prantl         : OptionGroup(), m_condition(), m_filenames(), m_line_num(0),
246a925974bSAdrian Prantl           m_column(0), m_func_names(),
247a925974bSAdrian Prantl           m_func_name_type_mask(eFunctionNameTypeNone), m_func_regexp(),
248a925974bSAdrian Prantl           m_source_text_regexp(), m_modules(), m_load_addr(), m_catch_bp(false),
249a925974bSAdrian Prantl           m_throw_bp(true), m_hardware(false),
250a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
25123b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
252a925974bSAdrian Prantl           m_skip_prologue(eLazyBoolCalculate), m_all_files(false),
253a925974bSAdrian Prantl           m_move_to_nearest_code(eLazyBoolCalculate) {}
25430fdc8d8SChris Lattner 
2559e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
25687df91b8SJim Ingham 
25797206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
258b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
25997206d57SZachary Turner       Status error;
260a925974bSAdrian Prantl       const int short_option =
261a925974bSAdrian Prantl           g_breakpoint_set_options[option_idx].short_option;
26230fdc8d8SChris Lattner 
263b9c1b51eSKate Stone       switch (short_option) {
264b9c1b51eSKate Stone       case 'a': {
26547cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
266e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
267b9c1b51eSKate Stone       } break;
26830fdc8d8SChris Lattner 
269e732052fSJim Ingham       case 'A':
270e732052fSJim Ingham         m_all_files = true;
271e732052fSJim Ingham         break;
272e732052fSJim Ingham 
273ca36cd16SJim Ingham       case 'b':
274adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
275ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
276ca36cd16SJim Ingham         break;
277ca36cd16SJim Ingham 
2786672a4f5SJonas Devlieghere       case 'u':
279fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
280b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
281fe11483bSZachary Turner                                          option_arg.str().c_str());
28230fdc8d8SChris Lattner         break;
2839e85e5a8SEugene Zelenko 
284b9c1b51eSKate Stone       case 'E': {
285fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
286fab10e89SJim Ingham 
287b9c1b51eSKate Stone         switch (language) {
288fab10e89SJim Ingham         case eLanguageTypeC89:
289fab10e89SJim Ingham         case eLanguageTypeC:
290fab10e89SJim Ingham         case eLanguageTypeC99:
2911d0089faSBruce Mitchener         case eLanguageTypeC11:
292a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
293fab10e89SJim Ingham           break;
294fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2951d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2961d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
2972ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
298a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
299fab10e89SJim Ingham           break;
300fab10e89SJim Ingham         case eLanguageTypeObjC:
301a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
302fab10e89SJim Ingham           break;
303fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
304b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
305b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
306fab10e89SJim Ingham           break;
307fab10e89SJim Ingham         case eLanguageTypeUnknown:
308b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
309b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
310fe11483bSZachary Turner               option_arg.str().c_str());
311fab10e89SJim Ingham           break;
312fab10e89SJim Ingham         default:
313b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
314b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
315fe11483bSZachary Turner               option_arg.str().c_str());
316fab10e89SJim Ingham         }
317b9c1b51eSKate Stone       } break;
318ca36cd16SJim Ingham 
319ca36cd16SJim Ingham       case 'f':
3208f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
321fab10e89SJim Ingham         break;
322ca36cd16SJim Ingham 
323ca36cd16SJim Ingham       case 'F':
324adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
325ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
326ca36cd16SJim Ingham         break;
327ca36cd16SJim Ingham 
328b9c1b51eSKate Stone       case 'h': {
329fab10e89SJim Ingham         bool success;
33047cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
331fab10e89SJim Ingham         if (!success)
332b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
333fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
334fe11483bSZachary Turner               option_arg.str().c_str());
335b9c1b51eSKate Stone       } break;
336eb023e75SGreg Clayton 
337eb023e75SGreg Clayton       case 'H':
338eb023e75SGreg Clayton         m_hardware = true;
339eb023e75SGreg Clayton         break;
340eb023e75SGreg Clayton 
341b9c1b51eSKate Stone       case 'K': {
342a8558b62SJim Ingham         bool success;
343a8558b62SJim Ingham         bool value;
34447cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
345a8558b62SJim Ingham         if (value)
346a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
347a8558b62SJim Ingham         else
348a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
349a8558b62SJim Ingham 
350a8558b62SJim Ingham         if (!success)
351b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
352b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
353fe11483bSZachary Turner               option_arg.str().c_str());
354b9c1b51eSKate Stone       } break;
355ca36cd16SJim Ingham 
356fe11483bSZachary Turner       case 'l':
357fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
358b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
359fe11483bSZachary Turner                                          option_arg.str().c_str());
360ca36cd16SJim Ingham         break;
361055ad9beSIlia K 
36223b1decbSDawn Perchik       case 'L':
363fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
36423b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
365b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
366fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
367fe11483bSZachary Turner               option_arg.str().c_str());
36823b1decbSDawn Perchik         break;
36923b1decbSDawn Perchik 
370b9c1b51eSKate Stone       case 'm': {
371055ad9beSIlia K         bool success;
372055ad9beSIlia K         bool value;
37347cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
374055ad9beSIlia K         if (value)
375055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
376055ad9beSIlia K         else
377055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
378055ad9beSIlia K 
379055ad9beSIlia K         if (!success)
380b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
381b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
382fe11483bSZachary Turner               option_arg.str().c_str());
383055ad9beSIlia K         break;
384055ad9beSIlia K       }
385055ad9beSIlia K 
386ca36cd16SJim Ingham       case 'M':
387adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
388ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
389ca36cd16SJim Ingham         break;
390ca36cd16SJim Ingham 
391ca36cd16SJim Ingham       case 'n':
392adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
393ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
394ca36cd16SJim Ingham         break;
395ca36cd16SJim Ingham 
3966fa7681bSZachary Turner       case 'N': {
397fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
398adcd0268SBenjamin Kramer           m_breakpoint_names.push_back(std::string(option_arg));
399ff9a91eaSJim Ingham         else
400ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
401fe11483bSZachary Turner                                          option_arg.str().c_str());
4025e09c8c3SJim Ingham         break;
4036fa7681bSZachary Turner       }
4045e09c8c3SJim Ingham 
405b9c1b51eSKate Stone       case 'R': {
4062411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
40747cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
40847cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4092411167fSJim Ingham         if (error.Success())
4102411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
411b9c1b51eSKate Stone       } break;
4122411167fSJim Ingham 
413a72b31c7SJim Ingham       case 'O':
414fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
415fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
416a72b31c7SJim Ingham         break;
417a72b31c7SJim Ingham 
418ca36cd16SJim Ingham       case 'p':
419adcd0268SBenjamin Kramer         m_source_text_regexp.assign(std::string(option_arg));
420ca36cd16SJim Ingham         break;
421ca36cd16SJim Ingham 
422ca36cd16SJim Ingham       case 'r':
423adcd0268SBenjamin Kramer         m_func_regexp.assign(std::string(option_arg));
424ca36cd16SJim Ingham         break;
425ca36cd16SJim Ingham 
426ca36cd16SJim Ingham       case 's':
4278f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
428ca36cd16SJim Ingham         break;
429ca36cd16SJim Ingham 
430ca36cd16SJim Ingham       case 'S':
431adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
432ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
433ca36cd16SJim Ingham         break;
434ca36cd16SJim Ingham 
435b9c1b51eSKate Stone       case 'w': {
436ca36cd16SJim Ingham         bool success;
43747cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
438ca36cd16SJim Ingham         if (!success)
439b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
440fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
441fe11483bSZachary Turner               option_arg.str().c_str());
442b9c1b51eSKate Stone       } break;
443ca36cd16SJim Ingham 
44476bb8d67SJim Ingham       case 'X':
445adcd0268SBenjamin Kramer         m_source_regex_func_names.insert(std::string(option_arg));
44676bb8d67SJim Ingham         break;
44776bb8d67SJim Ingham 
448bc0a9a17SJim Ingham       case 'y':
449bc0a9a17SJim Ingham       {
450bc0a9a17SJim Ingham         OptionValueFileColonLine value;
451bc0a9a17SJim Ingham         Status fcl_err = value.SetValueFromString(option_arg);
452bc0a9a17SJim Ingham         if (!fcl_err.Success()) {
453bc0a9a17SJim Ingham           error.SetErrorStringWithFormat(
454bc0a9a17SJim Ingham               "Invalid value for file:line specifier: %s",
455bc0a9a17SJim Ingham               fcl_err.AsCString());
456bc0a9a17SJim Ingham         } else {
457bc0a9a17SJim Ingham           m_filenames.AppendIfUnique(value.GetFileSpec());
458bc0a9a17SJim Ingham           m_line_num = value.GetLineNumber();
459bc0a9a17SJim Ingham           m_column = value.GetColumnNumber();
460bc0a9a17SJim Ingham         }
461bc0a9a17SJim Ingham       } break;
462bc0a9a17SJim Ingham 
46330fdc8d8SChris Lattner       default:
46436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
46530fdc8d8SChris Lattner       }
46630fdc8d8SChris Lattner 
46730fdc8d8SChris Lattner       return error;
46830fdc8d8SChris Lattner     }
4699e85e5a8SEugene Zelenko 
470b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
47187df91b8SJim Ingham       m_filenames.Clear();
47230fdc8d8SChris Lattner       m_line_num = 0;
47330fdc8d8SChris Lattner       m_column = 0;
474fab10e89SJim Ingham       m_func_names.clear();
4751f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
47630fdc8d8SChris Lattner       m_func_regexp.clear();
4771f746071SGreg Clayton       m_source_text_regexp.clear();
47887df91b8SJim Ingham       m_modules.Clear();
4791f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4802411167fSJim Ingham       m_offset_addr = 0;
481fab10e89SJim Ingham       m_catch_bp = false;
482fab10e89SJim Ingham       m_throw_bp = true;
483eb023e75SGreg Clayton       m_hardware = false;
484a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
48523b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
486a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4875e09c8c3SJim Ingham       m_breakpoint_names.clear();
488e732052fSJim Ingham       m_all_files = false;
489a72b31c7SJim Ingham       m_exception_extra_args.Clear();
490055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
49176bb8d67SJim Ingham       m_source_regex_func_names.clear();
4923815e702SJim Ingham       m_current_key.clear();
49330fdc8d8SChris Lattner     }
49430fdc8d8SChris Lattner 
4951f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
49670602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
4971f0f5b5bSZachary Turner     }
49830fdc8d8SChris Lattner 
4995a988416SJim Ingham     // Instance variables to hold the values for command options.
500969795f1SJim Ingham 
5015a988416SJim Ingham     std::string m_condition;
5025a988416SJim Ingham     FileSpecList m_filenames;
5035a988416SJim Ingham     uint32_t m_line_num;
5045a988416SJim Ingham     uint32_t m_column;
5055a988416SJim Ingham     std::vector<std::string> m_func_names;
5065e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
507117b1fa1SZachary Turner     lldb::FunctionNameType m_func_name_type_mask;
5085a988416SJim Ingham     std::string m_func_regexp;
5095a988416SJim Ingham     std::string m_source_text_regexp;
5105a988416SJim Ingham     FileSpecList m_modules;
5115a988416SJim Ingham     lldb::addr_t m_load_addr;
5122411167fSJim Ingham     lldb::addr_t m_offset_addr;
5135a988416SJim Ingham     bool m_catch_bp;
5145a988416SJim Ingham     bool m_throw_bp;
515eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
516a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
51723b1decbSDawn Perchik     lldb::LanguageType m_language;
5185a988416SJim Ingham     LazyBool m_skip_prologue;
519e732052fSJim Ingham     bool m_all_files;
520a72b31c7SJim Ingham     Args m_exception_extra_args;
521055ad9beSIlia K     LazyBool m_move_to_nearest_code;
52276bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5233815e702SJim Ingham     std::string m_current_key;
5245a988416SJim Ingham   };
5255a988416SJim Ingham 
5265a988416SJim Ingham protected:
527b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
528cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
52930fdc8d8SChris Lattner 
53030fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
53130fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
53230fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
53330fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
534b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
535b9c1b51eSKate Stone     //   expression)
536b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
537b9c1b51eSKate Stone     //   to source text)
538b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
539b9c1b51eSKate Stone     //   given language.)
54030fdc8d8SChris Lattner 
54130fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
54230fdc8d8SChris Lattner 
543738af7a6SJim Ingham     if (!m_python_class_options.GetName().empty())
5443815e702SJim Ingham       break_type = eSetTypeScripted;
5453815e702SJim Ingham     else if (m_options.m_line_num != 0)
54630fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
54730fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
54830fdc8d8SChris Lattner       break_type = eSetTypeAddress;
549fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
55030fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
55130fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
55230fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
553969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
554969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
555a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
556fab10e89SJim Ingham       break_type = eSetTypeException;
55730fdc8d8SChris Lattner 
558b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
559274060b6SGreg Clayton     FileSpec module_spec;
560a8558b62SJim Ingham     const bool internal = false;
561a8558b62SJim Ingham 
562b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
563b9c1b51eSKate Stone     // that off.
564b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
565b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5662411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5672411167fSJim Ingham 
568b9c1b51eSKate Stone     switch (break_type) {
56930fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
57030fdc8d8SChris Lattner     {
57130fdc8d8SChris Lattner       FileSpec file;
572c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
573b9c1b51eSKate Stone       if (num_files == 0) {
574b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
57587df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
57687df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
57787df91b8SJim Ingham           return false;
57887df91b8SJim Ingham         }
579b9c1b51eSKate Stone       } else if (num_files > 1) {
580b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
581b9c1b51eSKate Stone                            "line breakpoints.");
58287df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
58387df91b8SJim Ingham         return false;
584b9c1b51eSKate Stone       } else
58587df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
58630fdc8d8SChris Lattner 
5871f746071SGreg Clayton       // Only check for inline functions if
5881f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5891f746071SGreg Clayton 
590cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
591cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
592cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
593cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
594b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
595b9c1b51eSKate Stone     } break;
5966eee5aa0SGreg Clayton 
59730fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
598055a08a4SJim Ingham     {
599b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
600b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
601b842f2ecSJim Ingham       //  will track the load location of the library.
602055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
603b9c1b51eSKate Stone       if (num_modules_specified == 1) {
604b9c1b51eSKate Stone         const FileSpec *file_spec =
605b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
606cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
607cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
608b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
609cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
610b842f2ecSJim Ingham                                         m_options.m_hardware);
611b9c1b51eSKate Stone       } else {
612b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
613b9c1b51eSKate Stone                            "address breakpoints.");
614055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
615055a08a4SJim Ingham         return false;
616055a08a4SJim Ingham       }
61730fdc8d8SChris Lattner       break;
618055a08a4SJim Ingham     }
61930fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6200c5cd90dSGreg Clayton     {
621117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6220c5cd90dSGreg Clayton 
6230c5cd90dSGreg Clayton       if (name_type_mask == 0)
624e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6250c5cd90dSGreg Clayton 
626cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
627cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
628cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
629cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
630b842f2ecSJim Ingham           m_options.m_hardware);
631b9c1b51eSKate Stone     } break;
6320c5cd90dSGreg Clayton 
633b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
634b9c1b51eSKate Stone                                  // name
63530fdc8d8SChris Lattner     {
63695eae423SZachary Turner       RegularExpression regexp(m_options.m_func_regexp);
6373af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
638b9c1b51eSKate Stone         result.AppendErrorWithFormat(
639b58af8d2SRaphael Isemann             "Function name regular expression could not be compiled: %s",
6403af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
641aaf68cd9SRaphael Isemann         // Check if the incorrect regex looks like a globbing expression and
642aaf68cd9SRaphael Isemann         // warn the user about it.
643aaf68cd9SRaphael Isemann         if (!m_options.m_func_regexp.empty()) {
644aaf68cd9SRaphael Isemann           if (m_options.m_func_regexp[0] == '*' ||
645aaf68cd9SRaphael Isemann               m_options.m_func_regexp[0] == '?')
646aaf68cd9SRaphael Isemann             result.AppendWarning(
647aaf68cd9SRaphael Isemann                 "Function name regex does not accept glob patterns.");
648aaf68cd9SRaphael Isemann         }
64930fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
650969795f1SJim Ingham         return false;
65130fdc8d8SChris Lattner       }
65287df91b8SJim Ingham 
653cb2380c9SRaphael Isemann       bp_sp = target.CreateFuncRegexBreakpoint(
6545aa1d819SJan Kratochvil           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
655cb2380c9SRaphael Isemann           m_options.m_language, m_options.m_skip_prologue, internal,
656b842f2ecSJim Ingham           m_options.m_hardware);
657a925974bSAdrian Prantl     } break;
658969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
659969795f1SJim Ingham     {
660c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
66187df91b8SJim Ingham 
662b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
663969795f1SJim Ingham         FileSpec file;
664b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
665b9c1b51eSKate Stone           result.AppendError(
666b9c1b51eSKate Stone               "No files provided and could not find default file.");
66787df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
66887df91b8SJim Ingham           return false;
669b9c1b51eSKate Stone         } else {
67087df91b8SJim Ingham           m_options.m_filenames.Append(file);
67187df91b8SJim Ingham         }
67287df91b8SJim Ingham       }
6730c5cd90dSGreg Clayton 
67495eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6753af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
676b9c1b51eSKate Stone         result.AppendErrorWithFormat(
677b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6783af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
679969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
680969795f1SJim Ingham         return false;
681969795f1SJim Ingham       }
682cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
683cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6845aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
685cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
686b9c1b51eSKate Stone     } break;
687b9c1b51eSKate Stone     case eSetTypeException: {
68897206d57SZachary Turner       Status precond_error;
689cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
690cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
691cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
692b842f2ecSJim Ingham           &precond_error);
693b9c1b51eSKate Stone       if (precond_error.Fail()) {
694b9c1b51eSKate Stone         result.AppendErrorWithFormat(
695b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
696a72b31c7SJim Ingham             precond_error.AsCString());
697cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
698a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
699a72b31c7SJim Ingham         return false;
700a72b31c7SJim Ingham       }
701b9c1b51eSKate Stone     } break;
7023815e702SJim Ingham     case eSetTypeScripted: {
7033815e702SJim Ingham 
7043815e702SJim Ingham       Status error;
705cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
706738af7a6SJim Ingham           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
707cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
708943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
7093815e702SJim Ingham       if (error.Fail()) {
7103815e702SJim Ingham         result.AppendErrorWithFormat(
711a925974bSAdrian Prantl             "Error setting extra exception arguments: %s", error.AsCString());
712cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7133815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
7143815e702SJim Ingham         return false;
7153815e702SJim Ingham       }
7163815e702SJim Ingham     } break;
71730fdc8d8SChris Lattner     default:
71830fdc8d8SChris Lattner       break;
71930fdc8d8SChris Lattner     }
72030fdc8d8SChris Lattner 
7211b54c88cSJim Ingham     // Now set the various options that were passed in:
722b842f2ecSJim Ingham     if (bp_sp) {
723b842f2ecSJim Ingham       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
724ca36cd16SJim Ingham 
725b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
72697206d57SZachary Turner         Status name_error;
727ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
728cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
729ff9a91eaSJim Ingham           if (name_error.Fail()) {
730ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
731ff9a91eaSJim Ingham                                          name.c_str());
732cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
733ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
734ff9a91eaSJim Ingham             return false;
735ff9a91eaSJim Ingham           }
736ff9a91eaSJim Ingham         }
7375e09c8c3SJim Ingham       }
7381b54c88cSJim Ingham     }
7391b54c88cSJim Ingham 
740b842f2ecSJim Ingham     if (bp_sp) {
74185e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7421391cc7dSJim Ingham       const bool show_locations = false;
743b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
744b9c1b51eSKate Stone                             show_locations);
745cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
746b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
747b9c1b51eSKate Stone                              "into future targets.\n");
748b9c1b51eSKate Stone       else {
74905097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
75005097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
75105097246SAdrian Prantl         // set the breakpoint till we run.
752b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
753b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
754b9c1b51eSKate Stone                                "actual locations.\n");
7554aeb1989SJim Ingham         }
7564aeb1989SJim Ingham       }
75730fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
758b842f2ecSJim Ingham     } else if (!bp_sp) {
75930fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
76030fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
76130fdc8d8SChris Lattner     }
76230fdc8d8SChris Lattner 
76330fdc8d8SChris Lattner     return result.Succeeded();
76430fdc8d8SChris Lattner   }
76530fdc8d8SChris Lattner 
7665a988416SJim Ingham private:
767cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
768b9c1b51eSKate Stone                       CommandReturnObject &result) {
7695a988416SJim Ingham     uint32_t default_line;
77005097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
77105097246SAdrian Prantl     // frame's file.
772cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
773b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
774b9c1b51eSKate Stone       if (cur_frame == nullptr) {
775b9c1b51eSKate Stone         result.AppendError(
776b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7775a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7785a988416SJim Ingham         return false;
779b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
780b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
781b9c1b51eSKate Stone                            "file, it has no debug info.");
7825a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7835a988416SJim Ingham         return false;
784b9c1b51eSKate Stone       } else {
785b9c1b51eSKate Stone         const SymbolContext &sc =
786b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
787b9c1b51eSKate Stone         if (sc.line_entry.file) {
7885a988416SJim Ingham           file = sc.line_entry.file;
789b9c1b51eSKate Stone         } else {
790b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
791b9c1b51eSKate Stone                              "use as the default file.");
7925a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
7935a988416SJim Ingham           return false;
7945a988416SJim Ingham         }
7955a988416SJim Ingham       }
7965a988416SJim Ingham     }
7975a988416SJim Ingham     return true;
7985a988416SJim Ingham   }
7995a988416SJim Ingham 
800b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
801b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
802943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
8035a988416SJim Ingham   CommandOptions m_options;
804b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
8055a988416SJim Ingham };
8069e85e5a8SEugene Zelenko 
8075a988416SJim Ingham // CommandObjectBreakpointModify
8085a988416SJim Ingham #pragma mark Modify
8095a988416SJim Ingham 
810b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8115a988416SJim Ingham public:
812b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
813b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
814b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
815b9c1b51eSKate Stone                             "breakpoints in the executable.  "
816b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
817b9c1b51eSKate Stone                             "created breakpoint.  "
818b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
819b9c1b51eSKate Stone                             "empty argument clears the modification.",
8209e85e5a8SEugene Zelenko                             nullptr),
821b9c1b51eSKate Stone         m_options() {
8225a988416SJim Ingham     CommandArgumentEntry arg;
823b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
824b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
825b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
826b9c1b51eSKate Stone     // arguments vector.
8275a988416SJim Ingham     m_arguments.push_back(arg);
828b842f2ecSJim Ingham 
829b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
830b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
831b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
832b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
833b842f2ecSJim Ingham     m_options.Finalize();
8345a988416SJim Ingham   }
8355a988416SJim Ingham 
8369e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8375a988416SJim Ingham 
8380e50b9a4SGongyu Deng   void
8390e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8400e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8410e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
8420e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8430e50b9a4SGongyu Deng         request, nullptr);
8440e50b9a4SGongyu Deng   }
8450e50b9a4SGongyu Deng 
846b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8475a988416SJim Ingham 
8485a988416SJim Ingham protected:
849b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
850cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8515a988416SJim Ingham 
852bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
853cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8545a988416SJim Ingham 
8555a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8565a988416SJim Ingham 
857b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
858cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
859b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8605a988416SJim Ingham 
861b9c1b51eSKate Stone     if (result.Succeeded()) {
8625a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
863b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8645a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8655a988416SJim Ingham 
866b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
867b9c1b51eSKate Stone           Breakpoint *bp =
868cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
869b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
870b9c1b51eSKate Stone             BreakpointLocation *location =
871b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
872b842f2ecSJim Ingham             if (location)
873a925974bSAdrian Prantl               location->GetLocationOptions()->CopyOverSetOptions(
874a925974bSAdrian Prantl                   m_bp_opts.GetBreakpointOptions());
875b9c1b51eSKate Stone           } else {
876a925974bSAdrian Prantl             bp->GetOptions()->CopyOverSetOptions(
877a925974bSAdrian Prantl                 m_bp_opts.GetBreakpointOptions());
8785a988416SJim Ingham           }
8795a988416SJim Ingham         }
8805a988416SJim Ingham       }
8815a988416SJim Ingham     }
8825a988416SJim Ingham 
8835a988416SJim Ingham     return result.Succeeded();
8845a988416SJim Ingham   }
8855a988416SJim Ingham 
8865a988416SJim Ingham private:
887b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
888b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
889b842f2ecSJim Ingham   OptionGroupOptions m_options;
8905a988416SJim Ingham };
8915a988416SJim Ingham 
8925a988416SJim Ingham // CommandObjectBreakpointEnable
8935a988416SJim Ingham #pragma mark Enable
8945a988416SJim Ingham 
895b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8965a988416SJim Ingham public:
897b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
898b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
899b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
900b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
901b9c1b51eSKate Stone                             nullptr) {
9025a988416SJim Ingham     CommandArgumentEntry arg;
903b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
904b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
905b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
906b9c1b51eSKate Stone     // arguments vector.
9075a988416SJim Ingham     m_arguments.push_back(arg);
9085a988416SJim Ingham   }
9095a988416SJim Ingham 
9109e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9115a988416SJim Ingham 
9120e50b9a4SGongyu Deng   void
9130e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
9140e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
9150e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
9160e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9170e50b9a4SGongyu Deng         request, nullptr);
9180e50b9a4SGongyu Deng   }
9190e50b9a4SGongyu Deng 
9205a988416SJim Ingham protected:
921b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
922cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9235a988416SJim Ingham 
924bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
925cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9265a988416SJim Ingham 
927cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9285a988416SJim Ingham 
9295a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9305a988416SJim Ingham 
931b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9325a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9335a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9345a988416SJim Ingham       return false;
9355a988416SJim Ingham     }
9365a988416SJim Ingham 
93711eb9c64SZachary Turner     if (command.empty()) {
9385a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
939cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
940b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
941b9c1b51eSKate Stone                                      " breakpoints)\n",
942b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9435a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
944b9c1b51eSKate Stone     } else {
9455a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9465a988416SJim Ingham       BreakpointIDList valid_bp_ids;
947b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
948cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
949b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9505a988416SJim Ingham 
951b9c1b51eSKate Stone       if (result.Succeeded()) {
9525a988416SJim Ingham         int enable_count = 0;
9535a988416SJim Ingham         int loc_count = 0;
9545a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
955b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9565a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9575a988416SJim Ingham 
958b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
959b9c1b51eSKate Stone             Breakpoint *breakpoint =
960cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
961b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
962b9c1b51eSKate Stone               BreakpointLocation *location =
963b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
964b9c1b51eSKate Stone               if (location) {
9655a988416SJim Ingham                 location->SetEnabled(true);
9665a988416SJim Ingham                 ++loc_count;
9675a988416SJim Ingham               }
968b9c1b51eSKate Stone             } else {
9695a988416SJim Ingham               breakpoint->SetEnabled(true);
9705a988416SJim Ingham               ++enable_count;
9715a988416SJim Ingham             }
9725a988416SJim Ingham           }
9735a988416SJim Ingham         }
974b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
975b9c1b51eSKate Stone                                        enable_count + loc_count);
9765a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9775a988416SJim Ingham       }
9785a988416SJim Ingham     }
9795a988416SJim Ingham 
9805a988416SJim Ingham     return result.Succeeded();
9815a988416SJim Ingham   }
9825a988416SJim Ingham };
9835a988416SJim Ingham 
9845a988416SJim Ingham // CommandObjectBreakpointDisable
9855a988416SJim Ingham #pragma mark Disable
9865a988416SJim Ingham 
987b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9885a988416SJim Ingham public:
9897428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
990b9c1b51eSKate Stone       : CommandObjectParsed(
991b9c1b51eSKate Stone             interpreter, "breakpoint disable",
992b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9937428a18cSKate Stone             "them.  If none are specified, disable all "
9947428a18cSKate Stone             "breakpoints.",
995b9c1b51eSKate Stone             nullptr) {
996b9c1b51eSKate Stone     SetHelpLong(
997b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9987428a18cSKate Stone If none are specified, disable all breakpoints."
9997428a18cSKate Stone         R"(
1000ea671fbdSKate Stone 
10017428a18cSKate Stone )"
10027428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
10037428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
10047428a18cSKate Stone         R"(
1005ea671fbdSKate Stone 
1006ea671fbdSKate Stone     (lldb) break disable 1
1007ea671fbdSKate Stone     (lldb) break enable 1.1
1008ea671fbdSKate Stone 
1009ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1010ea671fbdSKate Stone 
1011ea671fbdSKate Stone     (lldb) break disable 1.*
1012ea671fbdSKate Stone     (lldb) break enable 1.1
1013ea671fbdSKate Stone 
10147428a18cSKate Stone )"
10157428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10167428a18cSKate Stone the second re-enables the first location.");
1017b0fac509SJim Ingham 
10185a988416SJim Ingham     CommandArgumentEntry arg;
1019b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1020b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1021b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1022b9c1b51eSKate Stone     // arguments vector.
10235a988416SJim Ingham     m_arguments.push_back(arg);
10245a988416SJim Ingham   }
10255a988416SJim Ingham 
10269e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10275a988416SJim Ingham 
10280e50b9a4SGongyu Deng   void
10290e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
10300e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
10310e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
10320e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10330e50b9a4SGongyu Deng         request, nullptr);
10340e50b9a4SGongyu Deng   }
10350e50b9a4SGongyu Deng 
10365a988416SJim Ingham protected:
1037b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1038cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1039bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1040cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10415a988416SJim Ingham 
1042cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10435a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10445a988416SJim Ingham 
1045b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10465a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10475a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10485a988416SJim Ingham       return false;
10495a988416SJim Ingham     }
10505a988416SJim Ingham 
105111eb9c64SZachary Turner     if (command.empty()) {
10525a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1053cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1054b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1055b9c1b51eSKate Stone                                      " breakpoints)\n",
1056b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10575a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1058b9c1b51eSKate Stone     } else {
10595a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10605a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10615a988416SJim Ingham 
1062b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1063cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1064b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10655a988416SJim Ingham 
1066b9c1b51eSKate Stone       if (result.Succeeded()) {
10675a988416SJim Ingham         int disable_count = 0;
10685a988416SJim Ingham         int loc_count = 0;
10695a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1070b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10715a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10725a988416SJim Ingham 
1073b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1074b9c1b51eSKate Stone             Breakpoint *breakpoint =
1075cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1076b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1077b9c1b51eSKate Stone               BreakpointLocation *location =
1078b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1079b9c1b51eSKate Stone               if (location) {
10805a988416SJim Ingham                 location->SetEnabled(false);
10815a988416SJim Ingham                 ++loc_count;
10825a988416SJim Ingham               }
1083b9c1b51eSKate Stone             } else {
10845a988416SJim Ingham               breakpoint->SetEnabled(false);
10855a988416SJim Ingham               ++disable_count;
10865a988416SJim Ingham             }
10875a988416SJim Ingham           }
10885a988416SJim Ingham         }
1089b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1090b9c1b51eSKate Stone                                        disable_count + loc_count);
10915a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10925a988416SJim Ingham       }
10935a988416SJim Ingham     }
10945a988416SJim Ingham 
10955a988416SJim Ingham     return result.Succeeded();
10965a988416SJim Ingham   }
10975a988416SJim Ingham };
10985a988416SJim Ingham 
10995a988416SJim Ingham // CommandObjectBreakpointList
11001f0f5b5bSZachary Turner 
11011f0f5b5bSZachary Turner #pragma mark List::CommandOptions
11026f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1103c5a2d747SRaphael Isemann #include "CommandOptions.inc"
11041f0f5b5bSZachary Turner 
11055a988416SJim Ingham #pragma mark List
11065a988416SJim Ingham 
1107b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
11085a988416SJim Ingham public:
1109b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1110b9c1b51eSKate Stone       : CommandObjectParsed(
1111b9c1b51eSKate Stone             interpreter, "breakpoint list",
11125a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
11139e85e5a8SEugene Zelenko             nullptr),
1114b9c1b51eSKate Stone         m_options() {
11155a988416SJim Ingham     CommandArgumentEntry arg;
11165a988416SJim Ingham     CommandArgumentData bp_id_arg;
11175a988416SJim Ingham 
11185a988416SJim Ingham     // Define the first (and only) variant of this arg.
11195a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11205a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11215a988416SJim Ingham 
1122b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1123b9c1b51eSKate Stone     // argument entry.
11245a988416SJim Ingham     arg.push_back(bp_id_arg);
11255a988416SJim Ingham 
11265a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11275a988416SJim Ingham     m_arguments.push_back(arg);
11285a988416SJim Ingham   }
11295a988416SJim Ingham 
11309e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11315a988416SJim Ingham 
1132b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11335a988416SJim Ingham 
1134b9c1b51eSKate Stone   class CommandOptions : public Options {
11355a988416SJim Ingham   public:
1136b9c1b51eSKate Stone     CommandOptions()
1137b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
11385a988416SJim Ingham     }
11395a988416SJim Ingham 
11409e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11415a988416SJim Ingham 
114297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1143b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
114497206d57SZachary Turner       Status error;
11453bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11465a988416SJim Ingham 
1147b9c1b51eSKate Stone       switch (short_option) {
11485a988416SJim Ingham       case 'b':
11495a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11505a988416SJim Ingham         break;
115133df7cd3SJim Ingham       case 'D':
115233df7cd3SJim Ingham         m_use_dummy = true;
115333df7cd3SJim Ingham         break;
11545a988416SJim Ingham       case 'f':
11555a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11565a988416SJim Ingham         break;
11575a988416SJim Ingham       case 'v':
11585a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11595a988416SJim Ingham         break;
11605a988416SJim Ingham       case 'i':
11615a988416SJim Ingham         m_internal = true;
11625a988416SJim Ingham         break;
11635a988416SJim Ingham       default:
116436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11655a988416SJim Ingham       }
11665a988416SJim Ingham 
11675a988416SJim Ingham       return error;
11685a988416SJim Ingham     }
11695a988416SJim Ingham 
1170b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11715a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11725a988416SJim Ingham       m_internal = false;
117333df7cd3SJim Ingham       m_use_dummy = false;
11745a988416SJim Ingham     }
11755a988416SJim Ingham 
11761f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
117770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11781f0f5b5bSZachary Turner     }
11795a988416SJim Ingham 
11805a988416SJim Ingham     // Instance variables to hold the values for command options.
11815a988416SJim Ingham 
11825a988416SJim Ingham     lldb::DescriptionLevel m_level;
11835a988416SJim Ingham 
11845a988416SJim Ingham     bool m_internal;
118533df7cd3SJim Ingham     bool m_use_dummy;
11865a988416SJim Ingham   };
11875a988416SJim Ingham 
11885a988416SJim Ingham protected:
1189b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1190cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11915a988416SJim Ingham 
1192b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1193cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1194bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1195cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11965a988416SJim Ingham 
11975a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11985a988416SJim Ingham 
1199b9c1b51eSKate Stone     if (num_breakpoints == 0) {
12005a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
12015a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
12025a988416SJim Ingham       return true;
12035a988416SJim Ingham     }
12045a988416SJim Ingham 
12055a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
12065a988416SJim Ingham 
120711eb9c64SZachary Turner     if (command.empty()) {
12085a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
12095a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1210b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
12115a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1212b842f2ecSJim Ingham         if (breakpoint->AllowList())
1213b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1214b842f2ecSJim Ingham                                    m_options.m_level);
12155a988416SJim Ingham       }
12165a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1217b9c1b51eSKate Stone     } else {
12185a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12195a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1220b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1221cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1222b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12235a988416SJim Ingham 
1224b9c1b51eSKate Stone       if (result.Succeeded()) {
1225b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12265a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1227b9c1b51eSKate Stone           Breakpoint *breakpoint =
1228cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1229b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1230b9c1b51eSKate Stone                                    m_options.m_level);
12315a988416SJim Ingham         }
12325a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1233b9c1b51eSKate Stone       } else {
12347428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12355a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
12365a988416SJim Ingham       }
12375a988416SJim Ingham     }
12385a988416SJim Ingham 
12395a988416SJim Ingham     return result.Succeeded();
12405a988416SJim Ingham   }
12415a988416SJim Ingham 
12425a988416SJim Ingham private:
12435a988416SJim Ingham   CommandOptions m_options;
12445a988416SJim Ingham };
12455a988416SJim Ingham 
12465a988416SJim Ingham // CommandObjectBreakpointClear
12471f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12481f0f5b5bSZachary Turner 
1249f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1250f94668e3SRaphael Isemann #include "CommandOptions.inc"
12511f0f5b5bSZachary Turner 
12525a988416SJim Ingham #pragma mark Clear
12535a988416SJim Ingham 
1254b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12555a988416SJim Ingham public:
1256efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12575a988416SJim Ingham 
12587428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12597428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1260b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1261b9c1b51eSKate Stone                             "specified source file and line.",
12625a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1263b9c1b51eSKate Stone         m_options() {}
12645a988416SJim Ingham 
12659e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12665a988416SJim Ingham 
1267b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12685a988416SJim Ingham 
1269b9c1b51eSKate Stone   class CommandOptions : public Options {
12705a988416SJim Ingham   public:
1271b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
12725a988416SJim Ingham 
12739e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12745a988416SJim Ingham 
127597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1276b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
127797206d57SZachary Turner       Status error;
12783bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12795a988416SJim Ingham 
1280b9c1b51eSKate Stone       switch (short_option) {
12815a988416SJim Ingham       case 'f':
1282adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
12835a988416SJim Ingham         break;
12845a988416SJim Ingham 
12855a988416SJim Ingham       case 'l':
1286fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12875a988416SJim Ingham         break;
12885a988416SJim Ingham 
12895a988416SJim Ingham       default:
129036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12915a988416SJim Ingham       }
12925a988416SJim Ingham 
12935a988416SJim Ingham       return error;
12945a988416SJim Ingham     }
12955a988416SJim Ingham 
1296b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12975a988416SJim Ingham       m_filename.clear();
12985a988416SJim Ingham       m_line_num = 0;
12995a988416SJim Ingham     }
13005a988416SJim Ingham 
13011f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
130270602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
13031f0f5b5bSZachary Turner     }
13045a988416SJim Ingham 
13055a988416SJim Ingham     // Instance variables to hold the values for command options.
13065a988416SJim Ingham 
13075a988416SJim Ingham     std::string m_filename;
13085a988416SJim Ingham     uint32_t m_line_num;
13095a988416SJim Ingham   };
13105a988416SJim Ingham 
13115a988416SJim Ingham protected:
1312b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1313cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
13145a988416SJim Ingham 
131505097246SAdrian Prantl     // The following are the various types of breakpoints that could be
131605097246SAdrian Prantl     // cleared:
13175a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13185a988416SJim Ingham 
13195a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13205a988416SJim Ingham 
13215a988416SJim Ingham     if (m_options.m_line_num != 0)
13225a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13235a988416SJim Ingham 
1324bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1325cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13265a988416SJim Ingham 
1327cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13285a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13295a988416SJim Ingham 
13305a988416SJim Ingham     // Early return if there's no breakpoint at all.
1331b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13325a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13335a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13345a988416SJim Ingham       return result.Succeeded();
13355a988416SJim Ingham     }
13365a988416SJim Ingham 
13375a988416SJim Ingham     // Find matching breakpoints and delete them.
13385a988416SJim Ingham 
13395a988416SJim Ingham     // First create a copy of all the IDs.
13405a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13415a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13429e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13435a988416SJim Ingham 
13445a988416SJim Ingham     int num_cleared = 0;
13455a988416SJim Ingham     StreamString ss;
1346b9c1b51eSKate Stone     switch (break_type) {
13475a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13485a988416SJim Ingham     {
13495a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13505a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13515a988416SJim Ingham 
1352b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13535a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13545a988416SJim Ingham 
1355b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1356b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1357b9c1b51eSKate Stone           // remove the breakpoint.
1358b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13595a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13605a988416SJim Ingham             ss.EOL();
1361cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13625a988416SJim Ingham             ++num_cleared;
13635a988416SJim Ingham           }
13645a988416SJim Ingham         }
13655a988416SJim Ingham       }
1366b9c1b51eSKate Stone     } break;
13675a988416SJim Ingham 
13685a988416SJim Ingham     default:
13695a988416SJim Ingham       break;
13705a988416SJim Ingham     }
13715a988416SJim Ingham 
1372b9c1b51eSKate Stone     if (num_cleared > 0) {
13735a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13745a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1375c156427dSZachary Turner       output_stream << ss.GetString();
13765a988416SJim Ingham       output_stream.EOL();
13775a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1378b9c1b51eSKate Stone     } else {
13795a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13805a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13815a988416SJim Ingham     }
13825a988416SJim Ingham 
13835a988416SJim Ingham     return result.Succeeded();
13845a988416SJim Ingham   }
13855a988416SJim Ingham 
13865a988416SJim Ingham private:
13875a988416SJim Ingham   CommandOptions m_options;
13885a988416SJim Ingham };
13895a988416SJim Ingham 
13905a988416SJim Ingham // CommandObjectBreakpointDelete
1391f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1392f94668e3SRaphael Isemann #include "CommandOptions.inc"
13931f0f5b5bSZachary Turner 
13945a988416SJim Ingham #pragma mark Delete
13955a988416SJim Ingham 
1396b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13975a988416SJim Ingham public:
1398b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1399b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1400b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1401b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
14029e85e5a8SEugene Zelenko                             nullptr),
1403b9c1b51eSKate Stone         m_options() {
14045a988416SJim Ingham     CommandArgumentEntry arg;
1405b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1406b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1407b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1408b9c1b51eSKate Stone     // arguments vector.
14095a988416SJim Ingham     m_arguments.push_back(arg);
14105a988416SJim Ingham   }
14115a988416SJim Ingham 
14129e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
14135a988416SJim Ingham 
14140e50b9a4SGongyu Deng   void
14150e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
14160e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
14170e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
14180e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
14190e50b9a4SGongyu Deng         request, nullptr);
14200e50b9a4SGongyu Deng   }
14210e50b9a4SGongyu Deng 
1422b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
142333df7cd3SJim Ingham 
1424b9c1b51eSKate Stone   class CommandOptions : public Options {
142533df7cd3SJim Ingham   public:
1426b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
142733df7cd3SJim Ingham 
14289e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
142933df7cd3SJim Ingham 
143097206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1431b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
143297206d57SZachary Turner       Status error;
143333df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
143433df7cd3SJim Ingham 
1435b9c1b51eSKate Stone       switch (short_option) {
143633df7cd3SJim Ingham       case 'f':
143733df7cd3SJim Ingham         m_force = true;
143833df7cd3SJim Ingham         break;
143933df7cd3SJim Ingham 
144033df7cd3SJim Ingham       case 'D':
144133df7cd3SJim Ingham         m_use_dummy = true;
144233df7cd3SJim Ingham         break;
144333df7cd3SJim Ingham 
144433df7cd3SJim Ingham       default:
144536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
144633df7cd3SJim Ingham       }
144733df7cd3SJim Ingham 
144833df7cd3SJim Ingham       return error;
144933df7cd3SJim Ingham     }
145033df7cd3SJim Ingham 
1451b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
145233df7cd3SJim Ingham       m_use_dummy = false;
145333df7cd3SJim Ingham       m_force = false;
145433df7cd3SJim Ingham     }
145533df7cd3SJim Ingham 
14561f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
145770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14581f0f5b5bSZachary Turner     }
145933df7cd3SJim Ingham 
146033df7cd3SJim Ingham     // Instance variables to hold the values for command options.
146133df7cd3SJim Ingham     bool m_use_dummy;
146233df7cd3SJim Ingham     bool m_force;
146333df7cd3SJim Ingham   };
146433df7cd3SJim Ingham 
14655a988416SJim Ingham protected:
1466b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1467cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14685a988416SJim Ingham 
1469bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1470cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14715a988416SJim Ingham 
1472cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
14735a988416SJim Ingham 
14745a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14755a988416SJim Ingham 
1476b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14775a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14785a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14795a988416SJim Ingham       return false;
14805a988416SJim Ingham     }
14815a988416SJim Ingham 
148211eb9c64SZachary Turner     if (command.empty()) {
1483b9c1b51eSKate Stone       if (!m_options.m_force &&
1484b9c1b51eSKate Stone           !m_interpreter.Confirm(
1485b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1486b9c1b51eSKate Stone               true)) {
14875a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1488b9c1b51eSKate Stone       } else {
1489cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1490b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1491b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1492b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14935a988416SJim Ingham       }
14945a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1495b9c1b51eSKate Stone     } else {
14965a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
14975a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1498b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1499cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1500b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
15015a988416SJim Ingham 
1502b9c1b51eSKate Stone       if (result.Succeeded()) {
15035a988416SJim Ingham         int delete_count = 0;
15045a988416SJim Ingham         int disable_count = 0;
15055a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1506b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
15075a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15085a988416SJim Ingham 
1509b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1510b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1511b9c1b51eSKate Stone               Breakpoint *breakpoint =
1512cb2380c9SRaphael Isemann                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1513b9c1b51eSKate Stone               BreakpointLocation *location =
1514b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1515b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1516b9c1b51eSKate Stone               // disable them instead.
1517b9c1b51eSKate Stone               if (location) {
15185a988416SJim Ingham                 location->SetEnabled(false);
15195a988416SJim Ingham                 ++disable_count;
15205a988416SJim Ingham               }
1521b9c1b51eSKate Stone             } else {
1522cb2380c9SRaphael Isemann               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15235a988416SJim Ingham               ++delete_count;
15245a988416SJim Ingham             }
15255a988416SJim Ingham           }
15265a988416SJim Ingham         }
1527b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1528b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15295a988416SJim Ingham             delete_count, disable_count);
15305a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
15315a988416SJim Ingham       }
15325a988416SJim Ingham     }
15335a988416SJim Ingham     return result.Succeeded();
15345a988416SJim Ingham   }
15359e85e5a8SEugene Zelenko 
153633df7cd3SJim Ingham private:
153733df7cd3SJim Ingham   CommandOptions m_options;
153833df7cd3SJim Ingham };
153933df7cd3SJim Ingham 
15405e09c8c3SJim Ingham // CommandObjectBreakpointName
1541f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1542f94668e3SRaphael Isemann #include "CommandOptions.inc"
1543bd68a052SRaphael Isemann 
1544b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15455e09c8c3SJim Ingham public:
1546b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1547b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15485e09c8c3SJim Ingham   }
15495e09c8c3SJim Ingham 
15509e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15515e09c8c3SJim Ingham 
15521f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
155370602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15545e09c8c3SJim Ingham   }
15555e09c8c3SJim Ingham 
155697206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1557b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
155897206d57SZachary Turner     Status error;
15595e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15605e09c8c3SJim Ingham 
1561b9c1b51eSKate Stone     switch (short_option) {
15625e09c8c3SJim Ingham     case 'N':
1563fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1564b9c1b51eSKate Stone           error.Success())
1565fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15665e09c8c3SJim Ingham       break;
15675e09c8c3SJim Ingham     case 'B':
1568fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1569b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15708cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1571fe11483bSZachary Turner             option_arg.str().c_str());
15725e09c8c3SJim Ingham       break;
15735e09c8c3SJim Ingham     case 'D':
1574fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1575b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15768cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1577fe11483bSZachary Turner             option_arg.str().c_str());
15785e09c8c3SJim Ingham       break;
1579e9632ebaSJim Ingham     case 'H':
1580e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1581e9632ebaSJim Ingham       break;
15825e09c8c3SJim Ingham 
15835e09c8c3SJim Ingham     default:
158436162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15855e09c8c3SJim Ingham     }
15865e09c8c3SJim Ingham     return error;
15875e09c8c3SJim Ingham   }
15885e09c8c3SJim Ingham 
1589b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
15905e09c8c3SJim Ingham     m_name.Clear();
15915e09c8c3SJim Ingham     m_breakpoint.Clear();
15925e09c8c3SJim Ingham     m_use_dummy.Clear();
15935e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1594e9632ebaSJim Ingham     m_help_string.Clear();
15955e09c8c3SJim Ingham   }
15965e09c8c3SJim Ingham 
15975e09c8c3SJim Ingham   OptionValueString m_name;
15985e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
15995e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1600e9632ebaSJim Ingham   OptionValueString m_help_string;
16015e09c8c3SJim Ingham };
16025e09c8c3SJim Ingham 
1603f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1604f94668e3SRaphael Isemann #include "CommandOptions.inc"
1605b842f2ecSJim Ingham 
16068fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1607b842f2ecSJim Ingham public:
16088fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1609b842f2ecSJim Ingham 
1610b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1611b842f2ecSJim Ingham 
1612b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1613b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1614b842f2ecSJim Ingham   }
1615b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1616b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1617b842f2ecSJim Ingham     Status error;
1618a925974bSAdrian Prantl     const int short_option =
1619a925974bSAdrian Prantl         g_breakpoint_access_options[option_idx].short_option;
1620b842f2ecSJim Ingham 
1621b842f2ecSJim Ingham     switch (short_option) {
1622b842f2ecSJim Ingham     case 'L': {
1623b842f2ecSJim Ingham       bool value, success;
162447cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1625b842f2ecSJim Ingham       if (success) {
1626b842f2ecSJim Ingham         m_permissions.SetAllowList(value);
1627b842f2ecSJim Ingham       } else
1628b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1629b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1630b842f2ecSJim Ingham             option_arg.str().c_str());
1631b842f2ecSJim Ingham     } break;
1632b842f2ecSJim Ingham     case 'A': {
1633b842f2ecSJim Ingham       bool value, success;
163447cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1635b842f2ecSJim Ingham       if (success) {
1636b842f2ecSJim Ingham         m_permissions.SetAllowDisable(value);
1637b842f2ecSJim Ingham       } else
1638b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1639b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1640b842f2ecSJim Ingham             option_arg.str().c_str());
1641b842f2ecSJim Ingham     } break;
1642b842f2ecSJim Ingham     case 'D': {
1643b842f2ecSJim Ingham       bool value, success;
164447cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1645b842f2ecSJim Ingham       if (success) {
1646b842f2ecSJim Ingham         m_permissions.SetAllowDelete(value);
1647b842f2ecSJim Ingham       } else
1648b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1649b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1650b842f2ecSJim Ingham             option_arg.str().c_str());
1651b842f2ecSJim Ingham     } break;
165236162014SRaphael Isemann     default:
165336162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
1654b842f2ecSJim Ingham     }
1655b842f2ecSJim Ingham 
1656b842f2ecSJim Ingham     return error;
1657b842f2ecSJim Ingham   }
1658b842f2ecSJim Ingham 
1659a925974bSAdrian Prantl   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1660b842f2ecSJim Ingham 
1661a925974bSAdrian Prantl   const BreakpointName::Permissions &GetPermissions() const {
1662b842f2ecSJim Ingham     return m_permissions;
1663b842f2ecSJim Ingham   }
1664b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1665b842f2ecSJim Ingham };
1666b842f2ecSJim Ingham 
1667b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1668b842f2ecSJim Ingham public:
1669b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1670b842f2ecSJim Ingham       : CommandObjectParsed(
1671a925974bSAdrian Prantl             interpreter, "configure",
1672a925974bSAdrian Prantl             "Configure the options for the breakpoint"
1673b842f2ecSJim Ingham             " name provided.  "
1674b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1675b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1676b842f2ecSJim Ingham             "on the name.",
1677b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1678b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1679b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1680b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1681b842f2ecSJim Ingham     // command.
1682b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1683b842f2ecSJim Ingham     CommandArgumentData id_arg;
1684b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1685b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1686b842f2ecSJim Ingham     arg1.push_back(id_arg);
1687b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1688b842f2ecSJim Ingham 
1689a925974bSAdrian Prantl     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1690a925974bSAdrian Prantl     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1691b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1692a925974bSAdrian Prantl     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1693e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1694b842f2ecSJim Ingham     m_option_group.Finalize();
1695b842f2ecSJim Ingham   }
1696b842f2ecSJim Ingham 
1697b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1698b842f2ecSJim Ingham 
1699b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1700b842f2ecSJim Ingham 
1701b842f2ecSJim Ingham protected:
1702b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1703b842f2ecSJim Ingham 
1704b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1705b842f2ecSJim Ingham     if (argc == 0) {
1706b842f2ecSJim Ingham       result.AppendError("No names provided.");
1707b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1708b842f2ecSJim Ingham       return false;
1709b842f2ecSJim Ingham     }
1710b842f2ecSJim Ingham 
1711cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1712b842f2ecSJim Ingham 
1713b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1714cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1715b842f2ecSJim Ingham 
1716b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1717b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1718b842f2ecSJim Ingham       Status error;
1719a925974bSAdrian Prantl       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1720b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1721b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1722b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1723b842f2ecSJim Ingham         return false;
1724b842f2ecSJim Ingham       }
1725b842f2ecSJim Ingham     }
172605097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
172705097246SAdrian Prantl     // check the error:
1728b842f2ecSJim Ingham     BreakpointSP bp_sp;
1729a925974bSAdrian Prantl     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1730b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1731cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1732a925974bSAdrian Prantl       if (!bp_sp) {
1733b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1734b842f2ecSJim Ingham                                       bp_id);
1735b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1736b842f2ecSJim Ingham         return false;
1737b842f2ecSJim Ingham       }
1738b842f2ecSJim Ingham     }
1739b842f2ecSJim Ingham 
1740b842f2ecSJim Ingham     Status error;
1741b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1742b842f2ecSJim Ingham       ConstString name(entry.c_str());
1743cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1744b842f2ecSJim Ingham       if (!bp_name)
1745b842f2ecSJim Ingham         continue;
1746e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1747e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1748e9632ebaSJim Ingham 
1749b842f2ecSJim Ingham       if (bp_sp)
1750cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1751b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1752b842f2ecSJim Ingham       else
1753cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1754b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1755b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1756b842f2ecSJim Ingham     }
1757b842f2ecSJim Ingham     return true;
1758b842f2ecSJim Ingham   }
1759b842f2ecSJim Ingham 
1760b842f2ecSJim Ingham private:
1761b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1762b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1763b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1764b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1765b842f2ecSJim Ingham };
1766b842f2ecSJim Ingham 
1767b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17685e09c8c3SJim Ingham public:
1769b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1770b9c1b51eSKate Stone       : CommandObjectParsed(
1771b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
17725e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1773b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1774b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1775b9c1b51eSKate Stone     // command.
17765e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17775e09c8c3SJim Ingham     CommandArgumentData id_arg;
17785e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17795e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17805e09c8c3SJim Ingham     arg1.push_back(id_arg);
17815e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17825e09c8c3SJim Ingham 
17835e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17845e09c8c3SJim Ingham     m_option_group.Finalize();
17855e09c8c3SJim Ingham   }
17865e09c8c3SJim Ingham 
17879e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17885e09c8c3SJim Ingham 
1789e87362e6SGongyu Deng   void
1790e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1791e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1792e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1793e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1794e87362e6SGongyu Deng         request, nullptr);
1795e87362e6SGongyu Deng   }
1796e87362e6SGongyu Deng 
1797b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
17985e09c8c3SJim Ingham 
17995e09c8c3SJim Ingham protected:
1800b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1801b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18025e09c8c3SJim Ingham       result.SetError("No name option provided.");
18035e09c8c3SJim Ingham       return false;
18045e09c8c3SJim Ingham     }
18055e09c8c3SJim Ingham 
1806cb2380c9SRaphael Isemann     Target &target =
1807b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18085e09c8c3SJim Ingham 
1809bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1810cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18115e09c8c3SJim Ingham 
1812cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18135e09c8c3SJim Ingham 
18145e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1815b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18165e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18175e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18185e09c8c3SJim Ingham       return false;
18195e09c8c3SJim Ingham     }
18205e09c8c3SJim Ingham 
18215e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18225e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1823b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1824cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1825b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18265e09c8c3SJim Ingham 
1827b9c1b51eSKate Stone     if (result.Succeeded()) {
1828b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18295e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18305e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18315e09c8c3SJim Ingham         return false;
18325e09c8c3SJim Ingham       }
18335e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1834b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1835b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1836b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1837b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1838b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1839b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18405e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1841cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18425e09c8c3SJim Ingham       }
18435e09c8c3SJim Ingham     }
18445e09c8c3SJim Ingham 
18455e09c8c3SJim Ingham     return true;
18465e09c8c3SJim Ingham   }
18475e09c8c3SJim Ingham 
18485e09c8c3SJim Ingham private:
18495e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18505e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18515e09c8c3SJim Ingham };
18525e09c8c3SJim Ingham 
1853b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18545e09c8c3SJim Ingham public:
1855b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1856b9c1b51eSKate Stone       : CommandObjectParsed(
1857b9c1b51eSKate Stone             interpreter, "delete",
18585e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18595e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1860b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1861b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1862b9c1b51eSKate Stone     // command.
18635e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18645e09c8c3SJim Ingham     CommandArgumentData id_arg;
18655e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18665e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18675e09c8c3SJim Ingham     arg1.push_back(id_arg);
18685e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18695e09c8c3SJim Ingham 
18705e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18715e09c8c3SJim Ingham     m_option_group.Finalize();
18725e09c8c3SJim Ingham   }
18735e09c8c3SJim Ingham 
18749e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18755e09c8c3SJim Ingham 
1876e87362e6SGongyu Deng   void
1877e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1878e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1879e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1880e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1881e87362e6SGongyu Deng         request, nullptr);
1882e87362e6SGongyu Deng   }
1883e87362e6SGongyu Deng 
1884b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18855e09c8c3SJim Ingham 
18865e09c8c3SJim Ingham protected:
1887b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1888b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18895e09c8c3SJim Ingham       result.SetError("No name option provided.");
18905e09c8c3SJim Ingham       return false;
18915e09c8c3SJim Ingham     }
18925e09c8c3SJim Ingham 
1893cb2380c9SRaphael Isemann     Target &target =
1894b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18955e09c8c3SJim Ingham 
1896bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1897cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18985e09c8c3SJim Ingham 
1899cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
19005e09c8c3SJim Ingham 
19015e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1902b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19035e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
19045e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19055e09c8c3SJim Ingham       return false;
19065e09c8c3SJim Ingham     }
19075e09c8c3SJim Ingham 
19085e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19095e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1910b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1911cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1912b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
19135e09c8c3SJim Ingham 
1914b9c1b51eSKate Stone     if (result.Succeeded()) {
1915b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19165e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
19175e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19185e09c8c3SJim Ingham         return false;
19195e09c8c3SJim Ingham       }
1920b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19215e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1922b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1923b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1924b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19255e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1926cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19275e09c8c3SJim Ingham       }
19285e09c8c3SJim Ingham     }
19295e09c8c3SJim Ingham 
19305e09c8c3SJim Ingham     return true;
19315e09c8c3SJim Ingham   }
19325e09c8c3SJim Ingham 
19335e09c8c3SJim Ingham private:
19345e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19355e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19365e09c8c3SJim Ingham };
19375e09c8c3SJim Ingham 
1938b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19395e09c8c3SJim Ingham public:
1940b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1941b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1942b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1943b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1944b842f2ecSJim Ingham                             "names",
19455e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1946b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1947b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19485e09c8c3SJim Ingham     m_option_group.Finalize();
19495e09c8c3SJim Ingham   }
19505e09c8c3SJim Ingham 
19519e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19525e09c8c3SJim Ingham 
1953b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19545e09c8c3SJim Ingham 
19555e09c8c3SJim Ingham protected:
1956b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1957cb2380c9SRaphael Isemann     Target &target =
1958b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19595e09c8c3SJim Ingham 
1960b842f2ecSJim Ingham     std::vector<std::string> name_list;
1961b842f2ecSJim Ingham     if (command.empty()) {
1962cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1963b842f2ecSJim Ingham     } else {
1964a925974bSAdrian Prantl       for (const Args::ArgEntry &arg : command) {
1965b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1966b842f2ecSJim Ingham       }
1967b842f2ecSJim Ingham     }
1968b842f2ecSJim Ingham 
1969b842f2ecSJim Ingham     if (name_list.empty()) {
1970b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1971b842f2ecSJim Ingham     } else {
1972b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1973b842f2ecSJim Ingham         const char *name = name_str.c_str();
1974b842f2ecSJim Ingham         // First print out the options for the name:
1975b842f2ecSJim Ingham         Status error;
1976cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1977cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1978a925974bSAdrian Prantl         if (bp_name) {
1979b842f2ecSJim Ingham           StreamString s;
1980b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1981a925974bSAdrian Prantl           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1982b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1983b842f2ecSJim Ingham           }
1984b842f2ecSJim Ingham 
1985bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1986cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19875e09c8c3SJim Ingham 
1988cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1989b842f2ecSJim Ingham           bool any_set = false;
1990b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1991b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19925e09c8c3SJim Ingham               StreamString s;
1993b842f2ecSJim Ingham               any_set = true;
19945e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19955e09c8c3SJim Ingham               s.EOL();
1996c156427dSZachary Turner               result.AppendMessage(s.GetString());
19975e09c8c3SJim Ingham             }
19985e09c8c3SJim Ingham           }
1999b842f2ecSJim Ingham           if (!any_set)
2000b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
2001b9c1b51eSKate Stone         } else {
2002b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
20035e09c8c3SJim Ingham         }
2004b842f2ecSJim Ingham       }
20055e09c8c3SJim Ingham     }
20065e09c8c3SJim Ingham     return true;
20075e09c8c3SJim Ingham   }
20085e09c8c3SJim Ingham 
20095e09c8c3SJim Ingham private:
20105e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20115e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20125e09c8c3SJim Ingham };
20135e09c8c3SJim Ingham 
2014e14dc268SJim Ingham // CommandObjectBreakpointName
2015b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20165e09c8c3SJim Ingham public:
20177428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2018b9c1b51eSKate Stone       : CommandObjectMultiword(
2019b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2020b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2021b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2022b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2023b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2024b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2025b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2026b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2027b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2028b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
20295e09c8c3SJim Ingham 
20305e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20315e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20325e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2033b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
20345e09c8c3SJim Ingham   }
20355e09c8c3SJim Ingham 
20369e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20375e09c8c3SJim Ingham };
20385e09c8c3SJim Ingham 
2039e14dc268SJim Ingham // CommandObjectBreakpointRead
20403acdf385SJim Ingham #pragma mark Read::CommandOptions
2041f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2042f94668e3SRaphael Isemann #include "CommandOptions.inc"
20431f0f5b5bSZachary Turner 
20441f0f5b5bSZachary Turner #pragma mark Read
2045e14dc268SJim Ingham 
2046e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2047e14dc268SJim Ingham public:
2048e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2049e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2050e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2051e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2052e14dc268SJim Ingham                             nullptr),
20537c89297cSGongyu Deng         m_options() {}
2054e14dc268SJim Ingham 
2055e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2056e14dc268SJim Ingham 
2057e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2058e14dc268SJim Ingham 
2059e14dc268SJim Ingham   class CommandOptions : public Options {
2060e14dc268SJim Ingham   public:
2061e14dc268SJim Ingham     CommandOptions() : Options() {}
2062e14dc268SJim Ingham 
2063e14dc268SJim Ingham     ~CommandOptions() override = default;
2064e14dc268SJim Ingham 
206597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2066e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
206797206d57SZachary Turner       Status error;
2068e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2069e14dc268SJim Ingham 
2070e14dc268SJim Ingham       switch (short_option) {
2071e14dc268SJim Ingham       case 'f':
2072adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2073e14dc268SJim Ingham         break;
20743acdf385SJim Ingham       case 'N': {
207597206d57SZachary Turner         Status name_error;
20763acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20773acdf385SJim Ingham                                                   name_error)) {
20783acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20793acdf385SJim Ingham                                          name_error.AsCString());
20803acdf385SJim Ingham         }
2081adcd0268SBenjamin Kramer         m_names.push_back(std::string(option_arg));
20823acdf385SJim Ingham         break;
20833acdf385SJim Ingham       }
2084e14dc268SJim Ingham       default:
208536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2086e14dc268SJim Ingham       }
2087e14dc268SJim Ingham 
2088e14dc268SJim Ingham       return error;
2089e14dc268SJim Ingham     }
2090e14dc268SJim Ingham 
2091e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2092e14dc268SJim Ingham       m_filename.clear();
20933acdf385SJim Ingham       m_names.clear();
2094e14dc268SJim Ingham     }
2095e14dc268SJim Ingham 
20961f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
209770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
20981f0f5b5bSZachary Turner     }
2099e14dc268SJim Ingham 
2100*22e63cbaSGongyu Deng     void HandleOptionArgumentCompletion(
2101*22e63cbaSGongyu Deng         CompletionRequest &request, OptionElementVector &opt_element_vector,
2102*22e63cbaSGongyu Deng         int opt_element_index, CommandInterpreter &interpreter) override {
2103*22e63cbaSGongyu Deng       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2104*22e63cbaSGongyu Deng       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2105*22e63cbaSGongyu Deng 
2106*22e63cbaSGongyu Deng       switch (GetDefinitions()[opt_defs_index].short_option) {
2107*22e63cbaSGongyu Deng       case 'f':
2108*22e63cbaSGongyu Deng         CommandCompletions::InvokeCommonCompletionCallbacks(
2109*22e63cbaSGongyu Deng             interpreter, CommandCompletions::eDiskFileCompletion, request,
2110*22e63cbaSGongyu Deng             nullptr);
2111*22e63cbaSGongyu Deng         break;
2112*22e63cbaSGongyu Deng 
2113*22e63cbaSGongyu Deng       case 'N':
2114*22e63cbaSGongyu Deng         llvm::Optional<FileSpec> file_spec;
2115*22e63cbaSGongyu Deng         const llvm::StringRef dash_f("-f");
2116*22e63cbaSGongyu Deng         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2117*22e63cbaSGongyu Deng           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2118*22e63cbaSGongyu Deng             file_spec.emplace(
2119*22e63cbaSGongyu Deng                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2120*22e63cbaSGongyu Deng             break;
2121*22e63cbaSGongyu Deng           }
2122*22e63cbaSGongyu Deng         }
2123*22e63cbaSGongyu Deng         if (!file_spec)
2124*22e63cbaSGongyu Deng           return;
2125*22e63cbaSGongyu Deng 
2126*22e63cbaSGongyu Deng         FileSystem::Instance().Resolve(*file_spec);
2127*22e63cbaSGongyu Deng         Status error;
2128*22e63cbaSGongyu Deng         StructuredData::ObjectSP input_data_sp =
2129*22e63cbaSGongyu Deng             StructuredData::ParseJSONFromFile(*file_spec, error);
2130*22e63cbaSGongyu Deng         if (!error.Success())
2131*22e63cbaSGongyu Deng           return;
2132*22e63cbaSGongyu Deng 
2133*22e63cbaSGongyu Deng         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2134*22e63cbaSGongyu Deng         if (!bkpt_array)
2135*22e63cbaSGongyu Deng           return;
2136*22e63cbaSGongyu Deng 
2137*22e63cbaSGongyu Deng         const size_t num_bkpts = bkpt_array->GetSize();
2138*22e63cbaSGongyu Deng         for (size_t i = 0; i < num_bkpts; i++) {
2139*22e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_object_sp =
2140*22e63cbaSGongyu Deng               bkpt_array->GetItemAtIndex(i);
2141*22e63cbaSGongyu Deng           if (!bkpt_object_sp)
2142*22e63cbaSGongyu Deng             return;
2143*22e63cbaSGongyu Deng 
2144*22e63cbaSGongyu Deng           StructuredData::Dictionary *bkpt_dict =
2145*22e63cbaSGongyu Deng               bkpt_object_sp->GetAsDictionary();
2146*22e63cbaSGongyu Deng           if (!bkpt_dict)
2147*22e63cbaSGongyu Deng             return;
2148*22e63cbaSGongyu Deng 
2149*22e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_data_sp =
2150*22e63cbaSGongyu Deng               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2151*22e63cbaSGongyu Deng           if (!bkpt_data_sp)
2152*22e63cbaSGongyu Deng             return;
2153*22e63cbaSGongyu Deng 
2154*22e63cbaSGongyu Deng           bkpt_dict = bkpt_data_sp->GetAsDictionary();
2155*22e63cbaSGongyu Deng           if (!bkpt_dict)
2156*22e63cbaSGongyu Deng             return;
2157*22e63cbaSGongyu Deng 
2158*22e63cbaSGongyu Deng           StructuredData::Array *names_array;
2159*22e63cbaSGongyu Deng 
2160*22e63cbaSGongyu Deng           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2161*22e63cbaSGongyu Deng             return;
2162*22e63cbaSGongyu Deng 
2163*22e63cbaSGongyu Deng           size_t num_names = names_array->GetSize();
2164*22e63cbaSGongyu Deng 
2165*22e63cbaSGongyu Deng           for (size_t i = 0; i < num_names; i++) {
2166*22e63cbaSGongyu Deng             llvm::StringRef name;
2167*22e63cbaSGongyu Deng             if (names_array->GetItemAtIndexAsString(i, name))
2168*22e63cbaSGongyu Deng               request.TryCompleteCurrentArg(name);
2169*22e63cbaSGongyu Deng           }
2170*22e63cbaSGongyu Deng         }
2171*22e63cbaSGongyu Deng       }
2172*22e63cbaSGongyu Deng     }
2173e14dc268SJim Ingham 
2174e14dc268SJim Ingham     std::string m_filename;
21753acdf385SJim Ingham     std::vector<std::string> m_names;
2176e14dc268SJim Ingham   };
2177e14dc268SJim Ingham 
2178e14dc268SJim Ingham protected:
2179e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2180cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2181e14dc268SJim Ingham 
21823acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2183cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
21843acdf385SJim Ingham 
21858f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
21868f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
218701f16664SJim Ingham     BreakpointIDList new_bps;
2188cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2189cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2190e14dc268SJim Ingham 
2191e14dc268SJim Ingham     if (!error.Success()) {
219201f16664SJim Ingham       result.AppendError(error.AsCString());
2193e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
219401f16664SJim Ingham       return false;
2195e14dc268SJim Ingham     }
21963acdf385SJim Ingham 
21973acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
21983acdf385SJim Ingham 
21993acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
22003acdf385SJim Ingham     if (num_breakpoints == 0) {
22013acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
22023acdf385SJim Ingham     } else {
22033acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
22043acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
22053acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
22063acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2207cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
22083acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
22093acdf385SJim Ingham                              .get();
22103acdf385SJim Ingham         if (bp)
22113acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22123acdf385SJim Ingham                              false);
22133acdf385SJim Ingham       }
22143acdf385SJim Ingham     }
2215e14dc268SJim Ingham     return result.Succeeded();
2216e14dc268SJim Ingham   }
2217e14dc268SJim Ingham 
2218e14dc268SJim Ingham private:
2219e14dc268SJim Ingham   CommandOptions m_options;
2220e14dc268SJim Ingham };
2221e14dc268SJim Ingham 
2222e14dc268SJim Ingham // CommandObjectBreakpointWrite
22231f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2224f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2225f94668e3SRaphael Isemann #include "CommandOptions.inc"
22261f0f5b5bSZachary Turner 
22271f0f5b5bSZachary Turner #pragma mark Write
2228e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2229e14dc268SJim Ingham public:
2230e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2231e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2232e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2233e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2234e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2235e14dc268SJim Ingham                             nullptr),
2236e14dc268SJim Ingham         m_options() {
2237e14dc268SJim Ingham     CommandArgumentEntry arg;
2238e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2239e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2240e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2241e14dc268SJim Ingham     // arguments vector.
2242e14dc268SJim Ingham     m_arguments.push_back(arg);
2243e14dc268SJim Ingham   }
2244e14dc268SJim Ingham 
2245e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2246e14dc268SJim Ingham 
2247e87362e6SGongyu Deng   void
2248e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
2249e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
2250e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
2251e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2252e87362e6SGongyu Deng         request, nullptr);
2253e87362e6SGongyu Deng   }
2254e87362e6SGongyu Deng 
2255e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2256e14dc268SJim Ingham 
2257e14dc268SJim Ingham   class CommandOptions : public Options {
2258e14dc268SJim Ingham   public:
2259e14dc268SJim Ingham     CommandOptions() : Options() {}
2260e14dc268SJim Ingham 
2261e14dc268SJim Ingham     ~CommandOptions() override = default;
2262e14dc268SJim Ingham 
226397206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2264e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
226597206d57SZachary Turner       Status error;
2266e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2267e14dc268SJim Ingham 
2268e14dc268SJim Ingham       switch (short_option) {
2269e14dc268SJim Ingham       case 'f':
2270adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2271e14dc268SJim Ingham         break;
22722d3628e1SJim Ingham       case 'a':
22732d3628e1SJim Ingham         m_append = true;
22742d3628e1SJim Ingham         break;
2275e14dc268SJim Ingham       default:
227636162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2277e14dc268SJim Ingham       }
2278e14dc268SJim Ingham 
2279e14dc268SJim Ingham       return error;
2280e14dc268SJim Ingham     }
2281e14dc268SJim Ingham 
2282e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2283e14dc268SJim Ingham       m_filename.clear();
22842d3628e1SJim Ingham       m_append = false;
2285e14dc268SJim Ingham     }
2286e14dc268SJim Ingham 
22871f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
228870602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
22891f0f5b5bSZachary Turner     }
2290e14dc268SJim Ingham 
2291e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2292e14dc268SJim Ingham 
2293e14dc268SJim Ingham     std::string m_filename;
22942d3628e1SJim Ingham     bool m_append = false;
2295e14dc268SJim Ingham   };
2296e14dc268SJim Ingham 
2297e14dc268SJim Ingham protected:
2298e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2299cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2300e14dc268SJim Ingham 
2301e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2302cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2303e14dc268SJim Ingham 
2304e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
230511eb9c64SZachary Turner     if (!command.empty()) {
2306e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2307cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2308b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2309e14dc268SJim Ingham 
231001f16664SJim Ingham       if (!result.Succeeded()) {
2311e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2312e14dc268SJim Ingham         return false;
2313e14dc268SJim Ingham       }
2314e14dc268SJim Ingham     }
23158f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
23168f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2317cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23188f3be7a3SJonas Devlieghere                                                      m_options.m_append);
231901f16664SJim Ingham     if (!error.Success()) {
232001f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
232101f16664SJim Ingham                                    error.AsCString());
232201f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2323e14dc268SJim Ingham     }
2324e14dc268SJim Ingham     return result.Succeeded();
2325e14dc268SJim Ingham   }
2326e14dc268SJim Ingham 
2327e14dc268SJim Ingham private:
2328e14dc268SJim Ingham   CommandOptions m_options;
2329e14dc268SJim Ingham };
2330e14dc268SJim Ingham 
233130fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2332ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
233330fdc8d8SChris Lattner 
2334b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2335b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2336b9c1b51eSKate Stone     : CommandObjectMultiword(
2337b9c1b51eSKate Stone           interpreter, "breakpoint",
23387428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2339b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2340b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2341b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2342b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2343b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2344b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2345b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2346b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2347b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2348b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2349b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2350b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2351b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2352b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2353b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2354b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2355b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2356b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2357b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2358e14dc268SJim Ingham   CommandObjectSP write_command_object(
2359e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2360e14dc268SJim Ingham   CommandObjectSP read_command_object(
2361e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
236230fdc8d8SChris Lattner 
2363b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
236430fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
236530fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2366b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2367b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2368ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2369b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2370b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
23715e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2372e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2373e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
237430fdc8d8SChris Lattner 
237523f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
237623f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
237723f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
237823f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
237923f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
238023f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
238123f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
238223f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
23835e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2384e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2385e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
238630fdc8d8SChris Lattner }
238730fdc8d8SChris Lattner 
23889e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
238930fdc8d8SChris Lattner 
2390a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2391a925974bSAdrian Prantl     Args &args, Target *target, bool allow_locations,
2392a925974bSAdrian Prantl     CommandReturnObject &result, BreakpointIDList *valid_ids,
2393a925974bSAdrian Prantl     BreakpointName::Permissions ::PermissionKinds purpose) {
239430fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2395b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2396b9c1b51eSKate Stone   //                                  canonical representation
2397b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2398b9c1b51eSKate Stone   //                                  representing a range (in which case there
2399b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2400b9c1b51eSKate Stone   //                                      after of one of the first two types.
24015e09c8c3SJim Ingham   //                                  4). A breakpoint name
2402b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2403b9c1b51eSKate Stone   // one.)
240430fdc8d8SChris Lattner 
240530fdc8d8SChris Lattner   Args temp_args;
240630fdc8d8SChris Lattner 
240711eb9c64SZachary Turner   if (args.empty()) {
2408b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2409b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2410b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
241136f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2412b9c1b51eSKate Stone     } else {
2413b9c1b51eSKate Stone       result.AppendError(
2414b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
241536f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
241636f3b369SJim Ingham     }
241736f3b369SJim Ingham     return;
241836f3b369SJim Ingham   }
241936f3b369SJim Ingham 
2420b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
242105097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
242205097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
242305097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
242405097246SAdrian Prantl   // into TEMP_ARGS.
242530fdc8d8SChris Lattner 
2426b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2427b842f2ecSJim Ingham                                            purpose, result, temp_args);
242830fdc8d8SChris Lattner 
2429b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2430b9c1b51eSKate Stone   // BreakpointIDList:
243130fdc8d8SChris Lattner 
243216662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
243330fdc8d8SChris Lattner 
243405097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
243505097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
243630fdc8d8SChris Lattner 
2437b9c1b51eSKate Stone   if (result.Succeeded()) {
2438b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
243905097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
244005097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
244130fdc8d8SChris Lattner 
2442c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2443b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
244430fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2445b9c1b51eSKate Stone       Breakpoint *breakpoint =
2446b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2447b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2448c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2449b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
245030fdc8d8SChris Lattner           StreamString id_str;
2451b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2452b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2453c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2454b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2455b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
245630fdc8d8SChris Lattner               id_str.GetData());
245730fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
245830fdc8d8SChris Lattner         }
2459b9c1b51eSKate Stone       } else {
2460c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2461b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2462b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
24637428a18cSKate Stone             cur_bp_id.GetBreakpointID());
246430fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
246530fdc8d8SChris Lattner       }
246630fdc8d8SChris Lattner     }
246730fdc8d8SChris Lattner   }
246830fdc8d8SChris Lattner }
2469