130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
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/CommandCompletions.h"
16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
19943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
2032abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.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/Thread.h"
281b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
29bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
30bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3130fdc8d8SChris Lattner 
32796ac80bSJonas Devlieghere #include <memory>
33796ac80bSJonas Devlieghere #include <vector>
34796ac80bSJonas Devlieghere 
3530fdc8d8SChris Lattner using namespace lldb;
3630fdc8d8SChris Lattner using namespace lldb_private;
3730fdc8d8SChris Lattner 
38b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
39b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
4030fdc8d8SChris Lattner   s->IndentMore();
4130fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4230fdc8d8SChris Lattner   s->IndentLess();
4330fdc8d8SChris Lattner   s->EOL();
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner 
46b842f2ecSJim Ingham // Modifiable Breakpoint Options
47b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
48f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
49f94668e3SRaphael Isemann #include "CommandOptions.inc"
50bd68a052SRaphael Isemann 
51b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup
52b842f2ecSJim Ingham {
53b842f2ecSJim Ingham public:
54b842f2ecSJim Ingham   BreakpointOptionGroup() :
55b842f2ecSJim Ingham           OptionGroup(),
56b842f2ecSJim Ingham           m_bp_opts(false) {}
57b842f2ecSJim Ingham 
58b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
59b842f2ecSJim Ingham 
60b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
61b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
62b842f2ecSJim Ingham   }
63b842f2ecSJim Ingham 
64b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
65b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
66b842f2ecSJim Ingham     Status error;
67b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
68b842f2ecSJim Ingham 
69b842f2ecSJim Ingham     switch (short_option) {
70b842f2ecSJim Ingham     case 'c':
7105097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
7205097246SAdrian Prantl       // to say it was passed in.
73b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
74b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
75b842f2ecSJim Ingham       break;
76b842f2ecSJim Ingham     case 'C':
77b842f2ecSJim Ingham       m_commands.push_back(option_arg);
78b842f2ecSJim Ingham       break;
79b842f2ecSJim Ingham     case 'd':
80b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
81b842f2ecSJim Ingham       break;
82b842f2ecSJim Ingham     case 'e':
83b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
84b842f2ecSJim Ingham       break;
85b842f2ecSJim Ingham     case 'G': {
86b842f2ecSJim Ingham       bool value, success;
8747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
88b842f2ecSJim Ingham       if (success) {
89b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
90b842f2ecSJim Ingham       } else
91b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
92b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
93b842f2ecSJim Ingham             option_arg.str().c_str());
94b842f2ecSJim Ingham     }
95b842f2ecSJim Ingham     break;
96b842f2ecSJim Ingham     case 'i':
97b842f2ecSJim Ingham     {
98b842f2ecSJim Ingham       uint32_t ignore_count;
99b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
100b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
101b842f2ecSJim Ingham                                        option_arg.str().c_str());
102b842f2ecSJim Ingham       else
103b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
104b842f2ecSJim Ingham     }
105b842f2ecSJim Ingham     break;
106b842f2ecSJim Ingham     case 'o': {
107b842f2ecSJim Ingham       bool value, success;
10847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
109b842f2ecSJim Ingham       if (success) {
110b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
111b842f2ecSJim Ingham       } else
112b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
113b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
114b842f2ecSJim Ingham             option_arg.str().c_str());
115b842f2ecSJim Ingham     } break;
116b842f2ecSJim Ingham     case 't':
117b842f2ecSJim Ingham     {
118b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
119b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
120b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
121b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
122b842f2ecSJim Ingham                                          option_arg.str().c_str());
123b842f2ecSJim Ingham       }
124b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
125b842f2ecSJim Ingham     }
126b842f2ecSJim Ingham     break;
127b842f2ecSJim Ingham     case 'T':
128b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
129b842f2ecSJim Ingham       break;
130b842f2ecSJim Ingham     case 'q':
131b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
132b842f2ecSJim Ingham       break;
133b842f2ecSJim Ingham     case 'x':
134b842f2ecSJim Ingham     {
135b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
136b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
137b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
138b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
139b842f2ecSJim Ingham                                          option_arg.str().c_str());
140b842f2ecSJim Ingham       }
141b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
142b842f2ecSJim Ingham     }
143b842f2ecSJim Ingham     break;
144b842f2ecSJim Ingham     default:
14536162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
146b842f2ecSJim Ingham     }
147b842f2ecSJim Ingham 
148b842f2ecSJim Ingham     return error;
149b842f2ecSJim Ingham   }
150b842f2ecSJim Ingham 
151b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
152b842f2ecSJim Ingham     m_bp_opts.Clear();
153b842f2ecSJim Ingham     m_commands.clear();
154b842f2ecSJim Ingham   }
155b842f2ecSJim Ingham 
156b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
157b842f2ecSJim Ingham     if (!m_commands.empty())
158b842f2ecSJim Ingham     {
159b842f2ecSJim Ingham       if (!m_commands.empty())
160b842f2ecSJim Ingham       {
161a8f3ae7cSJonas Devlieghere           auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
162b842f2ecSJim Ingham 
163b842f2ecSJim Ingham           for (std::string &str : m_commands)
164b842f2ecSJim Ingham             cmd_data->user_source.AppendString(str);
165b842f2ecSJim Ingham 
166b842f2ecSJim Ingham           cmd_data->stop_on_error = true;
167b842f2ecSJim Ingham           m_bp_opts.SetCommandDataCallback(cmd_data);
168b842f2ecSJim Ingham       }
169b842f2ecSJim Ingham     }
170b842f2ecSJim Ingham     return Status();
171b842f2ecSJim Ingham   }
172b842f2ecSJim Ingham 
173b842f2ecSJim Ingham   const BreakpointOptions &GetBreakpointOptions()
174b842f2ecSJim Ingham   {
175b842f2ecSJim Ingham     return m_bp_opts;
176b842f2ecSJim Ingham   }
177b842f2ecSJim Ingham 
178b842f2ecSJim Ingham   std::vector<std::string> m_commands;
179b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
180b842f2ecSJim Ingham 
181b842f2ecSJim Ingham };
182bd68a052SRaphael Isemann 
183f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
184f94668e3SRaphael Isemann #include "CommandOptions.inc"
185b842f2ecSJim Ingham 
186b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup
187b842f2ecSJim Ingham {
188b842f2ecSJim Ingham public:
189b842f2ecSJim Ingham   BreakpointDummyOptionGroup() :
190b842f2ecSJim Ingham           OptionGroup() {}
191b842f2ecSJim Ingham 
192b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
193b842f2ecSJim Ingham 
194b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
195b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
196b842f2ecSJim Ingham   }
197b842f2ecSJim Ingham 
198b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
199b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
200b842f2ecSJim Ingham     Status error;
201b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
202b842f2ecSJim Ingham 
203b842f2ecSJim Ingham     switch (short_option) {
204b842f2ecSJim Ingham       case 'D':
205b842f2ecSJim Ingham         m_use_dummy = true;
206b842f2ecSJim Ingham         break;
207b842f2ecSJim Ingham     default:
20836162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
209b842f2ecSJim Ingham     }
210b842f2ecSJim Ingham 
211b842f2ecSJim Ingham     return error;
212b842f2ecSJim Ingham   }
213b842f2ecSJim Ingham 
214b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
215b842f2ecSJim Ingham     m_use_dummy = false;
216b842f2ecSJim Ingham   }
217b842f2ecSJim Ingham 
218b842f2ecSJim Ingham   bool m_use_dummy;
219b842f2ecSJim Ingham 
220b842f2ecSJim Ingham };
221b842f2ecSJim Ingham 
222f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
223f94668e3SRaphael Isemann #include "CommandOptions.inc"
2241f0f5b5bSZachary Turner 
2255a988416SJim Ingham // CommandObjectBreakpointSet
22630fdc8d8SChris Lattner 
227b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2285a988416SJim Ingham public:
229efe8e7e3SFangrui Song   enum BreakpointSetType {
2305a988416SJim Ingham     eSetTypeInvalid,
2315a988416SJim Ingham     eSetTypeFileAndLine,
2325a988416SJim Ingham     eSetTypeAddress,
2335a988416SJim Ingham     eSetTypeFunctionName,
2345a988416SJim Ingham     eSetTypeFunctionRegexp,
2355a988416SJim Ingham     eSetTypeSourceRegexp,
2363815e702SJim Ingham     eSetTypeException,
2373815e702SJim Ingham     eSetTypeScripted,
238efe8e7e3SFangrui Song   };
2395a988416SJim Ingham 
240b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
241b9c1b51eSKate Stone       : CommandObjectParsed(
242b9c1b51eSKate Stone             interpreter, "breakpoint set",
2435a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2445a988416SJim Ingham             "breakpoint set <cmd-options>"),
245*f6a2086dSSam McCall         m_bp_opts(), m_python_class_options("scripted breakpoint", 'P'),
246*f6a2086dSSam McCall         m_options() {
247b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
248943a2481SJim Ingham     m_all_options.Append(&m_python_class_options, LLDB_OPT_SET_1,
249943a2481SJim Ingham                          LLDB_OPT_SET_11);
250b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
251b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
252b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
253*f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
254b842f2ecSJim Ingham     m_all_options.Append(&m_options);
255b842f2ecSJim Ingham     m_all_options.Finalize();
256b842f2ecSJim Ingham   }
2575a988416SJim Ingham 
2589e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2595a988416SJim Ingham 
260b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2615a988416SJim Ingham 
262b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2635a988416SJim Ingham   public:
264b9c1b51eSKate Stone     CommandOptions()
265b842f2ecSJim Ingham         : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
266b9c1b51eSKate Stone           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
267b9c1b51eSKate Stone           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
268b9c1b51eSKate Stone           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
269a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
27023b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
271b842f2ecSJim Ingham           m_skip_prologue(eLazyBoolCalculate),
272b9c1b51eSKate Stone           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
27330fdc8d8SChris Lattner 
2749e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
27587df91b8SJim Ingham 
27697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
277b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
27897206d57SZachary Turner       Status error;
279b842f2ecSJim Ingham       const int short_option = g_breakpoint_set_options[option_idx].short_option;
28030fdc8d8SChris Lattner 
281b9c1b51eSKate Stone       switch (short_option) {
282b9c1b51eSKate Stone       case 'a': {
28347cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
284e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
285b9c1b51eSKate Stone       } break;
28630fdc8d8SChris Lattner 
287e732052fSJim Ingham       case 'A':
288e732052fSJim Ingham         m_all_files = true;
289e732052fSJim Ingham         break;
290e732052fSJim Ingham 
291ca36cd16SJim Ingham       case 'b':
292ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
293ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
294ca36cd16SJim Ingham         break;
295ca36cd16SJim Ingham 
296fe11483bSZachary Turner       case 'C':
297fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
298b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
299fe11483bSZachary Turner                                          option_arg.str().c_str());
30030fdc8d8SChris Lattner         break;
3019e85e5a8SEugene Zelenko 
302b9c1b51eSKate Stone       case 'E': {
303fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
304fab10e89SJim Ingham 
305b9c1b51eSKate Stone         switch (language) {
306fab10e89SJim Ingham         case eLanguageTypeC89:
307fab10e89SJim Ingham         case eLanguageTypeC:
308fab10e89SJim Ingham         case eLanguageTypeC99:
3091d0089faSBruce Mitchener         case eLanguageTypeC11:
310a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
311fab10e89SJim Ingham           break;
312fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
3131d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
3141d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
3152ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
316a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
317fab10e89SJim Ingham           break;
318fab10e89SJim Ingham         case eLanguageTypeObjC:
319a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
320fab10e89SJim Ingham           break;
321fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
322b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
323b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
324fab10e89SJim Ingham           break;
325fab10e89SJim Ingham         case eLanguageTypeUnknown:
326b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
327b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
328fe11483bSZachary Turner               option_arg.str().c_str());
329fab10e89SJim Ingham           break;
330fab10e89SJim Ingham         default:
331b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
332b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
333fe11483bSZachary Turner               option_arg.str().c_str());
334fab10e89SJim Ingham         }
335b9c1b51eSKate Stone       } break;
336ca36cd16SJim Ingham 
337ca36cd16SJim Ingham       case 'f':
3388f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
339fab10e89SJim Ingham         break;
340ca36cd16SJim Ingham 
341ca36cd16SJim Ingham       case 'F':
342ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
343ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
344ca36cd16SJim Ingham         break;
345ca36cd16SJim Ingham 
346b9c1b51eSKate Stone       case 'h': {
347fab10e89SJim Ingham         bool success;
34847cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
349fab10e89SJim Ingham         if (!success)
350b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
351fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
352fe11483bSZachary Turner               option_arg.str().c_str());
353b9c1b51eSKate Stone       } break;
354eb023e75SGreg Clayton 
355eb023e75SGreg Clayton       case 'H':
356eb023e75SGreg Clayton         m_hardware = true;
357eb023e75SGreg Clayton         break;
358eb023e75SGreg Clayton 
359b9c1b51eSKate Stone       case 'K': {
360a8558b62SJim Ingham         bool success;
361a8558b62SJim Ingham         bool value;
36247cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
363a8558b62SJim Ingham         if (value)
364a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
365a8558b62SJim Ingham         else
366a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
367a8558b62SJim Ingham 
368a8558b62SJim Ingham         if (!success)
369b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
370b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
371fe11483bSZachary Turner               option_arg.str().c_str());
372b9c1b51eSKate Stone       } break;
373ca36cd16SJim Ingham 
374fe11483bSZachary Turner       case 'l':
375fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
376b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
377fe11483bSZachary Turner                                          option_arg.str().c_str());
378ca36cd16SJim Ingham         break;
379055ad9beSIlia K 
38023b1decbSDawn Perchik       case 'L':
381fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
38223b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
383b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
384fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
385fe11483bSZachary Turner               option_arg.str().c_str());
38623b1decbSDawn Perchik         break;
38723b1decbSDawn Perchik 
388b9c1b51eSKate Stone       case 'm': {
389055ad9beSIlia K         bool success;
390055ad9beSIlia K         bool value;
39147cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
392055ad9beSIlia K         if (value)
393055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
394055ad9beSIlia K         else
395055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
396055ad9beSIlia K 
397055ad9beSIlia K         if (!success)
398b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
399b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
400fe11483bSZachary Turner               option_arg.str().c_str());
401055ad9beSIlia K         break;
402055ad9beSIlia K       }
403055ad9beSIlia K 
404ca36cd16SJim Ingham       case 'M':
405ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
406ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
407ca36cd16SJim Ingham         break;
408ca36cd16SJim Ingham 
409ca36cd16SJim Ingham       case 'n':
410ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
411ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
412ca36cd16SJim Ingham         break;
413ca36cd16SJim Ingham 
4146fa7681bSZachary Turner       case 'N': {
415fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
4165e09c8c3SJim Ingham           m_breakpoint_names.push_back(option_arg);
417ff9a91eaSJim Ingham         else
418ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
419fe11483bSZachary Turner                                          option_arg.str().c_str());
4205e09c8c3SJim Ingham         break;
4216fa7681bSZachary Turner       }
4225e09c8c3SJim Ingham 
423b9c1b51eSKate Stone       case 'R': {
4242411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
42547cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
42647cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4272411167fSJim Ingham         if (error.Success())
4282411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
429b9c1b51eSKate Stone       } break;
4302411167fSJim Ingham 
431a72b31c7SJim Ingham       case 'O':
432fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
433fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
434a72b31c7SJim Ingham         break;
435a72b31c7SJim Ingham 
436ca36cd16SJim Ingham       case 'p':
437ca36cd16SJim Ingham         m_source_text_regexp.assign(option_arg);
438ca36cd16SJim Ingham         break;
439ca36cd16SJim Ingham 
440ca36cd16SJim Ingham       case 'r':
441ca36cd16SJim Ingham         m_func_regexp.assign(option_arg);
442ca36cd16SJim Ingham         break;
443ca36cd16SJim Ingham 
444ca36cd16SJim Ingham       case 's':
4458f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
446ca36cd16SJim Ingham         break;
447ca36cd16SJim Ingham 
448ca36cd16SJim Ingham       case 'S':
449ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
450ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
451ca36cd16SJim Ingham         break;
452ca36cd16SJim Ingham 
453b9c1b51eSKate Stone       case 'w': {
454ca36cd16SJim Ingham         bool success;
45547cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
456ca36cd16SJim Ingham         if (!success)
457b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
458fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
459fe11483bSZachary Turner               option_arg.str().c_str());
460b9c1b51eSKate Stone       } break;
461ca36cd16SJim Ingham 
46276bb8d67SJim Ingham       case 'X':
46376bb8d67SJim Ingham         m_source_regex_func_names.insert(option_arg);
46476bb8d67SJim Ingham         break;
46576bb8d67SJim Ingham 
46630fdc8d8SChris Lattner       default:
46736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
46830fdc8d8SChris Lattner       }
46930fdc8d8SChris Lattner 
47030fdc8d8SChris Lattner       return error;
47130fdc8d8SChris Lattner     }
4729e85e5a8SEugene Zelenko 
473b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
47487df91b8SJim Ingham       m_filenames.Clear();
47530fdc8d8SChris Lattner       m_line_num = 0;
47630fdc8d8SChris Lattner       m_column = 0;
477fab10e89SJim Ingham       m_func_names.clear();
4781f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
47930fdc8d8SChris Lattner       m_func_regexp.clear();
4801f746071SGreg Clayton       m_source_text_regexp.clear();
48187df91b8SJim Ingham       m_modules.Clear();
4821f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4832411167fSJim Ingham       m_offset_addr = 0;
484fab10e89SJim Ingham       m_catch_bp = false;
485fab10e89SJim Ingham       m_throw_bp = true;
486eb023e75SGreg Clayton       m_hardware = false;
487a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
48823b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
489a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4905e09c8c3SJim Ingham       m_breakpoint_names.clear();
491e732052fSJim Ingham       m_all_files = false;
492a72b31c7SJim Ingham       m_exception_extra_args.Clear();
493055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
49476bb8d67SJim Ingham       m_source_regex_func_names.clear();
4953815e702SJim Ingham       m_current_key.clear();
49630fdc8d8SChris Lattner     }
49730fdc8d8SChris Lattner 
4981f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
49970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
5001f0f5b5bSZachary Turner     }
50130fdc8d8SChris Lattner 
5025a988416SJim Ingham     // Instance variables to hold the values for command options.
503969795f1SJim Ingham 
5045a988416SJim Ingham     std::string m_condition;
5055a988416SJim Ingham     FileSpecList m_filenames;
5065a988416SJim Ingham     uint32_t m_line_num;
5075a988416SJim Ingham     uint32_t m_column;
5085a988416SJim Ingham     std::vector<std::string> m_func_names;
5095e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
510117b1fa1SZachary Turner     lldb::FunctionNameType m_func_name_type_mask;
5115a988416SJim Ingham     std::string m_func_regexp;
5125a988416SJim Ingham     std::string m_source_text_regexp;
5135a988416SJim Ingham     FileSpecList m_modules;
5145a988416SJim Ingham     lldb::addr_t m_load_addr;
5152411167fSJim Ingham     lldb::addr_t m_offset_addr;
5165a988416SJim Ingham     bool m_catch_bp;
5175a988416SJim Ingham     bool m_throw_bp;
518eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
519a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
52023b1decbSDawn Perchik     lldb::LanguageType m_language;
5215a988416SJim Ingham     LazyBool m_skip_prologue;
522e732052fSJim Ingham     bool m_all_files;
523a72b31c7SJim Ingham     Args m_exception_extra_args;
524055ad9beSIlia K     LazyBool m_move_to_nearest_code;
52576bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5263815e702SJim Ingham     std::string m_current_key;
5275a988416SJim Ingham   };
5285a988416SJim Ingham 
5295a988416SJim Ingham protected:
530b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
531cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
53230fdc8d8SChris Lattner 
53330fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
53430fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
53530fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
53630fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
537b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
538b9c1b51eSKate Stone     //   expression)
539b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
540b9c1b51eSKate Stone     //   to source text)
541b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
542b9c1b51eSKate Stone     //   given language.)
54330fdc8d8SChris Lattner 
54430fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
54530fdc8d8SChris Lattner 
546943a2481SJim Ingham     if (!m_python_class_options.GetClassName().empty())
5473815e702SJim Ingham       break_type = eSetTypeScripted;
5483815e702SJim Ingham     else if (m_options.m_line_num != 0)
54930fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
55030fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
55130fdc8d8SChris Lattner       break_type = eSetTypeAddress;
552fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
55330fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
55430fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
55530fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
556969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
557969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
558a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
559fab10e89SJim Ingham       break_type = eSetTypeException;
56030fdc8d8SChris Lattner 
561b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
562274060b6SGreg Clayton     FileSpec module_spec;
563a8558b62SJim Ingham     const bool internal = false;
564a8558b62SJim Ingham 
565b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
566b9c1b51eSKate Stone     // that off.
567b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
568b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5692411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5702411167fSJim Ingham 
571b9c1b51eSKate Stone     switch (break_type) {
57230fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
57330fdc8d8SChris Lattner     {
57430fdc8d8SChris Lattner       FileSpec file;
575c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
576b9c1b51eSKate Stone       if (num_files == 0) {
577b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
57887df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
57987df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
58087df91b8SJim Ingham           return false;
58187df91b8SJim Ingham         }
582b9c1b51eSKate Stone       } else if (num_files > 1) {
583b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
584b9c1b51eSKate Stone                            "line breakpoints.");
58587df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
58687df91b8SJim Ingham         return false;
587b9c1b51eSKate Stone       } else
58887df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
58930fdc8d8SChris Lattner 
5901f746071SGreg Clayton       // Only check for inline functions if
5911f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5921f746071SGreg Clayton 
593cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
594cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
595cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
596cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
597b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
598b9c1b51eSKate Stone     } break;
5996eee5aa0SGreg Clayton 
60030fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
601055a08a4SJim Ingham     {
602b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
603b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
604b842f2ecSJim Ingham       //  will track the load location of the library.
605055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
606b9c1b51eSKate Stone       if (num_modules_specified == 1) {
607b9c1b51eSKate Stone         const FileSpec *file_spec =
608b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
609cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
610cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
611b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
612cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
613b842f2ecSJim Ingham                                         m_options.m_hardware);
614b9c1b51eSKate Stone       } else {
615b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
616b9c1b51eSKate Stone                            "address breakpoints.");
617055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
618055a08a4SJim Ingham         return false;
619055a08a4SJim Ingham       }
62030fdc8d8SChris Lattner       break;
621055a08a4SJim Ingham     }
62230fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6230c5cd90dSGreg Clayton     {
624117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6250c5cd90dSGreg Clayton 
6260c5cd90dSGreg Clayton       if (name_type_mask == 0)
627e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6280c5cd90dSGreg Clayton 
629cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
630cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
631cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
632cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
633b842f2ecSJim Ingham           m_options.m_hardware);
634b9c1b51eSKate Stone     } break;
6350c5cd90dSGreg Clayton 
636b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
637b9c1b51eSKate Stone                                  // name
63830fdc8d8SChris Lattner       {
63995eae423SZachary Turner         RegularExpression regexp(m_options.m_func_regexp);
6403af3f1e8SJonas Devlieghere         if (llvm::Error err = regexp.GetError()) {
641b9c1b51eSKate Stone           result.AppendErrorWithFormat(
642b9c1b51eSKate Stone               "Function name regular expression could not be compiled: \"%s\"",
6433af3f1e8SJonas Devlieghere               llvm::toString(std::move(err)).c_str());
64430fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
645969795f1SJim Ingham           return false;
64630fdc8d8SChris Lattner         }
64787df91b8SJim Ingham 
648cb2380c9SRaphael Isemann         bp_sp = target.CreateFuncRegexBreakpoint(
6495aa1d819SJan Kratochvil             &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
650cb2380c9SRaphael Isemann             m_options.m_language, m_options.m_skip_prologue, internal,
651b842f2ecSJim Ingham             m_options.m_hardware);
652e14dc268SJim Ingham       }
653e14dc268SJim Ingham       break;
654969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
655969795f1SJim Ingham     {
656c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
65787df91b8SJim Ingham 
658b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
659969795f1SJim Ingham         FileSpec file;
660b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
661b9c1b51eSKate Stone           result.AppendError(
662b9c1b51eSKate Stone               "No files provided and could not find default file.");
66387df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
66487df91b8SJim Ingham           return false;
665b9c1b51eSKate Stone         } else {
66687df91b8SJim Ingham           m_options.m_filenames.Append(file);
66787df91b8SJim Ingham         }
66887df91b8SJim Ingham       }
6690c5cd90dSGreg Clayton 
67095eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6713af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
672b9c1b51eSKate Stone         result.AppendErrorWithFormat(
673b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6743af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
675969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
676969795f1SJim Ingham         return false;
677969795f1SJim Ingham       }
678cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
679cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6805aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
681cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
682b9c1b51eSKate Stone     } break;
683b9c1b51eSKate Stone     case eSetTypeException: {
68497206d57SZachary Turner       Status precond_error;
685cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
686cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
687cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
688b842f2ecSJim Ingham           &precond_error);
689b9c1b51eSKate Stone       if (precond_error.Fail()) {
690b9c1b51eSKate Stone         result.AppendErrorWithFormat(
691b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
692a72b31c7SJim Ingham             precond_error.AsCString());
693cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
694a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
695a72b31c7SJim Ingham         return false;
696a72b31c7SJim Ingham       }
697b9c1b51eSKate Stone     } break;
6983815e702SJim Ingham     case eSetTypeScripted: {
6993815e702SJim Ingham 
7003815e702SJim Ingham       Status error;
701cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
702943a2481SJim Ingham           m_python_class_options.GetClassName().c_str(), &(m_options.m_modules),
703cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
704943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
7053815e702SJim Ingham       if (error.Fail()) {
7063815e702SJim Ingham         result.AppendErrorWithFormat(
7073815e702SJim Ingham             "Error setting extra exception arguments: %s",
7083815e702SJim Ingham             error.AsCString());
709cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7103815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
7113815e702SJim Ingham         return false;
7123815e702SJim Ingham       }
7133815e702SJim Ingham     } break;
71430fdc8d8SChris Lattner     default:
71530fdc8d8SChris Lattner       break;
71630fdc8d8SChris Lattner     }
71730fdc8d8SChris Lattner 
7181b54c88cSJim Ingham     // Now set the various options that were passed in:
719b842f2ecSJim Ingham     if (bp_sp) {
720b842f2ecSJim Ingham       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
721ca36cd16SJim Ingham 
722b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
72397206d57SZachary Turner         Status name_error;
724ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
725cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
726ff9a91eaSJim Ingham           if (name_error.Fail()) {
727ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
728ff9a91eaSJim Ingham                                          name.c_str());
729cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
730ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
731ff9a91eaSJim Ingham             return false;
732ff9a91eaSJim Ingham           }
733ff9a91eaSJim Ingham         }
7345e09c8c3SJim Ingham       }
7351b54c88cSJim Ingham     }
7361b54c88cSJim Ingham 
737b842f2ecSJim Ingham     if (bp_sp) {
73885e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7391391cc7dSJim Ingham       const bool show_locations = false;
740b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
741b9c1b51eSKate Stone                          show_locations);
742cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
743b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
744b9c1b51eSKate Stone                              "into future targets.\n");
745b9c1b51eSKate Stone       else {
74605097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
74705097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
74805097246SAdrian Prantl         // set the breakpoint till we run.
749b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
750b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
751b9c1b51eSKate Stone                                "actual locations.\n");
7524aeb1989SJim Ingham         }
7534aeb1989SJim Ingham       }
75430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
755b842f2ecSJim Ingham     } else if (!bp_sp) {
75630fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
75730fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
75830fdc8d8SChris Lattner     }
75930fdc8d8SChris Lattner 
76030fdc8d8SChris Lattner     return result.Succeeded();
76130fdc8d8SChris Lattner   }
76230fdc8d8SChris Lattner 
7635a988416SJim Ingham private:
764cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
765b9c1b51eSKate Stone                       CommandReturnObject &result) {
7665a988416SJim Ingham     uint32_t default_line;
76705097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
76805097246SAdrian Prantl     // frame's file.
769cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
770b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
771b9c1b51eSKate Stone       if (cur_frame == nullptr) {
772b9c1b51eSKate Stone         result.AppendError(
773b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7745a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7755a988416SJim Ingham         return false;
776b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
777b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
778b9c1b51eSKate Stone                            "file, it has no debug info.");
7795a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7805a988416SJim Ingham         return false;
781b9c1b51eSKate Stone       } else {
782b9c1b51eSKate Stone         const SymbolContext &sc =
783b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
784b9c1b51eSKate Stone         if (sc.line_entry.file) {
7855a988416SJim Ingham           file = sc.line_entry.file;
786b9c1b51eSKate Stone         } else {
787b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
788b9c1b51eSKate Stone                              "use as the default file.");
7895a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
7905a988416SJim Ingham           return false;
7915a988416SJim Ingham         }
7925a988416SJim Ingham       }
7935a988416SJim Ingham     }
7945a988416SJim Ingham     return true;
7955a988416SJim Ingham   }
7965a988416SJim Ingham 
797b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
798b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
799943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
8005a988416SJim Ingham   CommandOptions m_options;
801b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
8025a988416SJim Ingham };
8039e85e5a8SEugene Zelenko 
8045a988416SJim Ingham // CommandObjectBreakpointModify
8055a988416SJim Ingham #pragma mark Modify
8065a988416SJim Ingham 
807b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8085a988416SJim Ingham public:
809b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
810b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
811b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
812b9c1b51eSKate Stone                             "breakpoints in the executable.  "
813b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
814b9c1b51eSKate Stone                             "created breakpoint.  "
815b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
816b9c1b51eSKate Stone                             "empty argument clears the modification.",
8179e85e5a8SEugene Zelenko                             nullptr),
818b9c1b51eSKate Stone         m_options() {
8195a988416SJim Ingham     CommandArgumentEntry arg;
820b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
821b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
822b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
823b9c1b51eSKate Stone     // arguments vector.
8245a988416SJim Ingham     m_arguments.push_back(arg);
825b842f2ecSJim Ingham 
826b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
827b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
828b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
829b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
830b842f2ecSJim Ingham     m_options.Finalize();
8315a988416SJim Ingham   }
8325a988416SJim Ingham 
8339e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8345a988416SJim Ingham 
835b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8365a988416SJim Ingham 
8375a988416SJim Ingham protected:
838b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
839cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8405a988416SJim Ingham 
841bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
842cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8435a988416SJim Ingham 
8445a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8455a988416SJim Ingham 
846b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
847cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
848b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8495a988416SJim Ingham 
850b9c1b51eSKate Stone     if (result.Succeeded()) {
8515a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
852b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8535a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8545a988416SJim Ingham 
855b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
856b9c1b51eSKate Stone           Breakpoint *bp =
857cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
858b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
859b9c1b51eSKate Stone             BreakpointLocation *location =
860b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
861b842f2ecSJim Ingham             if (location)
862b842f2ecSJim Ingham               location->GetLocationOptions()
863b842f2ecSJim Ingham                   ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
864b9c1b51eSKate Stone           } else {
865b842f2ecSJim Ingham             bp->GetOptions()
866b842f2ecSJim Ingham                 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
8675a988416SJim Ingham           }
8685a988416SJim Ingham         }
8695a988416SJim Ingham       }
8705a988416SJim Ingham     }
8715a988416SJim Ingham 
8725a988416SJim Ingham     return result.Succeeded();
8735a988416SJim Ingham   }
8745a988416SJim Ingham 
8755a988416SJim Ingham private:
876b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
877b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
878b842f2ecSJim Ingham   OptionGroupOptions m_options;
8795a988416SJim Ingham };
8805a988416SJim Ingham 
8815a988416SJim Ingham // CommandObjectBreakpointEnable
8825a988416SJim Ingham #pragma mark Enable
8835a988416SJim Ingham 
884b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8855a988416SJim Ingham public:
886b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
887b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
888b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
889b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
890b9c1b51eSKate Stone                             nullptr) {
8915a988416SJim Ingham     CommandArgumentEntry arg;
892b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
893b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
894b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
895b9c1b51eSKate Stone     // arguments vector.
8965a988416SJim Ingham     m_arguments.push_back(arg);
8975a988416SJim Ingham   }
8985a988416SJim Ingham 
8999e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9005a988416SJim Ingham 
9015a988416SJim Ingham protected:
902b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
903cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9045a988416SJim Ingham 
905bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
906cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9075a988416SJim Ingham 
908cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9095a988416SJim Ingham 
9105a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9115a988416SJim Ingham 
912b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9135a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9145a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9155a988416SJim Ingham       return false;
9165a988416SJim Ingham     }
9175a988416SJim Ingham 
91811eb9c64SZachary Turner     if (command.empty()) {
9195a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
920cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
921b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
922b9c1b51eSKate Stone                                      " breakpoints)\n",
923b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9245a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
925b9c1b51eSKate Stone     } else {
9265a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9275a988416SJim Ingham       BreakpointIDList valid_bp_ids;
928b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
929cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
930b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9315a988416SJim Ingham 
932b9c1b51eSKate Stone       if (result.Succeeded()) {
9335a988416SJim Ingham         int enable_count = 0;
9345a988416SJim Ingham         int loc_count = 0;
9355a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
936b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9375a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9385a988416SJim Ingham 
939b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
940b9c1b51eSKate Stone             Breakpoint *breakpoint =
941cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
942b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
943b9c1b51eSKate Stone               BreakpointLocation *location =
944b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
945b9c1b51eSKate Stone               if (location) {
9465a988416SJim Ingham                 location->SetEnabled(true);
9475a988416SJim Ingham                 ++loc_count;
9485a988416SJim Ingham               }
949b9c1b51eSKate Stone             } else {
9505a988416SJim Ingham               breakpoint->SetEnabled(true);
9515a988416SJim Ingham               ++enable_count;
9525a988416SJim Ingham             }
9535a988416SJim Ingham           }
9545a988416SJim Ingham         }
955b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
956b9c1b51eSKate Stone                                        enable_count + loc_count);
9575a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9585a988416SJim Ingham       }
9595a988416SJim Ingham     }
9605a988416SJim Ingham 
9615a988416SJim Ingham     return result.Succeeded();
9625a988416SJim Ingham   }
9635a988416SJim Ingham };
9645a988416SJim Ingham 
9655a988416SJim Ingham // CommandObjectBreakpointDisable
9665a988416SJim Ingham #pragma mark Disable
9675a988416SJim Ingham 
968b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9695a988416SJim Ingham public:
9707428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
971b9c1b51eSKate Stone       : CommandObjectParsed(
972b9c1b51eSKate Stone             interpreter, "breakpoint disable",
973b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9747428a18cSKate Stone             "them.  If none are specified, disable all "
9757428a18cSKate Stone             "breakpoints.",
976b9c1b51eSKate Stone             nullptr) {
977b9c1b51eSKate Stone     SetHelpLong(
978b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9797428a18cSKate Stone If none are specified, disable all breakpoints."
9807428a18cSKate Stone         R"(
981ea671fbdSKate Stone 
9827428a18cSKate Stone )"
9837428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
9847428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
9857428a18cSKate Stone         R"(
986ea671fbdSKate Stone 
987ea671fbdSKate Stone     (lldb) break disable 1
988ea671fbdSKate Stone     (lldb) break enable 1.1
989ea671fbdSKate Stone 
990ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
991ea671fbdSKate Stone 
992ea671fbdSKate Stone     (lldb) break disable 1.*
993ea671fbdSKate Stone     (lldb) break enable 1.1
994ea671fbdSKate Stone 
9957428a18cSKate Stone )"
9967428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
9977428a18cSKate Stone the second re-enables the first location.");
998b0fac509SJim Ingham 
9995a988416SJim Ingham     CommandArgumentEntry arg;
1000b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1001b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1002b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1003b9c1b51eSKate Stone     // arguments vector.
10045a988416SJim Ingham     m_arguments.push_back(arg);
10055a988416SJim Ingham   }
10065a988416SJim Ingham 
10079e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10085a988416SJim Ingham 
10095a988416SJim Ingham protected:
1010b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1011cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1012bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1013cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10145a988416SJim Ingham 
1015cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10165a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10175a988416SJim Ingham 
1018b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10195a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10205a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10215a988416SJim Ingham       return false;
10225a988416SJim Ingham     }
10235a988416SJim Ingham 
102411eb9c64SZachary Turner     if (command.empty()) {
10255a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1026cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1027b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1028b9c1b51eSKate Stone                                      " breakpoints)\n",
1029b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10305a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1031b9c1b51eSKate Stone     } else {
10325a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10335a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10345a988416SJim Ingham 
1035b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1036cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1037b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10385a988416SJim Ingham 
1039b9c1b51eSKate Stone       if (result.Succeeded()) {
10405a988416SJim Ingham         int disable_count = 0;
10415a988416SJim Ingham         int loc_count = 0;
10425a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1043b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10445a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10455a988416SJim Ingham 
1046b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1047b9c1b51eSKate Stone             Breakpoint *breakpoint =
1048cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1049b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1050b9c1b51eSKate Stone               BreakpointLocation *location =
1051b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1052b9c1b51eSKate Stone               if (location) {
10535a988416SJim Ingham                 location->SetEnabled(false);
10545a988416SJim Ingham                 ++loc_count;
10555a988416SJim Ingham               }
1056b9c1b51eSKate Stone             } else {
10575a988416SJim Ingham               breakpoint->SetEnabled(false);
10585a988416SJim Ingham               ++disable_count;
10595a988416SJim Ingham             }
10605a988416SJim Ingham           }
10615a988416SJim Ingham         }
1062b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1063b9c1b51eSKate Stone                                        disable_count + loc_count);
10645a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10655a988416SJim Ingham       }
10665a988416SJim Ingham     }
10675a988416SJim Ingham 
10685a988416SJim Ingham     return result.Succeeded();
10695a988416SJim Ingham   }
10705a988416SJim Ingham };
10715a988416SJim Ingham 
10725a988416SJim Ingham // CommandObjectBreakpointList
10731f0f5b5bSZachary Turner 
10741f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10756f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1076c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10771f0f5b5bSZachary Turner 
10785a988416SJim Ingham #pragma mark List
10795a988416SJim Ingham 
1080b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
10815a988416SJim Ingham public:
1082b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1083b9c1b51eSKate Stone       : CommandObjectParsed(
1084b9c1b51eSKate Stone             interpreter, "breakpoint list",
10855a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
10869e85e5a8SEugene Zelenko             nullptr),
1087b9c1b51eSKate Stone         m_options() {
10885a988416SJim Ingham     CommandArgumentEntry arg;
10895a988416SJim Ingham     CommandArgumentData bp_id_arg;
10905a988416SJim Ingham 
10915a988416SJim Ingham     // Define the first (and only) variant of this arg.
10925a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
10935a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
10945a988416SJim Ingham 
1095b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1096b9c1b51eSKate Stone     // argument entry.
10975a988416SJim Ingham     arg.push_back(bp_id_arg);
10985a988416SJim Ingham 
10995a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11005a988416SJim Ingham     m_arguments.push_back(arg);
11015a988416SJim Ingham   }
11025a988416SJim Ingham 
11039e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11045a988416SJim Ingham 
1105b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11065a988416SJim Ingham 
1107b9c1b51eSKate Stone   class CommandOptions : public Options {
11085a988416SJim Ingham   public:
1109b9c1b51eSKate Stone     CommandOptions()
1110b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
11115a988416SJim Ingham     }
11125a988416SJim Ingham 
11139e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11145a988416SJim Ingham 
111597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1116b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
111797206d57SZachary Turner       Status error;
11183bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11195a988416SJim Ingham 
1120b9c1b51eSKate Stone       switch (short_option) {
11215a988416SJim Ingham       case 'b':
11225a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11235a988416SJim Ingham         break;
112433df7cd3SJim Ingham       case 'D':
112533df7cd3SJim Ingham         m_use_dummy = true;
112633df7cd3SJim Ingham         break;
11275a988416SJim Ingham       case 'f':
11285a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11295a988416SJim Ingham         break;
11305a988416SJim Ingham       case 'v':
11315a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11325a988416SJim Ingham         break;
11335a988416SJim Ingham       case 'i':
11345a988416SJim Ingham         m_internal = true;
11355a988416SJim Ingham         break;
11365a988416SJim Ingham       default:
113736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11385a988416SJim Ingham       }
11395a988416SJim Ingham 
11405a988416SJim Ingham       return error;
11415a988416SJim Ingham     }
11425a988416SJim Ingham 
1143b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11445a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11455a988416SJim Ingham       m_internal = false;
114633df7cd3SJim Ingham       m_use_dummy = false;
11475a988416SJim Ingham     }
11485a988416SJim Ingham 
11491f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
115070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11511f0f5b5bSZachary Turner     }
11525a988416SJim Ingham 
11535a988416SJim Ingham     // Instance variables to hold the values for command options.
11545a988416SJim Ingham 
11555a988416SJim Ingham     lldb::DescriptionLevel m_level;
11565a988416SJim Ingham 
11575a988416SJim Ingham     bool m_internal;
115833df7cd3SJim Ingham     bool m_use_dummy;
11595a988416SJim Ingham   };
11605a988416SJim Ingham 
11615a988416SJim Ingham protected:
1162b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1163cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11645a988416SJim Ingham 
1165b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1166cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1167bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1168cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11695a988416SJim Ingham 
11705a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11715a988416SJim Ingham 
1172b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11735a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11745a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11755a988416SJim Ingham       return true;
11765a988416SJim Ingham     }
11775a988416SJim Ingham 
11785a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
11795a988416SJim Ingham 
118011eb9c64SZachary Turner     if (command.empty()) {
11815a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
11825a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1183b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
11845a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1185b842f2ecSJim Ingham         if (breakpoint->AllowList())
1186b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1187b842f2ecSJim Ingham                                    m_options.m_level);
11885a988416SJim Ingham       }
11895a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1190b9c1b51eSKate Stone     } else {
11915a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
11925a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1193b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1194cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1195b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
11965a988416SJim Ingham 
1197b9c1b51eSKate Stone       if (result.Succeeded()) {
1198b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
11995a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1200b9c1b51eSKate Stone           Breakpoint *breakpoint =
1201cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1202b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1203b9c1b51eSKate Stone                                    m_options.m_level);
12045a988416SJim Ingham         }
12055a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1206b9c1b51eSKate Stone       } else {
12077428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12085a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
12095a988416SJim Ingham       }
12105a988416SJim Ingham     }
12115a988416SJim Ingham 
12125a988416SJim Ingham     return result.Succeeded();
12135a988416SJim Ingham   }
12145a988416SJim Ingham 
12155a988416SJim Ingham private:
12165a988416SJim Ingham   CommandOptions m_options;
12175a988416SJim Ingham };
12185a988416SJim Ingham 
12195a988416SJim Ingham // CommandObjectBreakpointClear
12201f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12211f0f5b5bSZachary Turner 
1222f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1223f94668e3SRaphael Isemann #include "CommandOptions.inc"
12241f0f5b5bSZachary Turner 
12255a988416SJim Ingham #pragma mark Clear
12265a988416SJim Ingham 
1227b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12285a988416SJim Ingham public:
1229efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12305a988416SJim Ingham 
12317428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12327428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1233b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1234b9c1b51eSKate Stone                             "specified source file and line.",
12355a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1236b9c1b51eSKate Stone         m_options() {}
12375a988416SJim Ingham 
12389e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12395a988416SJim Ingham 
1240b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12415a988416SJim Ingham 
1242b9c1b51eSKate Stone   class CommandOptions : public Options {
12435a988416SJim Ingham   public:
1244b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
12455a988416SJim Ingham 
12469e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12475a988416SJim Ingham 
124897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1249b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
125097206d57SZachary Turner       Status error;
12513bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12525a988416SJim Ingham 
1253b9c1b51eSKate Stone       switch (short_option) {
12545a988416SJim Ingham       case 'f':
12555a988416SJim Ingham         m_filename.assign(option_arg);
12565a988416SJim Ingham         break;
12575a988416SJim Ingham 
12585a988416SJim Ingham       case 'l':
1259fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12605a988416SJim Ingham         break;
12615a988416SJim Ingham 
12625a988416SJim Ingham       default:
126336162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12645a988416SJim Ingham       }
12655a988416SJim Ingham 
12665a988416SJim Ingham       return error;
12675a988416SJim Ingham     }
12685a988416SJim Ingham 
1269b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12705a988416SJim Ingham       m_filename.clear();
12715a988416SJim Ingham       m_line_num = 0;
12725a988416SJim Ingham     }
12735a988416SJim Ingham 
12741f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
127570602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12761f0f5b5bSZachary Turner     }
12775a988416SJim Ingham 
12785a988416SJim Ingham     // Instance variables to hold the values for command options.
12795a988416SJim Ingham 
12805a988416SJim Ingham     std::string m_filename;
12815a988416SJim Ingham     uint32_t m_line_num;
12825a988416SJim Ingham   };
12835a988416SJim Ingham 
12845a988416SJim Ingham protected:
1285b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1286cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
12875a988416SJim Ingham 
128805097246SAdrian Prantl     // The following are the various types of breakpoints that could be
128905097246SAdrian Prantl     // cleared:
12905a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
12915a988416SJim Ingham 
12925a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
12935a988416SJim Ingham 
12945a988416SJim Ingham     if (m_options.m_line_num != 0)
12955a988416SJim Ingham       break_type = eClearTypeFileAndLine;
12965a988416SJim Ingham 
1297bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1298cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
12995a988416SJim Ingham 
1300cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13015a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13025a988416SJim Ingham 
13035a988416SJim Ingham     // Early return if there's no breakpoint at all.
1304b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13055a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13065a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13075a988416SJim Ingham       return result.Succeeded();
13085a988416SJim Ingham     }
13095a988416SJim Ingham 
13105a988416SJim Ingham     // Find matching breakpoints and delete them.
13115a988416SJim Ingham 
13125a988416SJim Ingham     // First create a copy of all the IDs.
13135a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13145a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13159e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13165a988416SJim Ingham 
13175a988416SJim Ingham     int num_cleared = 0;
13185a988416SJim Ingham     StreamString ss;
1319b9c1b51eSKate Stone     switch (break_type) {
13205a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13215a988416SJim Ingham     {
13225a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13235a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13245a988416SJim Ingham 
1325b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13265a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13275a988416SJim Ingham 
1328b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1329b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1330b9c1b51eSKate Stone           // remove the breakpoint.
1331b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13325a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13335a988416SJim Ingham             ss.EOL();
1334cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13355a988416SJim Ingham             ++num_cleared;
13365a988416SJim Ingham           }
13375a988416SJim Ingham         }
13385a988416SJim Ingham       }
1339b9c1b51eSKate Stone     } break;
13405a988416SJim Ingham 
13415a988416SJim Ingham     default:
13425a988416SJim Ingham       break;
13435a988416SJim Ingham     }
13445a988416SJim Ingham 
1345b9c1b51eSKate Stone     if (num_cleared > 0) {
13465a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13475a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1348c156427dSZachary Turner       output_stream << ss.GetString();
13495a988416SJim Ingham       output_stream.EOL();
13505a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1351b9c1b51eSKate Stone     } else {
13525a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13535a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13545a988416SJim Ingham     }
13555a988416SJim Ingham 
13565a988416SJim Ingham     return result.Succeeded();
13575a988416SJim Ingham   }
13585a988416SJim Ingham 
13595a988416SJim Ingham private:
13605a988416SJim Ingham   CommandOptions m_options;
13615a988416SJim Ingham };
13625a988416SJim Ingham 
13635a988416SJim Ingham // CommandObjectBreakpointDelete
1364f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1365f94668e3SRaphael Isemann #include "CommandOptions.inc"
13661f0f5b5bSZachary Turner 
13675a988416SJim Ingham #pragma mark Delete
13685a988416SJim Ingham 
1369b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13705a988416SJim Ingham public:
1371b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1372b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1373b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1374b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
13759e85e5a8SEugene Zelenko                             nullptr),
1376b9c1b51eSKate Stone         m_options() {
13775a988416SJim Ingham     CommandArgumentEntry arg;
1378b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1379b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1380b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1381b9c1b51eSKate Stone     // arguments vector.
13825a988416SJim Ingham     m_arguments.push_back(arg);
13835a988416SJim Ingham   }
13845a988416SJim Ingham 
13859e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
13865a988416SJim Ingham 
1387b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
138833df7cd3SJim Ingham 
1389b9c1b51eSKate Stone   class CommandOptions : public Options {
139033df7cd3SJim Ingham   public:
1391b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
139233df7cd3SJim Ingham 
13939e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
139433df7cd3SJim Ingham 
139597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1396b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
139797206d57SZachary Turner       Status error;
139833df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
139933df7cd3SJim Ingham 
1400b9c1b51eSKate Stone       switch (short_option) {
140133df7cd3SJim Ingham       case 'f':
140233df7cd3SJim Ingham         m_force = true;
140333df7cd3SJim Ingham         break;
140433df7cd3SJim Ingham 
140533df7cd3SJim Ingham       case 'D':
140633df7cd3SJim Ingham         m_use_dummy = true;
140733df7cd3SJim Ingham         break;
140833df7cd3SJim Ingham 
140933df7cd3SJim Ingham       default:
141036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
141133df7cd3SJim Ingham       }
141233df7cd3SJim Ingham 
141333df7cd3SJim Ingham       return error;
141433df7cd3SJim Ingham     }
141533df7cd3SJim Ingham 
1416b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
141733df7cd3SJim Ingham       m_use_dummy = false;
141833df7cd3SJim Ingham       m_force = false;
141933df7cd3SJim Ingham     }
142033df7cd3SJim Ingham 
14211f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
142270602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14231f0f5b5bSZachary Turner     }
142433df7cd3SJim Ingham 
142533df7cd3SJim Ingham     // Instance variables to hold the values for command options.
142633df7cd3SJim Ingham     bool m_use_dummy;
142733df7cd3SJim Ingham     bool m_force;
142833df7cd3SJim Ingham   };
142933df7cd3SJim Ingham 
14305a988416SJim Ingham protected:
1431b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1432cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14335a988416SJim Ingham 
1434bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1435cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14365a988416SJim Ingham 
1437cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
14385a988416SJim Ingham 
14395a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14405a988416SJim Ingham 
1441b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14425a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14435a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14445a988416SJim Ingham       return false;
14455a988416SJim Ingham     }
14465a988416SJim Ingham 
144711eb9c64SZachary Turner     if (command.empty()) {
1448b9c1b51eSKate Stone       if (!m_options.m_force &&
1449b9c1b51eSKate Stone           !m_interpreter.Confirm(
1450b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1451b9c1b51eSKate Stone               true)) {
14525a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1453b9c1b51eSKate Stone       } else {
1454cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1455b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1456b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1457b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14585a988416SJim Ingham       }
14595a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1460b9c1b51eSKate Stone     } else {
14615a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
14625a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1463b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1464cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1465b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
14665a988416SJim Ingham 
1467b9c1b51eSKate Stone       if (result.Succeeded()) {
14685a988416SJim Ingham         int delete_count = 0;
14695a988416SJim Ingham         int disable_count = 0;
14705a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1471b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
14725a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
14735a988416SJim Ingham 
1474b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1475b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1476b9c1b51eSKate Stone               Breakpoint *breakpoint =
1477cb2380c9SRaphael Isemann                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1478b9c1b51eSKate Stone               BreakpointLocation *location =
1479b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1480b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1481b9c1b51eSKate Stone               // disable them instead.
1482b9c1b51eSKate Stone               if (location) {
14835a988416SJim Ingham                 location->SetEnabled(false);
14845a988416SJim Ingham                 ++disable_count;
14855a988416SJim Ingham               }
1486b9c1b51eSKate Stone             } else {
1487cb2380c9SRaphael Isemann               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
14885a988416SJim Ingham               ++delete_count;
14895a988416SJim Ingham             }
14905a988416SJim Ingham           }
14915a988416SJim Ingham         }
1492b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1493b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
14945a988416SJim Ingham             delete_count, disable_count);
14955a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
14965a988416SJim Ingham       }
14975a988416SJim Ingham     }
14985a988416SJim Ingham     return result.Succeeded();
14995a988416SJim Ingham   }
15009e85e5a8SEugene Zelenko 
150133df7cd3SJim Ingham private:
150233df7cd3SJim Ingham   CommandOptions m_options;
150333df7cd3SJim Ingham };
150433df7cd3SJim Ingham 
15055e09c8c3SJim Ingham // CommandObjectBreakpointName
1506f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1507f94668e3SRaphael Isemann #include "CommandOptions.inc"
1508bd68a052SRaphael Isemann 
1509b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15105e09c8c3SJim Ingham public:
1511b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1512b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15135e09c8c3SJim Ingham   }
15145e09c8c3SJim Ingham 
15159e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15165e09c8c3SJim Ingham 
15171f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
151870602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15195e09c8c3SJim Ingham   }
15205e09c8c3SJim Ingham 
152197206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1522b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
152397206d57SZachary Turner     Status error;
15245e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15255e09c8c3SJim Ingham 
1526b9c1b51eSKate Stone     switch (short_option) {
15275e09c8c3SJim Ingham     case 'N':
1528fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1529b9c1b51eSKate Stone           error.Success())
1530fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15315e09c8c3SJim Ingham       break;
15325e09c8c3SJim Ingham     case 'B':
1533fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1534b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15358cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1536fe11483bSZachary Turner             option_arg.str().c_str());
15375e09c8c3SJim Ingham       break;
15385e09c8c3SJim Ingham     case 'D':
1539fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1540b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15418cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1542fe11483bSZachary Turner             option_arg.str().c_str());
15435e09c8c3SJim Ingham       break;
1544e9632ebaSJim Ingham     case 'H':
1545e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1546e9632ebaSJim Ingham       break;
15475e09c8c3SJim Ingham 
15485e09c8c3SJim Ingham     default:
154936162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15505e09c8c3SJim Ingham     }
15515e09c8c3SJim Ingham     return error;
15525e09c8c3SJim Ingham   }
15535e09c8c3SJim Ingham 
1554b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
15555e09c8c3SJim Ingham     m_name.Clear();
15565e09c8c3SJim Ingham     m_breakpoint.Clear();
15575e09c8c3SJim Ingham     m_use_dummy.Clear();
15585e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1559e9632ebaSJim Ingham     m_help_string.Clear();
15605e09c8c3SJim Ingham   }
15615e09c8c3SJim Ingham 
15625e09c8c3SJim Ingham   OptionValueString m_name;
15635e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
15645e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1565e9632ebaSJim Ingham   OptionValueString m_help_string;
15665e09c8c3SJim Ingham };
15675e09c8c3SJim Ingham 
1568f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1569f94668e3SRaphael Isemann #include "CommandOptions.inc"
1570b842f2ecSJim Ingham 
15718fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1572b842f2ecSJim Ingham public:
15738fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1574b842f2ecSJim Ingham 
1575b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1576b842f2ecSJim Ingham 
1577b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1578b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1579b842f2ecSJim Ingham   }
1580b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1581b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1582b842f2ecSJim Ingham     Status error;
1583b842f2ecSJim Ingham     const int short_option
1584b842f2ecSJim Ingham         = g_breakpoint_access_options[option_idx].short_option;
1585b842f2ecSJim Ingham 
1586b842f2ecSJim Ingham     switch (short_option) {
1587b842f2ecSJim Ingham       case 'L': {
1588b842f2ecSJim Ingham         bool value, success;
158947cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1590b842f2ecSJim Ingham         if (success) {
1591b842f2ecSJim Ingham           m_permissions.SetAllowList(value);
1592b842f2ecSJim Ingham         } else
1593b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1594b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1595b842f2ecSJim Ingham               option_arg.str().c_str());
1596b842f2ecSJim Ingham       } break;
1597b842f2ecSJim Ingham       case 'A': {
1598b842f2ecSJim Ingham         bool value, success;
159947cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1600b842f2ecSJim Ingham         if (success) {
1601b842f2ecSJim Ingham           m_permissions.SetAllowDisable(value);
1602b842f2ecSJim Ingham         } else
1603b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1604b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1605b842f2ecSJim Ingham               option_arg.str().c_str());
1606b842f2ecSJim Ingham       } break;
1607b842f2ecSJim Ingham       case 'D': {
1608b842f2ecSJim Ingham         bool value, success;
160947cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1610b842f2ecSJim Ingham         if (success) {
1611b842f2ecSJim Ingham           m_permissions.SetAllowDelete(value);
1612b842f2ecSJim Ingham         } else
1613b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1614b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1615b842f2ecSJim Ingham               option_arg.str().c_str());
1616b842f2ecSJim Ingham       } break;
161736162014SRaphael Isemann       default:
161836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
1619b842f2ecSJim Ingham     }
1620b842f2ecSJim Ingham 
1621b842f2ecSJim Ingham     return error;
1622b842f2ecSJim Ingham   }
1623b842f2ecSJim Ingham 
1624b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
1625b842f2ecSJim Ingham   }
1626b842f2ecSJim Ingham 
1627b842f2ecSJim Ingham   const BreakpointName::Permissions &GetPermissions() const
1628b842f2ecSJim Ingham   {
1629b842f2ecSJim Ingham     return m_permissions;
1630b842f2ecSJim Ingham   }
1631b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1632b842f2ecSJim Ingham };
1633b842f2ecSJim Ingham 
1634b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1635b842f2ecSJim Ingham public:
1636b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1637b842f2ecSJim Ingham       : CommandObjectParsed(
1638b842f2ecSJim Ingham             interpreter, "configure", "Configure the options for the breakpoint"
1639b842f2ecSJim Ingham             " name provided.  "
1640b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1641b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1642b842f2ecSJim Ingham             "on the name.",
1643b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1644b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1645b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1646b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1647b842f2ecSJim Ingham     // command.
1648b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1649b842f2ecSJim Ingham     CommandArgumentData id_arg;
1650b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1651b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1652b842f2ecSJim Ingham     arg1.push_back(id_arg);
1653b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1654b842f2ecSJim Ingham 
1655b842f2ecSJim Ingham     m_option_group.Append(&m_bp_opts,
1656b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1657b842f2ecSJim Ingham                           LLDB_OPT_SET_1);
1658b842f2ecSJim Ingham     m_option_group.Append(&m_access_options,
1659b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1660b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1661e9632ebaSJim Ingham     m_option_group.Append(&m_bp_id,
1662e9632ebaSJim Ingham                           LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1663e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1664b842f2ecSJim Ingham     m_option_group.Finalize();
1665b842f2ecSJim Ingham   }
1666b842f2ecSJim Ingham 
1667b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1668b842f2ecSJim Ingham 
1669b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1670b842f2ecSJim Ingham 
1671b842f2ecSJim Ingham protected:
1672b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1673b842f2ecSJim Ingham 
1674b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1675b842f2ecSJim Ingham     if (argc == 0) {
1676b842f2ecSJim Ingham       result.AppendError("No names provided.");
1677b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1678b842f2ecSJim Ingham       return false;
1679b842f2ecSJim Ingham     }
1680b842f2ecSJim Ingham 
1681cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1682b842f2ecSJim Ingham 
1683b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1684cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1685b842f2ecSJim Ingham 
1686b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1687b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1688b842f2ecSJim Ingham       Status error;
16890d9a201eSRaphael Isemann       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error))
1690b842f2ecSJim Ingham       {
1691b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1692b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1693b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1694b842f2ecSJim Ingham         return false;
1695b842f2ecSJim Ingham       }
1696b842f2ecSJim Ingham     }
169705097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
169805097246SAdrian Prantl     // check the error:
1699b842f2ecSJim Ingham     BreakpointSP bp_sp;
1700b842f2ecSJim Ingham     if (m_bp_id.m_breakpoint.OptionWasSet())
1701b842f2ecSJim Ingham     {
1702b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1703cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1704b842f2ecSJim Ingham       if (!bp_sp)
1705b842f2ecSJim Ingham       {
1706b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1707b842f2ecSJim Ingham                            bp_id);
1708b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1709b842f2ecSJim Ingham         return false;
1710b842f2ecSJim Ingham       }
1711b842f2ecSJim Ingham     }
1712b842f2ecSJim Ingham 
1713b842f2ecSJim Ingham     Status error;
1714b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1715b842f2ecSJim Ingham       ConstString name(entry.c_str());
1716cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1717b842f2ecSJim Ingham       if (!bp_name)
1718b842f2ecSJim Ingham         continue;
1719e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1720e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1721e9632ebaSJim Ingham 
1722b842f2ecSJim Ingham       if (bp_sp)
1723cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1724b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1725b842f2ecSJim Ingham       else
1726cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1727b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1728b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1729b842f2ecSJim Ingham     }
1730b842f2ecSJim Ingham     return true;
1731b842f2ecSJim Ingham   }
1732b842f2ecSJim Ingham 
1733b842f2ecSJim Ingham private:
1734b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1735b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1736b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1737b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1738b842f2ecSJim Ingham };
1739b842f2ecSJim Ingham 
1740b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17415e09c8c3SJim Ingham public:
1742b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1743b9c1b51eSKate Stone       : CommandObjectParsed(
1744b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
17455e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1746b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1747b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1748b9c1b51eSKate Stone     // command.
17495e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17505e09c8c3SJim Ingham     CommandArgumentData id_arg;
17515e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17525e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17535e09c8c3SJim Ingham     arg1.push_back(id_arg);
17545e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17555e09c8c3SJim Ingham 
17565e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17575e09c8c3SJim Ingham     m_option_group.Finalize();
17585e09c8c3SJim Ingham   }
17595e09c8c3SJim Ingham 
17609e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17615e09c8c3SJim Ingham 
1762b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
17635e09c8c3SJim Ingham 
17645e09c8c3SJim Ingham protected:
1765b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1766b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
17675e09c8c3SJim Ingham       result.SetError("No name option provided.");
17685e09c8c3SJim Ingham       return false;
17695e09c8c3SJim Ingham     }
17705e09c8c3SJim Ingham 
1771cb2380c9SRaphael Isemann     Target &target =
1772b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
17735e09c8c3SJim Ingham 
1774bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1775cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
17765e09c8c3SJim Ingham 
1777cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
17785e09c8c3SJim Ingham 
17795e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1780b9c1b51eSKate Stone     if (num_breakpoints == 0) {
17815e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
17825e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
17835e09c8c3SJim Ingham       return false;
17845e09c8c3SJim Ingham     }
17855e09c8c3SJim Ingham 
17865e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
17875e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1788b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1789cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1790b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
17915e09c8c3SJim Ingham 
1792b9c1b51eSKate Stone     if (result.Succeeded()) {
1793b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
17945e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
17955e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
17965e09c8c3SJim Ingham         return false;
17975e09c8c3SJim Ingham       }
17985e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1799b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1800b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1801b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1802b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1803b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1804b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18055e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1806cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18075e09c8c3SJim Ingham       }
18085e09c8c3SJim Ingham     }
18095e09c8c3SJim Ingham 
18105e09c8c3SJim Ingham     return true;
18115e09c8c3SJim Ingham   }
18125e09c8c3SJim Ingham 
18135e09c8c3SJim Ingham private:
18145e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18155e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18165e09c8c3SJim Ingham };
18175e09c8c3SJim Ingham 
1818b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18195e09c8c3SJim Ingham public:
1820b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1821b9c1b51eSKate Stone       : CommandObjectParsed(
1822b9c1b51eSKate Stone             interpreter, "delete",
18235e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18245e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1825b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1826b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1827b9c1b51eSKate Stone     // command.
18285e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18295e09c8c3SJim Ingham     CommandArgumentData id_arg;
18305e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18315e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18325e09c8c3SJim Ingham     arg1.push_back(id_arg);
18335e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18345e09c8c3SJim Ingham 
18355e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18365e09c8c3SJim Ingham     m_option_group.Finalize();
18375e09c8c3SJim Ingham   }
18385e09c8c3SJim Ingham 
18399e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18405e09c8c3SJim Ingham 
1841b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18425e09c8c3SJim Ingham 
18435e09c8c3SJim Ingham protected:
1844b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1845b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18465e09c8c3SJim Ingham       result.SetError("No name option provided.");
18475e09c8c3SJim Ingham       return false;
18485e09c8c3SJim Ingham     }
18495e09c8c3SJim Ingham 
1850cb2380c9SRaphael Isemann     Target &target =
1851b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18525e09c8c3SJim Ingham 
1853bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1854cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18555e09c8c3SJim Ingham 
1856cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18575e09c8c3SJim Ingham 
18585e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1859b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18605e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
18615e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18625e09c8c3SJim Ingham       return false;
18635e09c8c3SJim Ingham     }
18645e09c8c3SJim Ingham 
18655e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18665e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1867b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1868cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1869b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
18705e09c8c3SJim Ingham 
1871b9c1b51eSKate Stone     if (result.Succeeded()) {
1872b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18735e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
18745e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18755e09c8c3SJim Ingham         return false;
18765e09c8c3SJim Ingham       }
1877b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
18785e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1879b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1880b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1881b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18825e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1883cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
18845e09c8c3SJim Ingham       }
18855e09c8c3SJim Ingham     }
18865e09c8c3SJim Ingham 
18875e09c8c3SJim Ingham     return true;
18885e09c8c3SJim Ingham   }
18895e09c8c3SJim Ingham 
18905e09c8c3SJim Ingham private:
18915e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18925e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18935e09c8c3SJim Ingham };
18945e09c8c3SJim Ingham 
1895b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
18965e09c8c3SJim Ingham public:
1897b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1898b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1899b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1900b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1901b842f2ecSJim Ingham                             "names",
19025e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1903b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1904b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19055e09c8c3SJim Ingham     m_option_group.Finalize();
19065e09c8c3SJim Ingham   }
19075e09c8c3SJim Ingham 
19089e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19095e09c8c3SJim Ingham 
1910b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19115e09c8c3SJim Ingham 
19125e09c8c3SJim Ingham protected:
1913b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1914cb2380c9SRaphael Isemann     Target &target =
1915b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19165e09c8c3SJim Ingham 
1917b842f2ecSJim Ingham     std::vector<std::string> name_list;
1918b842f2ecSJim Ingham     if (command.empty()) {
1919cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1920b842f2ecSJim Ingham     } else {
1921b842f2ecSJim Ingham       for (const Args::ArgEntry &arg : command)
1922b842f2ecSJim Ingham       {
1923b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1924b842f2ecSJim Ingham       }
1925b842f2ecSJim Ingham     }
1926b842f2ecSJim Ingham 
1927b842f2ecSJim Ingham     if (name_list.empty()) {
1928b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1929b842f2ecSJim Ingham     } else {
1930b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1931b842f2ecSJim Ingham         const char *name = name_str.c_str();
1932b842f2ecSJim Ingham         // First print out the options for the name:
1933b842f2ecSJim Ingham         Status error;
1934cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1935cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1936b842f2ecSJim Ingham         if (bp_name)
1937b842f2ecSJim Ingham         {
1938b842f2ecSJim Ingham           StreamString s;
1939b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1940b842f2ecSJim Ingham           if (bp_name->GetDescription(&s, eDescriptionLevelFull))
1941b842f2ecSJim Ingham           {
1942b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1943b842f2ecSJim Ingham           }
1944b842f2ecSJim Ingham 
1945bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1946cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19475e09c8c3SJim Ingham 
1948cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1949b842f2ecSJim Ingham           bool any_set = false;
1950b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1951b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19525e09c8c3SJim Ingham               StreamString s;
1953b842f2ecSJim Ingham               any_set = true;
19545e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19555e09c8c3SJim Ingham               s.EOL();
1956c156427dSZachary Turner               result.AppendMessage(s.GetString());
19575e09c8c3SJim Ingham             }
19585e09c8c3SJim Ingham           }
1959b842f2ecSJim Ingham           if (!any_set)
1960b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
1961b9c1b51eSKate Stone         } else {
1962b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
19635e09c8c3SJim Ingham         }
1964b842f2ecSJim Ingham       }
19655e09c8c3SJim Ingham     }
19665e09c8c3SJim Ingham     return true;
19675e09c8c3SJim Ingham   }
19685e09c8c3SJim Ingham 
19695e09c8c3SJim Ingham private:
19705e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19715e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19725e09c8c3SJim Ingham };
19735e09c8c3SJim Ingham 
1974e14dc268SJim Ingham // CommandObjectBreakpointName
1975b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
19765e09c8c3SJim Ingham public:
19777428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
1978b9c1b51eSKate Stone       : CommandObjectMultiword(
1979b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
1980b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
1981b9c1b51eSKate Stone     CommandObjectSP add_command_object(
1982b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
1983b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
1984b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
1985b9c1b51eSKate Stone     CommandObjectSP list_command_object(
1986b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
1987b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
1988b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
19895e09c8c3SJim Ingham 
19905e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
19915e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
19925e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
1993b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
19945e09c8c3SJim Ingham   }
19955e09c8c3SJim Ingham 
19969e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
19975e09c8c3SJim Ingham };
19985e09c8c3SJim Ingham 
1999e14dc268SJim Ingham // CommandObjectBreakpointRead
20003acdf385SJim Ingham #pragma mark Read::CommandOptions
2001f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2002f94668e3SRaphael Isemann #include "CommandOptions.inc"
20031f0f5b5bSZachary Turner 
20041f0f5b5bSZachary Turner #pragma mark Read
2005e14dc268SJim Ingham 
2006e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2007e14dc268SJim Ingham public:
2008e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2009e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2010e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2011e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2012e14dc268SJim Ingham                             nullptr),
2013e14dc268SJim Ingham         m_options() {
2014e14dc268SJim Ingham     CommandArgumentEntry arg;
2015e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2016e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2017e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2018e14dc268SJim Ingham     // arguments vector.
2019e14dc268SJim Ingham     m_arguments.push_back(arg);
2020e14dc268SJim Ingham   }
2021e14dc268SJim Ingham 
2022e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2023e14dc268SJim Ingham 
2024e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2025e14dc268SJim Ingham 
2026e14dc268SJim Ingham   class CommandOptions : public Options {
2027e14dc268SJim Ingham   public:
2028e14dc268SJim Ingham     CommandOptions() : Options() {}
2029e14dc268SJim Ingham 
2030e14dc268SJim Ingham     ~CommandOptions() override = default;
2031e14dc268SJim Ingham 
203297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2033e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
203497206d57SZachary Turner       Status error;
2035e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2036e14dc268SJim Ingham 
2037e14dc268SJim Ingham       switch (short_option) {
2038e14dc268SJim Ingham       case 'f':
2039e14dc268SJim Ingham         m_filename.assign(option_arg);
2040e14dc268SJim Ingham         break;
20413acdf385SJim Ingham       case 'N': {
204297206d57SZachary Turner         Status name_error;
20433acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20443acdf385SJim Ingham                                                   name_error)) {
20453acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20463acdf385SJim Ingham                                          name_error.AsCString());
20473acdf385SJim Ingham         }
20483acdf385SJim Ingham         m_names.push_back(option_arg);
20493acdf385SJim Ingham         break;
20503acdf385SJim Ingham       }
2051e14dc268SJim Ingham       default:
205236162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2053e14dc268SJim Ingham       }
2054e14dc268SJim Ingham 
2055e14dc268SJim Ingham       return error;
2056e14dc268SJim Ingham     }
2057e14dc268SJim Ingham 
2058e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2059e14dc268SJim Ingham       m_filename.clear();
20603acdf385SJim Ingham       m_names.clear();
2061e14dc268SJim Ingham     }
2062e14dc268SJim Ingham 
20631f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
206470602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
20651f0f5b5bSZachary Turner     }
2066e14dc268SJim Ingham 
2067e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2068e14dc268SJim Ingham 
2069e14dc268SJim Ingham     std::string m_filename;
20703acdf385SJim Ingham     std::vector<std::string> m_names;
2071e14dc268SJim Ingham   };
2072e14dc268SJim Ingham 
2073e14dc268SJim Ingham protected:
2074e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2075cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2076e14dc268SJim Ingham 
20773acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2078cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
20793acdf385SJim Ingham 
20808f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
20818f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
208201f16664SJim Ingham     BreakpointIDList new_bps;
2083cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2084cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2085e14dc268SJim Ingham 
2086e14dc268SJim Ingham     if (!error.Success()) {
208701f16664SJim Ingham       result.AppendError(error.AsCString());
2088e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
208901f16664SJim Ingham       return false;
2090e14dc268SJim Ingham     }
20913acdf385SJim Ingham 
20923acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
20933acdf385SJim Ingham 
20943acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
20953acdf385SJim Ingham     if (num_breakpoints == 0) {
20963acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
20973acdf385SJim Ingham     } else {
20983acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
20993acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
21003acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
21013acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2102cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
21033acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
21043acdf385SJim Ingham                              .get();
21053acdf385SJim Ingham         if (bp)
21063acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
21073acdf385SJim Ingham                              false);
21083acdf385SJim Ingham       }
21093acdf385SJim Ingham     }
2110e14dc268SJim Ingham     return result.Succeeded();
2111e14dc268SJim Ingham   }
2112e14dc268SJim Ingham 
2113e14dc268SJim Ingham private:
2114e14dc268SJim Ingham   CommandOptions m_options;
2115e14dc268SJim Ingham };
2116e14dc268SJim Ingham 
2117e14dc268SJim Ingham // CommandObjectBreakpointWrite
21181f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2119f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2120f94668e3SRaphael Isemann #include "CommandOptions.inc"
21211f0f5b5bSZachary Turner 
21221f0f5b5bSZachary Turner #pragma mark Write
2123e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2124e14dc268SJim Ingham public:
2125e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2126e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2127e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2128e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2129e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2130e14dc268SJim Ingham                             nullptr),
2131e14dc268SJim Ingham         m_options() {
2132e14dc268SJim Ingham     CommandArgumentEntry arg;
2133e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2134e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2135e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2136e14dc268SJim Ingham     // arguments vector.
2137e14dc268SJim Ingham     m_arguments.push_back(arg);
2138e14dc268SJim Ingham   }
2139e14dc268SJim Ingham 
2140e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2141e14dc268SJim Ingham 
2142e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2143e14dc268SJim Ingham 
2144e14dc268SJim Ingham   class CommandOptions : public Options {
2145e14dc268SJim Ingham   public:
2146e14dc268SJim Ingham     CommandOptions() : Options() {}
2147e14dc268SJim Ingham 
2148e14dc268SJim Ingham     ~CommandOptions() override = default;
2149e14dc268SJim Ingham 
215097206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2151e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
215297206d57SZachary Turner       Status error;
2153e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2154e14dc268SJim Ingham 
2155e14dc268SJim Ingham       switch (short_option) {
2156e14dc268SJim Ingham       case 'f':
2157e14dc268SJim Ingham         m_filename.assign(option_arg);
2158e14dc268SJim Ingham         break;
21592d3628e1SJim Ingham       case 'a':
21602d3628e1SJim Ingham         m_append = true;
21612d3628e1SJim Ingham         break;
2162e14dc268SJim Ingham       default:
216336162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2164e14dc268SJim Ingham       }
2165e14dc268SJim Ingham 
2166e14dc268SJim Ingham       return error;
2167e14dc268SJim Ingham     }
2168e14dc268SJim Ingham 
2169e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2170e14dc268SJim Ingham       m_filename.clear();
21712d3628e1SJim Ingham       m_append = false;
2172e14dc268SJim Ingham     }
2173e14dc268SJim Ingham 
21741f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
217570602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
21761f0f5b5bSZachary Turner     }
2177e14dc268SJim Ingham 
2178e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2179e14dc268SJim Ingham 
2180e14dc268SJim Ingham     std::string m_filename;
21812d3628e1SJim Ingham     bool m_append = false;
2182e14dc268SJim Ingham   };
2183e14dc268SJim Ingham 
2184e14dc268SJim Ingham protected:
2185e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2186cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2187e14dc268SJim Ingham 
2188e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2189cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2190e14dc268SJim Ingham 
2191e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
219211eb9c64SZachary Turner     if (!command.empty()) {
2193e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2194cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2195b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2196e14dc268SJim Ingham 
219701f16664SJim Ingham       if (!result.Succeeded()) {
2198e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2199e14dc268SJim Ingham         return false;
2200e14dc268SJim Ingham       }
2201e14dc268SJim Ingham     }
22028f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
22038f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2204cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
22058f3be7a3SJonas Devlieghere                                                      m_options.m_append);
220601f16664SJim Ingham     if (!error.Success()) {
220701f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
220801f16664SJim Ingham                                    error.AsCString());
220901f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2210e14dc268SJim Ingham     }
2211e14dc268SJim Ingham     return result.Succeeded();
2212e14dc268SJim Ingham   }
2213e14dc268SJim Ingham 
2214e14dc268SJim Ingham private:
2215e14dc268SJim Ingham   CommandOptions m_options;
2216e14dc268SJim Ingham };
2217e14dc268SJim Ingham 
221830fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2219ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
222030fdc8d8SChris Lattner 
2221b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2222b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2223b9c1b51eSKate Stone     : CommandObjectMultiword(
2224b9c1b51eSKate Stone           interpreter, "breakpoint",
22257428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2226b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2227b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2228b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2229b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2230b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2231b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2232b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2233b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2234b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2235b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2236b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2237b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2238b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2239b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2240b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2241b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2242b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2243b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2244b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2245e14dc268SJim Ingham   CommandObjectSP write_command_object(
2246e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2247e14dc268SJim Ingham   CommandObjectSP read_command_object(
2248e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
224930fdc8d8SChris Lattner 
2250b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
225130fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
225230fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2253b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2254b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2255ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2256b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2257b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
22585e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2259e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2260e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
226130fdc8d8SChris Lattner 
226223f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
226323f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
226423f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
226523f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
226623f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
226723f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
226823f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
226923f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
22705e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2271e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2272e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
227330fdc8d8SChris Lattner }
227430fdc8d8SChris Lattner 
22759e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
227630fdc8d8SChris Lattner 
2277b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
22785e09c8c3SJim Ingham                                                  bool allow_locations,
22795e09c8c3SJim Ingham                                                  CommandReturnObject &result,
2280b842f2ecSJim Ingham                                                  BreakpointIDList *valid_ids,
2281b842f2ecSJim Ingham                                                  BreakpointName::Permissions
2282b842f2ecSJim Ingham                                                      ::PermissionKinds
2283b842f2ecSJim Ingham                                                      purpose) {
228430fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2285b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2286b9c1b51eSKate Stone   //                                  canonical representation
2287b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2288b9c1b51eSKate Stone   //                                  representing a range (in which case there
2289b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2290b9c1b51eSKate Stone   //                                      after of one of the first two types.
22915e09c8c3SJim Ingham   //                                  4). A breakpoint name
2292b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2293b9c1b51eSKate Stone   // one.)
229430fdc8d8SChris Lattner 
229530fdc8d8SChris Lattner   Args temp_args;
229630fdc8d8SChris Lattner 
229711eb9c64SZachary Turner   if (args.empty()) {
2298b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2299b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2300b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
230136f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2302b9c1b51eSKate Stone     } else {
2303b9c1b51eSKate Stone       result.AppendError(
2304b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
230536f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
230636f3b369SJim Ingham     }
230736f3b369SJim Ingham     return;
230836f3b369SJim Ingham   }
230936f3b369SJim Ingham 
2310b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
231105097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
231205097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
231305097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
231405097246SAdrian Prantl   // into TEMP_ARGS.
231530fdc8d8SChris Lattner 
2316b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2317b842f2ecSJim Ingham                                            purpose, result, temp_args);
231830fdc8d8SChris Lattner 
2319b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2320b9c1b51eSKate Stone   // BreakpointIDList:
232130fdc8d8SChris Lattner 
232216662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
232330fdc8d8SChris Lattner 
232405097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
232505097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
232630fdc8d8SChris Lattner 
2327b9c1b51eSKate Stone   if (result.Succeeded()) {
2328b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
232905097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
233005097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
233130fdc8d8SChris Lattner 
2332c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2333b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
233430fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2335b9c1b51eSKate Stone       Breakpoint *breakpoint =
2336b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2337b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2338c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2339b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
234030fdc8d8SChris Lattner           StreamString id_str;
2341b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2342b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2343c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2344b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2345b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
234630fdc8d8SChris Lattner               id_str.GetData());
234730fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
234830fdc8d8SChris Lattner         }
2349b9c1b51eSKate Stone       } else {
2350c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2351b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2352b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
23537428a18cSKate Stone             cur_bp_id.GetBreakpointID());
235430fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
235530fdc8d8SChris Lattner       }
235630fdc8d8SChris Lattner     }
235730fdc8d8SChris Lattner   }
235830fdc8d8SChris Lattner }
2359