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"
1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
230e0984eeSJim Ingham #include "lldb/Target/Language.h"
24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
25b9c1b51eSKate Stone #include "lldb/Target/Target.h"
261b54c88cSJim Ingham #include "lldb/Target/Thread.h"
271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3030fdc8d8SChris Lattner 
31796ac80bSJonas Devlieghere #include <memory>
32796ac80bSJonas Devlieghere #include <vector>
33796ac80bSJonas Devlieghere 
3430fdc8d8SChris Lattner using namespace lldb;
3530fdc8d8SChris Lattner using namespace lldb_private;
3630fdc8d8SChris Lattner 
37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
3930fdc8d8SChris Lattner   s->IndentMore();
4030fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4130fdc8d8SChris Lattner   s->IndentLess();
4230fdc8d8SChris Lattner   s->EOL();
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
45b842f2ecSJim Ingham // Modifiable Breakpoint Options
46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
47f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
48f94668e3SRaphael Isemann #include "CommandOptions.inc"
49bd68a052SRaphael Isemann 
50b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup
51b842f2ecSJim Ingham {
52b842f2ecSJim Ingham public:
53b842f2ecSJim Ingham   BreakpointOptionGroup() :
54b842f2ecSJim Ingham           OptionGroup(),
55b842f2ecSJim Ingham           m_bp_opts(false) {}
56b842f2ecSJim Ingham 
57b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
58b842f2ecSJim Ingham 
59b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
60b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
61b842f2ecSJim Ingham   }
62b842f2ecSJim Ingham 
63b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
64b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
65b842f2ecSJim Ingham     Status error;
66b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
67b842f2ecSJim Ingham 
68b842f2ecSJim Ingham     switch (short_option) {
69b842f2ecSJim Ingham     case 'c':
7005097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
7105097246SAdrian Prantl       // to say it was passed in.
72b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
73b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
74b842f2ecSJim Ingham       break;
75b842f2ecSJim Ingham     case 'C':
76b842f2ecSJim Ingham       m_commands.push_back(option_arg);
77b842f2ecSJim Ingham       break;
78b842f2ecSJim Ingham     case 'd':
79b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
80b842f2ecSJim Ingham       break;
81b842f2ecSJim Ingham     case 'e':
82b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
83b842f2ecSJim Ingham       break;
84b842f2ecSJim Ingham     case 'G': {
85b842f2ecSJim Ingham       bool value, success;
8647cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
87b842f2ecSJim Ingham       if (success) {
88b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
89b842f2ecSJim Ingham       } else
90b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
91b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
92b842f2ecSJim Ingham             option_arg.str().c_str());
93b842f2ecSJim Ingham     }
94b842f2ecSJim Ingham     break;
95b842f2ecSJim Ingham     case 'i':
96b842f2ecSJim Ingham     {
97b842f2ecSJim Ingham       uint32_t ignore_count;
98b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
99b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
100b842f2ecSJim Ingham                                        option_arg.str().c_str());
101b842f2ecSJim Ingham       else
102b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
103b842f2ecSJim Ingham     }
104b842f2ecSJim Ingham     break;
105b842f2ecSJim Ingham     case 'o': {
106b842f2ecSJim Ingham       bool value, success;
10747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
108b842f2ecSJim Ingham       if (success) {
109b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
110b842f2ecSJim Ingham       } else
111b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
112b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
113b842f2ecSJim Ingham             option_arg.str().c_str());
114b842f2ecSJim Ingham     } break;
115b842f2ecSJim Ingham     case 't':
116b842f2ecSJim Ingham     {
117b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
118b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
119b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
120b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
121b842f2ecSJim Ingham                                          option_arg.str().c_str());
122b842f2ecSJim Ingham       }
123b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
124b842f2ecSJim Ingham     }
125b842f2ecSJim Ingham     break;
126b842f2ecSJim Ingham     case 'T':
127b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
128b842f2ecSJim Ingham       break;
129b842f2ecSJim Ingham     case 'q':
130b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
131b842f2ecSJim Ingham       break;
132b842f2ecSJim Ingham     case 'x':
133b842f2ecSJim Ingham     {
134b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
135b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
136b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
137b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
138b842f2ecSJim Ingham                                          option_arg.str().c_str());
139b842f2ecSJim Ingham       }
140b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
141b842f2ecSJim Ingham     }
142b842f2ecSJim Ingham     break;
143b842f2ecSJim Ingham     default:
14436162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
145b842f2ecSJim Ingham     }
146b842f2ecSJim Ingham 
147b842f2ecSJim Ingham     return error;
148b842f2ecSJim Ingham   }
149b842f2ecSJim Ingham 
150b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
151b842f2ecSJim Ingham     m_bp_opts.Clear();
152b842f2ecSJim Ingham     m_commands.clear();
153b842f2ecSJim Ingham   }
154b842f2ecSJim Ingham 
155b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
156b842f2ecSJim Ingham     if (!m_commands.empty())
157b842f2ecSJim Ingham     {
158b842f2ecSJim Ingham       if (!m_commands.empty())
159b842f2ecSJim Ingham       {
160a8f3ae7cSJonas Devlieghere           auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
161b842f2ecSJim Ingham 
162b842f2ecSJim Ingham           for (std::string &str : m_commands)
163b842f2ecSJim Ingham             cmd_data->user_source.AppendString(str);
164b842f2ecSJim Ingham 
165b842f2ecSJim Ingham           cmd_data->stop_on_error = true;
166b842f2ecSJim Ingham           m_bp_opts.SetCommandDataCallback(cmd_data);
167b842f2ecSJim Ingham       }
168b842f2ecSJim Ingham     }
169b842f2ecSJim Ingham     return Status();
170b842f2ecSJim Ingham   }
171b842f2ecSJim Ingham 
172b842f2ecSJim Ingham   const BreakpointOptions &GetBreakpointOptions()
173b842f2ecSJim Ingham   {
174b842f2ecSJim Ingham     return m_bp_opts;
175b842f2ecSJim Ingham   }
176b842f2ecSJim Ingham 
177b842f2ecSJim Ingham   std::vector<std::string> m_commands;
178b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
179b842f2ecSJim Ingham 
180b842f2ecSJim Ingham };
181bd68a052SRaphael Isemann 
182f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
183f94668e3SRaphael Isemann #include "CommandOptions.inc"
184b842f2ecSJim Ingham 
185b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup
186b842f2ecSJim Ingham {
187b842f2ecSJim Ingham public:
188b842f2ecSJim Ingham   BreakpointDummyOptionGroup() :
189b842f2ecSJim Ingham           OptionGroup() {}
190b842f2ecSJim Ingham 
191b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
192b842f2ecSJim Ingham 
193b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
194b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
195b842f2ecSJim Ingham   }
196b842f2ecSJim Ingham 
197b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
198b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
199b842f2ecSJim Ingham     Status error;
200b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
201b842f2ecSJim Ingham 
202b842f2ecSJim Ingham     switch (short_option) {
203b842f2ecSJim Ingham       case 'D':
204b842f2ecSJim Ingham         m_use_dummy = true;
205b842f2ecSJim Ingham         break;
206b842f2ecSJim Ingham     default:
20736162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
208b842f2ecSJim Ingham     }
209b842f2ecSJim Ingham 
210b842f2ecSJim Ingham     return error;
211b842f2ecSJim Ingham   }
212b842f2ecSJim Ingham 
213b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
214b842f2ecSJim Ingham     m_use_dummy = false;
215b842f2ecSJim Ingham   }
216b842f2ecSJim Ingham 
217b842f2ecSJim Ingham   bool m_use_dummy;
218b842f2ecSJim Ingham 
219b842f2ecSJim Ingham };
220b842f2ecSJim Ingham 
221f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
222f94668e3SRaphael Isemann #include "CommandOptions.inc"
2231f0f5b5bSZachary Turner 
2245a988416SJim Ingham // CommandObjectBreakpointSet
22530fdc8d8SChris Lattner 
226b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2275a988416SJim Ingham public:
228efe8e7e3SFangrui Song   enum BreakpointSetType {
2295a988416SJim Ingham     eSetTypeInvalid,
2305a988416SJim Ingham     eSetTypeFileAndLine,
2315a988416SJim Ingham     eSetTypeAddress,
2325a988416SJim Ingham     eSetTypeFunctionName,
2335a988416SJim Ingham     eSetTypeFunctionRegexp,
2345a988416SJim Ingham     eSetTypeSourceRegexp,
2353815e702SJim Ingham     eSetTypeException,
2363815e702SJim Ingham     eSetTypeScripted,
237efe8e7e3SFangrui Song   };
2385a988416SJim Ingham 
239b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
240b9c1b51eSKate Stone       : CommandObjectParsed(
241b9c1b51eSKate Stone             interpreter, "breakpoint set",
2425a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2435a988416SJim Ingham             "breakpoint set <cmd-options>"),
244b842f2ecSJim Ingham         m_bp_opts(), m_options() {
245b842f2ecSJim Ingham           // We're picking up all the normal options, commands and disable.
246b842f2ecSJim Ingham           m_all_options.Append(&m_bp_opts,
247b842f2ecSJim Ingham                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
248b842f2ecSJim Ingham                                LLDB_OPT_SET_ALL);
249b842f2ecSJim Ingham           m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
250b842f2ecSJim Ingham           m_all_options.Append(&m_options);
251b842f2ecSJim Ingham           m_all_options.Finalize();
252b842f2ecSJim Ingham         }
2535a988416SJim Ingham 
2549e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2555a988416SJim Ingham 
256b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2575a988416SJim Ingham 
258b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2595a988416SJim Ingham   public:
260b9c1b51eSKate Stone     CommandOptions()
261b842f2ecSJim Ingham         : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
262b9c1b51eSKate Stone           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
263b9c1b51eSKate Stone           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
264b9c1b51eSKate Stone           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
265a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
26623b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
267b842f2ecSJim Ingham           m_skip_prologue(eLazyBoolCalculate),
268b9c1b51eSKate Stone           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
26930fdc8d8SChris Lattner 
2709e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
27187df91b8SJim Ingham 
27297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
273b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
27497206d57SZachary Turner       Status error;
275b842f2ecSJim Ingham       const int short_option = g_breakpoint_set_options[option_idx].short_option;
27630fdc8d8SChris Lattner 
277b9c1b51eSKate Stone       switch (short_option) {
278b9c1b51eSKate Stone       case 'a': {
27947cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
280e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
281b9c1b51eSKate Stone       } break;
28230fdc8d8SChris Lattner 
283e732052fSJim Ingham       case 'A':
284e732052fSJim Ingham         m_all_files = true;
285e732052fSJim Ingham         break;
286e732052fSJim Ingham 
287ca36cd16SJim Ingham       case 'b':
288ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
289ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
290ca36cd16SJim Ingham         break;
291ca36cd16SJim Ingham 
292fe11483bSZachary Turner       case 'C':
293fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
294b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
295fe11483bSZachary Turner                                          option_arg.str().c_str());
29630fdc8d8SChris Lattner         break;
2979e85e5a8SEugene Zelenko 
298b9c1b51eSKate Stone       case 'E': {
299fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
300fab10e89SJim Ingham 
301b9c1b51eSKate Stone         switch (language) {
302fab10e89SJim Ingham         case eLanguageTypeC89:
303fab10e89SJim Ingham         case eLanguageTypeC:
304fab10e89SJim Ingham         case eLanguageTypeC99:
3051d0089faSBruce Mitchener         case eLanguageTypeC11:
306a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
307fab10e89SJim Ingham           break;
308fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
3091d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
3101d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
3112ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
312a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
313fab10e89SJim Ingham           break;
314fab10e89SJim Ingham         case eLanguageTypeObjC:
315a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
316fab10e89SJim Ingham           break;
317fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
318b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
319b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
320fab10e89SJim Ingham           break;
321fab10e89SJim Ingham         case eLanguageTypeUnknown:
322b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
323b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
324fe11483bSZachary Turner               option_arg.str().c_str());
325fab10e89SJim Ingham           break;
326fab10e89SJim Ingham         default:
327b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
328b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
329fe11483bSZachary Turner               option_arg.str().c_str());
330fab10e89SJim Ingham         }
331b9c1b51eSKate Stone       } break;
332ca36cd16SJim Ingham 
333ca36cd16SJim Ingham       case 'f':
3348f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
335fab10e89SJim Ingham         break;
336ca36cd16SJim Ingham 
337ca36cd16SJim Ingham       case 'F':
338ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
339ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
340ca36cd16SJim Ingham         break;
341ca36cd16SJim Ingham 
342b9c1b51eSKate Stone       case 'h': {
343fab10e89SJim Ingham         bool success;
34447cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
345fab10e89SJim Ingham         if (!success)
346b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
347fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
348fe11483bSZachary Turner               option_arg.str().c_str());
349b9c1b51eSKate Stone       } break;
350eb023e75SGreg Clayton 
351eb023e75SGreg Clayton       case 'H':
352eb023e75SGreg Clayton         m_hardware = true;
353eb023e75SGreg Clayton         break;
354eb023e75SGreg Clayton 
3553815e702SJim Ingham       case 'k': {
3563815e702SJim Ingham           if (m_current_key.empty())
3573815e702SJim Ingham             m_current_key.assign(option_arg);
3583815e702SJim Ingham           else
3593815e702SJim Ingham             error.SetErrorStringWithFormat("Key: %s missing value.",
3603815e702SJim Ingham                                             m_current_key.c_str());
3613815e702SJim Ingham 
3623815e702SJim Ingham       } break;
363b9c1b51eSKate Stone       case 'K': {
364a8558b62SJim Ingham         bool success;
365a8558b62SJim Ingham         bool value;
36647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
367a8558b62SJim Ingham         if (value)
368a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
369a8558b62SJim Ingham         else
370a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
371a8558b62SJim Ingham 
372a8558b62SJim Ingham         if (!success)
373b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
374b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
375fe11483bSZachary Turner               option_arg.str().c_str());
376b9c1b51eSKate Stone       } break;
377ca36cd16SJim Ingham 
378fe11483bSZachary Turner       case 'l':
379fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
380b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
381fe11483bSZachary Turner                                          option_arg.str().c_str());
382ca36cd16SJim Ingham         break;
383055ad9beSIlia K 
38423b1decbSDawn Perchik       case 'L':
385fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
38623b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
387b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
388fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
389fe11483bSZachary Turner               option_arg.str().c_str());
39023b1decbSDawn Perchik         break;
39123b1decbSDawn Perchik 
392b9c1b51eSKate Stone       case 'm': {
393055ad9beSIlia K         bool success;
394055ad9beSIlia K         bool value;
39547cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
396055ad9beSIlia K         if (value)
397055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
398055ad9beSIlia K         else
399055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
400055ad9beSIlia K 
401055ad9beSIlia K         if (!success)
402b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
403b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
404fe11483bSZachary Turner               option_arg.str().c_str());
405055ad9beSIlia K         break;
406055ad9beSIlia K       }
407055ad9beSIlia K 
408ca36cd16SJim Ingham       case 'M':
409ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
410ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
411ca36cd16SJim Ingham         break;
412ca36cd16SJim Ingham 
413ca36cd16SJim Ingham       case 'n':
414ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
415ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
416ca36cd16SJim Ingham         break;
417ca36cd16SJim Ingham 
4186fa7681bSZachary Turner       case 'N': {
419fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
4205e09c8c3SJim Ingham           m_breakpoint_names.push_back(option_arg);
421ff9a91eaSJim Ingham         else
422ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
423fe11483bSZachary Turner                                          option_arg.str().c_str());
4245e09c8c3SJim Ingham         break;
4256fa7681bSZachary Turner       }
4265e09c8c3SJim Ingham 
427b9c1b51eSKate Stone       case 'R': {
4282411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
42947cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
43047cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4312411167fSJim Ingham         if (error.Success())
4322411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
433b9c1b51eSKate Stone       } break;
4342411167fSJim Ingham 
435a72b31c7SJim Ingham       case 'O':
436fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
437fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
438a72b31c7SJim Ingham         break;
439a72b31c7SJim Ingham 
440ca36cd16SJim Ingham       case 'p':
441ca36cd16SJim Ingham         m_source_text_regexp.assign(option_arg);
442ca36cd16SJim Ingham         break;
443ca36cd16SJim Ingham 
4443815e702SJim Ingham       case 'P':
4453815e702SJim Ingham         m_python_class.assign(option_arg);
4463815e702SJim Ingham         break;
4473815e702SJim Ingham 
448ca36cd16SJim Ingham       case 'r':
449ca36cd16SJim Ingham         m_func_regexp.assign(option_arg);
450ca36cd16SJim Ingham         break;
451ca36cd16SJim Ingham 
452ca36cd16SJim Ingham       case 's':
4538f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
454ca36cd16SJim Ingham         break;
455ca36cd16SJim Ingham 
456ca36cd16SJim Ingham       case 'S':
457ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
458ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
459ca36cd16SJim Ingham         break;
460ca36cd16SJim Ingham 
4613815e702SJim Ingham       case 'v': {
4623815e702SJim Ingham           if (!m_current_key.empty()) {
4633815e702SJim Ingham               m_extra_args_sp->AddStringItem(m_current_key, option_arg);
4643815e702SJim Ingham               m_current_key.clear();
4653815e702SJim Ingham           }
4663815e702SJim Ingham           else
4673815e702SJim Ingham             error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
4683815e702SJim Ingham                                            option_arg.str().c_str());
4693815e702SJim Ingham       } break;
4703815e702SJim Ingham 
471b9c1b51eSKate Stone       case 'w': {
472ca36cd16SJim Ingham         bool success;
47347cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
474ca36cd16SJim Ingham         if (!success)
475b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
476fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
477fe11483bSZachary Turner               option_arg.str().c_str());
478b9c1b51eSKate Stone       } break;
479ca36cd16SJim Ingham 
48076bb8d67SJim Ingham       case 'X':
48176bb8d67SJim Ingham         m_source_regex_func_names.insert(option_arg);
48276bb8d67SJim Ingham         break;
48376bb8d67SJim Ingham 
48430fdc8d8SChris Lattner       default:
48536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
48630fdc8d8SChris Lattner       }
48730fdc8d8SChris Lattner 
48830fdc8d8SChris Lattner       return error;
48930fdc8d8SChris Lattner     }
4909e85e5a8SEugene Zelenko 
491b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
49287df91b8SJim Ingham       m_filenames.Clear();
49330fdc8d8SChris Lattner       m_line_num = 0;
49430fdc8d8SChris Lattner       m_column = 0;
495fab10e89SJim Ingham       m_func_names.clear();
4961f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
49730fdc8d8SChris Lattner       m_func_regexp.clear();
4981f746071SGreg Clayton       m_source_text_regexp.clear();
49987df91b8SJim Ingham       m_modules.Clear();
5001f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
5012411167fSJim Ingham       m_offset_addr = 0;
502fab10e89SJim Ingham       m_catch_bp = false;
503fab10e89SJim Ingham       m_throw_bp = true;
504eb023e75SGreg Clayton       m_hardware = false;
505a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
50623b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
507a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
5085e09c8c3SJim Ingham       m_breakpoint_names.clear();
509e732052fSJim Ingham       m_all_files = false;
510a72b31c7SJim Ingham       m_exception_extra_args.Clear();
511055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
51276bb8d67SJim Ingham       m_source_regex_func_names.clear();
5133815e702SJim Ingham       m_python_class.clear();
514796ac80bSJonas Devlieghere       m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
5153815e702SJim Ingham       m_current_key.clear();
51630fdc8d8SChris Lattner     }
51730fdc8d8SChris Lattner 
5181f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
51970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
5201f0f5b5bSZachary Turner     }
52130fdc8d8SChris Lattner 
5225a988416SJim Ingham     // Instance variables to hold the values for command options.
523969795f1SJim Ingham 
5245a988416SJim Ingham     std::string m_condition;
5255a988416SJim Ingham     FileSpecList m_filenames;
5265a988416SJim Ingham     uint32_t m_line_num;
5275a988416SJim Ingham     uint32_t m_column;
5285a988416SJim Ingham     std::vector<std::string> m_func_names;
5295e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
530117b1fa1SZachary Turner     lldb::FunctionNameType m_func_name_type_mask;
5315a988416SJim Ingham     std::string m_func_regexp;
5325a988416SJim Ingham     std::string m_source_text_regexp;
5335a988416SJim Ingham     FileSpecList m_modules;
5345a988416SJim Ingham     lldb::addr_t m_load_addr;
5352411167fSJim Ingham     lldb::addr_t m_offset_addr;
5365a988416SJim Ingham     bool m_catch_bp;
5375a988416SJim Ingham     bool m_throw_bp;
538eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
539a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
54023b1decbSDawn Perchik     lldb::LanguageType m_language;
5415a988416SJim Ingham     LazyBool m_skip_prologue;
542e732052fSJim Ingham     bool m_all_files;
543a72b31c7SJim Ingham     Args m_exception_extra_args;
544055ad9beSIlia K     LazyBool m_move_to_nearest_code;
54576bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5463815e702SJim Ingham     std::string m_python_class;
5473815e702SJim Ingham     StructuredData::DictionarySP m_extra_args_sp;
5483815e702SJim Ingham     std::string m_current_key;
5495a988416SJim Ingham   };
5505a988416SJim Ingham 
5515a988416SJim Ingham protected:
552b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
553cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
55430fdc8d8SChris Lattner 
55530fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
55630fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
55730fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
55830fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
559b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
560b9c1b51eSKate Stone     //   expression)
561b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
562b9c1b51eSKate Stone     //   to source text)
563b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
564b9c1b51eSKate Stone     //   given language.)
56530fdc8d8SChris Lattner 
56630fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
56730fdc8d8SChris Lattner 
5683815e702SJim Ingham     if (!m_options.m_python_class.empty())
5693815e702SJim Ingham       break_type = eSetTypeScripted;
5703815e702SJim Ingham     else if (m_options.m_line_num != 0)
57130fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
57230fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
57330fdc8d8SChris Lattner       break_type = eSetTypeAddress;
574fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
57530fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
57630fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
57730fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
578969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
579969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
580a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
581fab10e89SJim Ingham       break_type = eSetTypeException;
58230fdc8d8SChris Lattner 
583b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
584274060b6SGreg Clayton     FileSpec module_spec;
585a8558b62SJim Ingham     const bool internal = false;
586a8558b62SJim Ingham 
587b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
588b9c1b51eSKate Stone     // that off.
589b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
590b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5912411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5922411167fSJim Ingham 
593b9c1b51eSKate Stone     switch (break_type) {
59430fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
59530fdc8d8SChris Lattner     {
59630fdc8d8SChris Lattner       FileSpec file;
597c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
598b9c1b51eSKate Stone       if (num_files == 0) {
599b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
60087df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
60187df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
60287df91b8SJim Ingham           return false;
60387df91b8SJim Ingham         }
604b9c1b51eSKate Stone       } else if (num_files > 1) {
605b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
606b9c1b51eSKate Stone                            "line breakpoints.");
60787df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
60887df91b8SJim Ingham         return false;
609b9c1b51eSKate Stone       } else
61087df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
61130fdc8d8SChris Lattner 
6121f746071SGreg Clayton       // Only check for inline functions if
6131f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
6141f746071SGreg Clayton 
615cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
616cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
617cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
618cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
619b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
620b9c1b51eSKate Stone     } break;
6216eee5aa0SGreg Clayton 
62230fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
623055a08a4SJim Ingham     {
624b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
625b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
626b842f2ecSJim Ingham       //  will track the load location of the library.
627055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
628b9c1b51eSKate Stone       if (num_modules_specified == 1) {
629b9c1b51eSKate Stone         const FileSpec *file_spec =
630b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
631cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
632cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
633b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
634cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
635b842f2ecSJim Ingham                                         m_options.m_hardware);
636b9c1b51eSKate Stone       } else {
637b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
638b9c1b51eSKate Stone                            "address breakpoints.");
639055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
640055a08a4SJim Ingham         return false;
641055a08a4SJim Ingham       }
64230fdc8d8SChris Lattner       break;
643055a08a4SJim Ingham     }
64430fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6450c5cd90dSGreg Clayton     {
646117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6470c5cd90dSGreg Clayton 
6480c5cd90dSGreg Clayton       if (name_type_mask == 0)
649e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6500c5cd90dSGreg Clayton 
651cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
652cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
653cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
654cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
655b842f2ecSJim Ingham           m_options.m_hardware);
656b9c1b51eSKate Stone     } break;
6570c5cd90dSGreg Clayton 
658b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
659b9c1b51eSKate Stone                                  // name
66030fdc8d8SChris Lattner       {
66195eae423SZachary Turner         RegularExpression regexp(m_options.m_func_regexp);
6623af3f1e8SJonas Devlieghere         if (llvm::Error err = regexp.GetError()) {
663b9c1b51eSKate Stone           result.AppendErrorWithFormat(
664b9c1b51eSKate Stone               "Function name regular expression could not be compiled: \"%s\"",
6653af3f1e8SJonas Devlieghere               llvm::toString(std::move(err)).c_str());
66630fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
667969795f1SJim Ingham           return false;
66830fdc8d8SChris Lattner         }
66987df91b8SJim Ingham 
670cb2380c9SRaphael Isemann         bp_sp = target.CreateFuncRegexBreakpoint(
6715aa1d819SJan Kratochvil             &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
672cb2380c9SRaphael Isemann             m_options.m_language, m_options.m_skip_prologue, internal,
673b842f2ecSJim Ingham             m_options.m_hardware);
674e14dc268SJim Ingham       }
675e14dc268SJim Ingham       break;
676969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
677969795f1SJim Ingham     {
678c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
67987df91b8SJim Ingham 
680b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
681969795f1SJim Ingham         FileSpec file;
682b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
683b9c1b51eSKate Stone           result.AppendError(
684b9c1b51eSKate Stone               "No files provided and could not find default file.");
68587df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
68687df91b8SJim Ingham           return false;
687b9c1b51eSKate Stone         } else {
68887df91b8SJim Ingham           m_options.m_filenames.Append(file);
68987df91b8SJim Ingham         }
69087df91b8SJim Ingham       }
6910c5cd90dSGreg Clayton 
69295eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6933af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
694b9c1b51eSKate Stone         result.AppendErrorWithFormat(
695b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6963af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
697969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
698969795f1SJim Ingham         return false;
699969795f1SJim Ingham       }
700cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
701cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
7025aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
703cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
704b9c1b51eSKate Stone     } break;
705b9c1b51eSKate Stone     case eSetTypeException: {
70697206d57SZachary Turner       Status precond_error;
707cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
708cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
709cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
710b842f2ecSJim Ingham           &precond_error);
711b9c1b51eSKate Stone       if (precond_error.Fail()) {
712b9c1b51eSKate Stone         result.AppendErrorWithFormat(
713b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
714a72b31c7SJim Ingham             precond_error.AsCString());
715cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
716a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
717a72b31c7SJim Ingham         return false;
718a72b31c7SJim Ingham       }
719b9c1b51eSKate Stone     } break;
7203815e702SJim Ingham     case eSetTypeScripted: {
7213815e702SJim Ingham 
7223815e702SJim Ingham       Status error;
723cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
724cb2380c9SRaphael Isemann           m_options.m_python_class, &(m_options.m_modules),
725cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
726cb2380c9SRaphael Isemann           m_options.m_extra_args_sp, &error);
7273815e702SJim Ingham       if (error.Fail()) {
7283815e702SJim Ingham         result.AppendErrorWithFormat(
7293815e702SJim Ingham             "Error setting extra exception arguments: %s",
7303815e702SJim Ingham             error.AsCString());
731cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7323815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
7333815e702SJim Ingham         return false;
7343815e702SJim Ingham       }
7353815e702SJim Ingham     } break;
73630fdc8d8SChris Lattner     default:
73730fdc8d8SChris Lattner       break;
73830fdc8d8SChris Lattner     }
73930fdc8d8SChris Lattner 
7401b54c88cSJim Ingham     // Now set the various options that were passed in:
741b842f2ecSJim Ingham     if (bp_sp) {
742b842f2ecSJim Ingham       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
743ca36cd16SJim Ingham 
744b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
74597206d57SZachary Turner         Status name_error;
746ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
747cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
748ff9a91eaSJim Ingham           if (name_error.Fail()) {
749ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
750ff9a91eaSJim Ingham                                          name.c_str());
751cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
752ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
753ff9a91eaSJim Ingham             return false;
754ff9a91eaSJim Ingham           }
755ff9a91eaSJim Ingham         }
7565e09c8c3SJim Ingham       }
7571b54c88cSJim Ingham     }
7581b54c88cSJim Ingham 
759b842f2ecSJim Ingham     if (bp_sp) {
76085e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7611391cc7dSJim Ingham       const bool show_locations = false;
762b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
763b9c1b51eSKate Stone                          show_locations);
764cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
765b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
766b9c1b51eSKate Stone                              "into future targets.\n");
767b9c1b51eSKate Stone       else {
76805097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
76905097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
77005097246SAdrian Prantl         // set the breakpoint till we run.
771b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
772b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
773b9c1b51eSKate Stone                                "actual locations.\n");
7744aeb1989SJim Ingham         }
7754aeb1989SJim Ingham       }
77630fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
777b842f2ecSJim Ingham     } else if (!bp_sp) {
77830fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
77930fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
78030fdc8d8SChris Lattner     }
78130fdc8d8SChris Lattner 
78230fdc8d8SChris Lattner     return result.Succeeded();
78330fdc8d8SChris Lattner   }
78430fdc8d8SChris Lattner 
7855a988416SJim Ingham private:
786cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
787b9c1b51eSKate Stone                       CommandReturnObject &result) {
7885a988416SJim Ingham     uint32_t default_line;
78905097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
79005097246SAdrian Prantl     // frame's file.
791cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
792b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
793b9c1b51eSKate Stone       if (cur_frame == nullptr) {
794b9c1b51eSKate Stone         result.AppendError(
795b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7965a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7975a988416SJim Ingham         return false;
798b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
799b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
800b9c1b51eSKate Stone                            "file, it has no debug info.");
8015a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
8025a988416SJim Ingham         return false;
803b9c1b51eSKate Stone       } else {
804b9c1b51eSKate Stone         const SymbolContext &sc =
805b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
806b9c1b51eSKate Stone         if (sc.line_entry.file) {
8075a988416SJim Ingham           file = sc.line_entry.file;
808b9c1b51eSKate Stone         } else {
809b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
810b9c1b51eSKate Stone                              "use as the default file.");
8115a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
8125a988416SJim Ingham           return false;
8135a988416SJim Ingham         }
8145a988416SJim Ingham       }
8155a988416SJim Ingham     }
8165a988416SJim Ingham     return true;
8175a988416SJim Ingham   }
8185a988416SJim Ingham 
819b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
820b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
8215a988416SJim Ingham   CommandOptions m_options;
822b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
8235a988416SJim Ingham };
8249e85e5a8SEugene Zelenko 
8255a988416SJim Ingham // CommandObjectBreakpointModify
8265a988416SJim Ingham #pragma mark Modify
8275a988416SJim Ingham 
828b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8295a988416SJim Ingham public:
830b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
831b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
832b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
833b9c1b51eSKate Stone                             "breakpoints in the executable.  "
834b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
835b9c1b51eSKate Stone                             "created breakpoint.  "
836b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
837b9c1b51eSKate Stone                             "empty argument clears the modification.",
8389e85e5a8SEugene Zelenko                             nullptr),
839b9c1b51eSKate Stone         m_options() {
8405a988416SJim Ingham     CommandArgumentEntry arg;
841b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
842b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
843b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
844b9c1b51eSKate Stone     // arguments vector.
8455a988416SJim Ingham     m_arguments.push_back(arg);
846b842f2ecSJim Ingham 
847b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
848b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
849b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
850b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
851b842f2ecSJim Ingham     m_options.Finalize();
8525a988416SJim Ingham   }
8535a988416SJim Ingham 
8549e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8555a988416SJim Ingham 
856b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8575a988416SJim Ingham 
8585a988416SJim Ingham protected:
859b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
860cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8615a988416SJim Ingham 
862bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
863cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8645a988416SJim Ingham 
8655a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8665a988416SJim Ingham 
867b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
868cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
869b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8705a988416SJim Ingham 
871b9c1b51eSKate Stone     if (result.Succeeded()) {
8725a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
873b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8745a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8755a988416SJim Ingham 
876b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
877b9c1b51eSKate Stone           Breakpoint *bp =
878cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
879b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
880b9c1b51eSKate Stone             BreakpointLocation *location =
881b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
882b842f2ecSJim Ingham             if (location)
883b842f2ecSJim Ingham               location->GetLocationOptions()
884b842f2ecSJim Ingham                   ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
885b9c1b51eSKate Stone           } else {
886b842f2ecSJim Ingham             bp->GetOptions()
887b842f2ecSJim Ingham                 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
8885a988416SJim Ingham           }
8895a988416SJim Ingham         }
8905a988416SJim Ingham       }
8915a988416SJim Ingham     }
8925a988416SJim Ingham 
8935a988416SJim Ingham     return result.Succeeded();
8945a988416SJim Ingham   }
8955a988416SJim Ingham 
8965a988416SJim Ingham private:
897b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
898b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
899b842f2ecSJim Ingham   OptionGroupOptions m_options;
9005a988416SJim Ingham };
9015a988416SJim Ingham 
9025a988416SJim Ingham // CommandObjectBreakpointEnable
9035a988416SJim Ingham #pragma mark Enable
9045a988416SJim Ingham 
905b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
9065a988416SJim Ingham public:
907b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
908b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
909b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
910b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
911b9c1b51eSKate Stone                             nullptr) {
9125a988416SJim Ingham     CommandArgumentEntry arg;
913b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
914b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
915b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
916b9c1b51eSKate Stone     // arguments vector.
9175a988416SJim Ingham     m_arguments.push_back(arg);
9185a988416SJim Ingham   }
9195a988416SJim Ingham 
9209e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9215a988416SJim Ingham 
9225a988416SJim Ingham protected:
923b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
924cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9255a988416SJim Ingham 
926bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
927cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9285a988416SJim Ingham 
929cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9305a988416SJim Ingham 
9315a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9325a988416SJim Ingham 
933b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9345a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9355a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9365a988416SJim Ingham       return false;
9375a988416SJim Ingham     }
9385a988416SJim Ingham 
93911eb9c64SZachary Turner     if (command.empty()) {
9405a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
941cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
942b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
943b9c1b51eSKate Stone                                      " breakpoints)\n",
944b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9455a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
946b9c1b51eSKate Stone     } else {
9475a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9485a988416SJim Ingham       BreakpointIDList valid_bp_ids;
949b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
950cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
951b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9525a988416SJim Ingham 
953b9c1b51eSKate Stone       if (result.Succeeded()) {
9545a988416SJim Ingham         int enable_count = 0;
9555a988416SJim Ingham         int loc_count = 0;
9565a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
957b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9585a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9595a988416SJim Ingham 
960b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
961b9c1b51eSKate Stone             Breakpoint *breakpoint =
962cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
963b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
964b9c1b51eSKate Stone               BreakpointLocation *location =
965b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
966b9c1b51eSKate Stone               if (location) {
9675a988416SJim Ingham                 location->SetEnabled(true);
9685a988416SJim Ingham                 ++loc_count;
9695a988416SJim Ingham               }
970b9c1b51eSKate Stone             } else {
9715a988416SJim Ingham               breakpoint->SetEnabled(true);
9725a988416SJim Ingham               ++enable_count;
9735a988416SJim Ingham             }
9745a988416SJim Ingham           }
9755a988416SJim Ingham         }
976b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
977b9c1b51eSKate Stone                                        enable_count + loc_count);
9785a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9795a988416SJim Ingham       }
9805a988416SJim Ingham     }
9815a988416SJim Ingham 
9825a988416SJim Ingham     return result.Succeeded();
9835a988416SJim Ingham   }
9845a988416SJim Ingham };
9855a988416SJim Ingham 
9865a988416SJim Ingham // CommandObjectBreakpointDisable
9875a988416SJim Ingham #pragma mark Disable
9885a988416SJim Ingham 
989b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9905a988416SJim Ingham public:
9917428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
992b9c1b51eSKate Stone       : CommandObjectParsed(
993b9c1b51eSKate Stone             interpreter, "breakpoint disable",
994b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9957428a18cSKate Stone             "them.  If none are specified, disable all "
9967428a18cSKate Stone             "breakpoints.",
997b9c1b51eSKate Stone             nullptr) {
998b9c1b51eSKate Stone     SetHelpLong(
999b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
10007428a18cSKate Stone If none are specified, disable all breakpoints."
10017428a18cSKate Stone         R"(
1002ea671fbdSKate Stone 
10037428a18cSKate Stone )"
10047428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
10057428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
10067428a18cSKate Stone         R"(
1007ea671fbdSKate Stone 
1008ea671fbdSKate Stone     (lldb) break disable 1
1009ea671fbdSKate Stone     (lldb) break enable 1.1
1010ea671fbdSKate Stone 
1011ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1012ea671fbdSKate Stone 
1013ea671fbdSKate Stone     (lldb) break disable 1.*
1014ea671fbdSKate Stone     (lldb) break enable 1.1
1015ea671fbdSKate Stone 
10167428a18cSKate Stone )"
10177428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10187428a18cSKate Stone the second re-enables the first location.");
1019b0fac509SJim Ingham 
10205a988416SJim Ingham     CommandArgumentEntry arg;
1021b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1022b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1023b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1024b9c1b51eSKate Stone     // arguments vector.
10255a988416SJim Ingham     m_arguments.push_back(arg);
10265a988416SJim Ingham   }
10275a988416SJim Ingham 
10289e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10295a988416SJim Ingham 
10305a988416SJim Ingham protected:
1031b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1032cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1033bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1034cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10355a988416SJim Ingham 
1036cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10375a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10385a988416SJim Ingham 
1039b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10405a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10415a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10425a988416SJim Ingham       return false;
10435a988416SJim Ingham     }
10445a988416SJim Ingham 
104511eb9c64SZachary Turner     if (command.empty()) {
10465a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1047cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1048b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1049b9c1b51eSKate Stone                                      " breakpoints)\n",
1050b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10515a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1052b9c1b51eSKate Stone     } else {
10535a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10545a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10555a988416SJim Ingham 
1056b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1057cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1058b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10595a988416SJim Ingham 
1060b9c1b51eSKate Stone       if (result.Succeeded()) {
10615a988416SJim Ingham         int disable_count = 0;
10625a988416SJim Ingham         int loc_count = 0;
10635a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1064b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10655a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10665a988416SJim Ingham 
1067b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1068b9c1b51eSKate Stone             Breakpoint *breakpoint =
1069cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1070b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1071b9c1b51eSKate Stone               BreakpointLocation *location =
1072b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1073b9c1b51eSKate Stone               if (location) {
10745a988416SJim Ingham                 location->SetEnabled(false);
10755a988416SJim Ingham                 ++loc_count;
10765a988416SJim Ingham               }
1077b9c1b51eSKate Stone             } else {
10785a988416SJim Ingham               breakpoint->SetEnabled(false);
10795a988416SJim Ingham               ++disable_count;
10805a988416SJim Ingham             }
10815a988416SJim Ingham           }
10825a988416SJim Ingham         }
1083b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1084b9c1b51eSKate Stone                                        disable_count + loc_count);
10855a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10865a988416SJim Ingham       }
10875a988416SJim Ingham     }
10885a988416SJim Ingham 
10895a988416SJim Ingham     return result.Succeeded();
10905a988416SJim Ingham   }
10915a988416SJim Ingham };
10925a988416SJim Ingham 
10935a988416SJim Ingham // CommandObjectBreakpointList
10941f0f5b5bSZachary Turner 
10951f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10966f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1097c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10981f0f5b5bSZachary Turner 
10995a988416SJim Ingham #pragma mark List
11005a988416SJim Ingham 
1101b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
11025a988416SJim Ingham public:
1103b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1104b9c1b51eSKate Stone       : CommandObjectParsed(
1105b9c1b51eSKate Stone             interpreter, "breakpoint list",
11065a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
11079e85e5a8SEugene Zelenko             nullptr),
1108b9c1b51eSKate Stone         m_options() {
11095a988416SJim Ingham     CommandArgumentEntry arg;
11105a988416SJim Ingham     CommandArgumentData bp_id_arg;
11115a988416SJim Ingham 
11125a988416SJim Ingham     // Define the first (and only) variant of this arg.
11135a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11145a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11155a988416SJim Ingham 
1116b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1117b9c1b51eSKate Stone     // argument entry.
11185a988416SJim Ingham     arg.push_back(bp_id_arg);
11195a988416SJim Ingham 
11205a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11215a988416SJim Ingham     m_arguments.push_back(arg);
11225a988416SJim Ingham   }
11235a988416SJim Ingham 
11249e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11255a988416SJim Ingham 
1126b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11275a988416SJim Ingham 
1128b9c1b51eSKate Stone   class CommandOptions : public Options {
11295a988416SJim Ingham   public:
1130b9c1b51eSKate Stone     CommandOptions()
1131b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
11325a988416SJim Ingham     }
11335a988416SJim Ingham 
11349e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11355a988416SJim Ingham 
113697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1137b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
113897206d57SZachary Turner       Status error;
11393bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11405a988416SJim Ingham 
1141b9c1b51eSKate Stone       switch (short_option) {
11425a988416SJim Ingham       case 'b':
11435a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11445a988416SJim Ingham         break;
114533df7cd3SJim Ingham       case 'D':
114633df7cd3SJim Ingham         m_use_dummy = true;
114733df7cd3SJim Ingham         break;
11485a988416SJim Ingham       case 'f':
11495a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11505a988416SJim Ingham         break;
11515a988416SJim Ingham       case 'v':
11525a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11535a988416SJim Ingham         break;
11545a988416SJim Ingham       case 'i':
11555a988416SJim Ingham         m_internal = true;
11565a988416SJim Ingham         break;
11575a988416SJim Ingham       default:
115836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11595a988416SJim Ingham       }
11605a988416SJim Ingham 
11615a988416SJim Ingham       return error;
11625a988416SJim Ingham     }
11635a988416SJim Ingham 
1164b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11655a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11665a988416SJim Ingham       m_internal = false;
116733df7cd3SJim Ingham       m_use_dummy = false;
11685a988416SJim Ingham     }
11695a988416SJim Ingham 
11701f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
117170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11721f0f5b5bSZachary Turner     }
11735a988416SJim Ingham 
11745a988416SJim Ingham     // Instance variables to hold the values for command options.
11755a988416SJim Ingham 
11765a988416SJim Ingham     lldb::DescriptionLevel m_level;
11775a988416SJim Ingham 
11785a988416SJim Ingham     bool m_internal;
117933df7cd3SJim Ingham     bool m_use_dummy;
11805a988416SJim Ingham   };
11815a988416SJim Ingham 
11825a988416SJim Ingham protected:
1183b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1184cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11855a988416SJim Ingham 
1186b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1187cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1188bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1189cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11905a988416SJim Ingham 
11915a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11925a988416SJim Ingham 
1193b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11945a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11955a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11965a988416SJim Ingham       return true;
11975a988416SJim Ingham     }
11985a988416SJim Ingham 
11995a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
12005a988416SJim Ingham 
120111eb9c64SZachary Turner     if (command.empty()) {
12025a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
12035a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1204b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
12055a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1206b842f2ecSJim Ingham         if (breakpoint->AllowList())
1207b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1208b842f2ecSJim Ingham                                    m_options.m_level);
12095a988416SJim Ingham       }
12105a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1211b9c1b51eSKate Stone     } else {
12125a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12135a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1214b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1215cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1216b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12175a988416SJim Ingham 
1218b9c1b51eSKate Stone       if (result.Succeeded()) {
1219b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12205a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1221b9c1b51eSKate Stone           Breakpoint *breakpoint =
1222cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1223b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1224b9c1b51eSKate Stone                                    m_options.m_level);
12255a988416SJim Ingham         }
12265a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1227b9c1b51eSKate Stone       } else {
12287428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12295a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
12305a988416SJim Ingham       }
12315a988416SJim Ingham     }
12325a988416SJim Ingham 
12335a988416SJim Ingham     return result.Succeeded();
12345a988416SJim Ingham   }
12355a988416SJim Ingham 
12365a988416SJim Ingham private:
12375a988416SJim Ingham   CommandOptions m_options;
12385a988416SJim Ingham };
12395a988416SJim Ingham 
12405a988416SJim Ingham // CommandObjectBreakpointClear
12411f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12421f0f5b5bSZachary Turner 
1243f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1244f94668e3SRaphael Isemann #include "CommandOptions.inc"
12451f0f5b5bSZachary Turner 
12465a988416SJim Ingham #pragma mark Clear
12475a988416SJim Ingham 
1248b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12495a988416SJim Ingham public:
1250efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12515a988416SJim Ingham 
12527428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12537428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1254b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1255b9c1b51eSKate Stone                             "specified source file and line.",
12565a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1257b9c1b51eSKate Stone         m_options() {}
12585a988416SJim Ingham 
12599e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12605a988416SJim Ingham 
1261b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12625a988416SJim Ingham 
1263b9c1b51eSKate Stone   class CommandOptions : public Options {
12645a988416SJim Ingham   public:
1265b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
12665a988416SJim Ingham 
12679e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12685a988416SJim Ingham 
126997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1270b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
127197206d57SZachary Turner       Status error;
12723bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12735a988416SJim Ingham 
1274b9c1b51eSKate Stone       switch (short_option) {
12755a988416SJim Ingham       case 'f':
12765a988416SJim Ingham         m_filename.assign(option_arg);
12775a988416SJim Ingham         break;
12785a988416SJim Ingham 
12795a988416SJim Ingham       case 'l':
1280fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12815a988416SJim Ingham         break;
12825a988416SJim Ingham 
12835a988416SJim Ingham       default:
128436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12855a988416SJim Ingham       }
12865a988416SJim Ingham 
12875a988416SJim Ingham       return error;
12885a988416SJim Ingham     }
12895a988416SJim Ingham 
1290b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12915a988416SJim Ingham       m_filename.clear();
12925a988416SJim Ingham       m_line_num = 0;
12935a988416SJim Ingham     }
12945a988416SJim Ingham 
12951f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
129670602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12971f0f5b5bSZachary Turner     }
12985a988416SJim Ingham 
12995a988416SJim Ingham     // Instance variables to hold the values for command options.
13005a988416SJim Ingham 
13015a988416SJim Ingham     std::string m_filename;
13025a988416SJim Ingham     uint32_t m_line_num;
13035a988416SJim Ingham   };
13045a988416SJim Ingham 
13055a988416SJim Ingham protected:
1306b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1307cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
13085a988416SJim Ingham 
130905097246SAdrian Prantl     // The following are the various types of breakpoints that could be
131005097246SAdrian Prantl     // cleared:
13115a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13125a988416SJim Ingham 
13135a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13145a988416SJim Ingham 
13155a988416SJim Ingham     if (m_options.m_line_num != 0)
13165a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13175a988416SJim Ingham 
1318bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1319cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13205a988416SJim Ingham 
1321cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13225a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13235a988416SJim Ingham 
13245a988416SJim Ingham     // Early return if there's no breakpoint at all.
1325b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13265a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13275a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13285a988416SJim Ingham       return result.Succeeded();
13295a988416SJim Ingham     }
13305a988416SJim Ingham 
13315a988416SJim Ingham     // Find matching breakpoints and delete them.
13325a988416SJim Ingham 
13335a988416SJim Ingham     // First create a copy of all the IDs.
13345a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13355a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13369e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13375a988416SJim Ingham 
13385a988416SJim Ingham     int num_cleared = 0;
13395a988416SJim Ingham     StreamString ss;
1340b9c1b51eSKate Stone     switch (break_type) {
13415a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13425a988416SJim Ingham     {
13435a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13445a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13455a988416SJim Ingham 
1346b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13475a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13485a988416SJim Ingham 
1349b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1350b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1351b9c1b51eSKate Stone           // remove the breakpoint.
1352b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13535a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13545a988416SJim Ingham             ss.EOL();
1355cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13565a988416SJim Ingham             ++num_cleared;
13575a988416SJim Ingham           }
13585a988416SJim Ingham         }
13595a988416SJim Ingham       }
1360b9c1b51eSKate Stone     } break;
13615a988416SJim Ingham 
13625a988416SJim Ingham     default:
13635a988416SJim Ingham       break;
13645a988416SJim Ingham     }
13655a988416SJim Ingham 
1366b9c1b51eSKate Stone     if (num_cleared > 0) {
13675a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13685a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1369c156427dSZachary Turner       output_stream << ss.GetString();
13705a988416SJim Ingham       output_stream.EOL();
13715a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1372b9c1b51eSKate Stone     } else {
13735a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13745a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13755a988416SJim Ingham     }
13765a988416SJim Ingham 
13775a988416SJim Ingham     return result.Succeeded();
13785a988416SJim Ingham   }
13795a988416SJim Ingham 
13805a988416SJim Ingham private:
13815a988416SJim Ingham   CommandOptions m_options;
13825a988416SJim Ingham };
13835a988416SJim Ingham 
13845a988416SJim Ingham // CommandObjectBreakpointDelete
1385f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1386f94668e3SRaphael Isemann #include "CommandOptions.inc"
13871f0f5b5bSZachary Turner 
13885a988416SJim Ingham #pragma mark Delete
13895a988416SJim Ingham 
1390b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13915a988416SJim Ingham public:
1392b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1393b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1394b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1395b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
13969e85e5a8SEugene Zelenko                             nullptr),
1397b9c1b51eSKate Stone         m_options() {
13985a988416SJim Ingham     CommandArgumentEntry arg;
1399b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1400b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1401b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1402b9c1b51eSKate Stone     // arguments vector.
14035a988416SJim Ingham     m_arguments.push_back(arg);
14045a988416SJim Ingham   }
14055a988416SJim Ingham 
14069e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
14075a988416SJim Ingham 
1408b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
140933df7cd3SJim Ingham 
1410b9c1b51eSKate Stone   class CommandOptions : public Options {
141133df7cd3SJim Ingham   public:
1412b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
141333df7cd3SJim Ingham 
14149e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
141533df7cd3SJim Ingham 
141697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1417b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
141897206d57SZachary Turner       Status error;
141933df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
142033df7cd3SJim Ingham 
1421b9c1b51eSKate Stone       switch (short_option) {
142233df7cd3SJim Ingham       case 'f':
142333df7cd3SJim Ingham         m_force = true;
142433df7cd3SJim Ingham         break;
142533df7cd3SJim Ingham 
142633df7cd3SJim Ingham       case 'D':
142733df7cd3SJim Ingham         m_use_dummy = true;
142833df7cd3SJim Ingham         break;
142933df7cd3SJim Ingham 
143033df7cd3SJim Ingham       default:
143136162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
143233df7cd3SJim Ingham       }
143333df7cd3SJim Ingham 
143433df7cd3SJim Ingham       return error;
143533df7cd3SJim Ingham     }
143633df7cd3SJim Ingham 
1437b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
143833df7cd3SJim Ingham       m_use_dummy = false;
143933df7cd3SJim Ingham       m_force = false;
144033df7cd3SJim Ingham     }
144133df7cd3SJim Ingham 
14421f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
144370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14441f0f5b5bSZachary Turner     }
144533df7cd3SJim Ingham 
144633df7cd3SJim Ingham     // Instance variables to hold the values for command options.
144733df7cd3SJim Ingham     bool m_use_dummy;
144833df7cd3SJim Ingham     bool m_force;
144933df7cd3SJim Ingham   };
145033df7cd3SJim Ingham 
14515a988416SJim Ingham protected:
1452b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1453cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14545a988416SJim Ingham 
1455bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1456cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14575a988416SJim Ingham 
1458cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
14595a988416SJim Ingham 
14605a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14615a988416SJim Ingham 
1462b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14635a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14645a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14655a988416SJim Ingham       return false;
14665a988416SJim Ingham     }
14675a988416SJim Ingham 
146811eb9c64SZachary Turner     if (command.empty()) {
1469b9c1b51eSKate Stone       if (!m_options.m_force &&
1470b9c1b51eSKate Stone           !m_interpreter.Confirm(
1471b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1472b9c1b51eSKate Stone               true)) {
14735a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1474b9c1b51eSKate Stone       } else {
1475cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1476b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1477b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1478b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14795a988416SJim Ingham       }
14805a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1481b9c1b51eSKate Stone     } else {
14825a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
14835a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1484b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1485cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1486b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
14875a988416SJim Ingham 
1488b9c1b51eSKate Stone       if (result.Succeeded()) {
14895a988416SJim Ingham         int delete_count = 0;
14905a988416SJim Ingham         int disable_count = 0;
14915a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1492b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
14935a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
14945a988416SJim Ingham 
1495b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1496b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1497b9c1b51eSKate Stone               Breakpoint *breakpoint =
1498cb2380c9SRaphael Isemann                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1499b9c1b51eSKate Stone               BreakpointLocation *location =
1500b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1501b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1502b9c1b51eSKate Stone               // disable them instead.
1503b9c1b51eSKate Stone               if (location) {
15045a988416SJim Ingham                 location->SetEnabled(false);
15055a988416SJim Ingham                 ++disable_count;
15065a988416SJim Ingham               }
1507b9c1b51eSKate Stone             } else {
1508cb2380c9SRaphael Isemann               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15095a988416SJim Ingham               ++delete_count;
15105a988416SJim Ingham             }
15115a988416SJim Ingham           }
15125a988416SJim Ingham         }
1513b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1514b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15155a988416SJim Ingham             delete_count, disable_count);
15165a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
15175a988416SJim Ingham       }
15185a988416SJim Ingham     }
15195a988416SJim Ingham     return result.Succeeded();
15205a988416SJim Ingham   }
15219e85e5a8SEugene Zelenko 
152233df7cd3SJim Ingham private:
152333df7cd3SJim Ingham   CommandOptions m_options;
152433df7cd3SJim Ingham };
152533df7cd3SJim Ingham 
15265e09c8c3SJim Ingham // CommandObjectBreakpointName
1527f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1528f94668e3SRaphael Isemann #include "CommandOptions.inc"
1529bd68a052SRaphael Isemann 
1530b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15315e09c8c3SJim Ingham public:
1532b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1533b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15345e09c8c3SJim Ingham   }
15355e09c8c3SJim Ingham 
15369e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15375e09c8c3SJim Ingham 
15381f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
153970602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15405e09c8c3SJim Ingham   }
15415e09c8c3SJim Ingham 
154297206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1543b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
154497206d57SZachary Turner     Status error;
15455e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15465e09c8c3SJim Ingham 
1547b9c1b51eSKate Stone     switch (short_option) {
15485e09c8c3SJim Ingham     case 'N':
1549fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1550b9c1b51eSKate Stone           error.Success())
1551fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15525e09c8c3SJim Ingham       break;
15535e09c8c3SJim Ingham     case 'B':
1554fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1555b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15568cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1557fe11483bSZachary Turner             option_arg.str().c_str());
15585e09c8c3SJim Ingham       break;
15595e09c8c3SJim Ingham     case 'D':
1560fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1561b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15628cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1563fe11483bSZachary Turner             option_arg.str().c_str());
15645e09c8c3SJim Ingham       break;
1565e9632ebaSJim Ingham     case 'H':
1566e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1567e9632ebaSJim Ingham       break;
15685e09c8c3SJim Ingham 
15695e09c8c3SJim Ingham     default:
157036162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15715e09c8c3SJim Ingham     }
15725e09c8c3SJim Ingham     return error;
15735e09c8c3SJim Ingham   }
15745e09c8c3SJim Ingham 
1575b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
15765e09c8c3SJim Ingham     m_name.Clear();
15775e09c8c3SJim Ingham     m_breakpoint.Clear();
15785e09c8c3SJim Ingham     m_use_dummy.Clear();
15795e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1580e9632ebaSJim Ingham     m_help_string.Clear();
15815e09c8c3SJim Ingham   }
15825e09c8c3SJim Ingham 
15835e09c8c3SJim Ingham   OptionValueString m_name;
15845e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
15855e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1586e9632ebaSJim Ingham   OptionValueString m_help_string;
15875e09c8c3SJim Ingham };
15885e09c8c3SJim Ingham 
1589f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1590f94668e3SRaphael Isemann #include "CommandOptions.inc"
1591b842f2ecSJim Ingham 
15928fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1593b842f2ecSJim Ingham public:
15948fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1595b842f2ecSJim Ingham 
1596b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1597b842f2ecSJim Ingham 
1598b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1599b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1600b842f2ecSJim Ingham   }
1601b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1602b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1603b842f2ecSJim Ingham     Status error;
1604b842f2ecSJim Ingham     const int short_option
1605b842f2ecSJim Ingham         = g_breakpoint_access_options[option_idx].short_option;
1606b842f2ecSJim Ingham 
1607b842f2ecSJim Ingham     switch (short_option) {
1608b842f2ecSJim Ingham       case 'L': {
1609b842f2ecSJim Ingham         bool value, success;
161047cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1611b842f2ecSJim Ingham         if (success) {
1612b842f2ecSJim Ingham           m_permissions.SetAllowList(value);
1613b842f2ecSJim Ingham         } else
1614b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1615b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1616b842f2ecSJim Ingham               option_arg.str().c_str());
1617b842f2ecSJim Ingham       } break;
1618b842f2ecSJim Ingham       case 'A': {
1619b842f2ecSJim Ingham         bool value, success;
162047cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1621b842f2ecSJim Ingham         if (success) {
1622b842f2ecSJim Ingham           m_permissions.SetAllowDisable(value);
1623b842f2ecSJim Ingham         } else
1624b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1625b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1626b842f2ecSJim Ingham               option_arg.str().c_str());
1627b842f2ecSJim Ingham       } break;
1628b842f2ecSJim Ingham       case 'D': {
1629b842f2ecSJim Ingham         bool value, success;
163047cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1631b842f2ecSJim Ingham         if (success) {
1632b842f2ecSJim Ingham           m_permissions.SetAllowDelete(value);
1633b842f2ecSJim Ingham         } else
1634b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1635b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1636b842f2ecSJim Ingham               option_arg.str().c_str());
1637b842f2ecSJim Ingham       } break;
163836162014SRaphael Isemann       default:
163936162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
1640b842f2ecSJim Ingham     }
1641b842f2ecSJim Ingham 
1642b842f2ecSJim Ingham     return error;
1643b842f2ecSJim Ingham   }
1644b842f2ecSJim Ingham 
1645b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
1646b842f2ecSJim Ingham   }
1647b842f2ecSJim Ingham 
1648b842f2ecSJim Ingham   const BreakpointName::Permissions &GetPermissions() const
1649b842f2ecSJim Ingham   {
1650b842f2ecSJim Ingham     return m_permissions;
1651b842f2ecSJim Ingham   }
1652b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1653b842f2ecSJim Ingham };
1654b842f2ecSJim Ingham 
1655b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1656b842f2ecSJim Ingham public:
1657b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1658b842f2ecSJim Ingham       : CommandObjectParsed(
1659b842f2ecSJim Ingham             interpreter, "configure", "Configure the options for the breakpoint"
1660b842f2ecSJim Ingham             " name provided.  "
1661b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1662b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1663b842f2ecSJim Ingham             "on the name.",
1664b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1665b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1666b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1667b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1668b842f2ecSJim Ingham     // command.
1669b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1670b842f2ecSJim Ingham     CommandArgumentData id_arg;
1671b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1672b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1673b842f2ecSJim Ingham     arg1.push_back(id_arg);
1674b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1675b842f2ecSJim Ingham 
1676b842f2ecSJim Ingham     m_option_group.Append(&m_bp_opts,
1677b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1678b842f2ecSJim Ingham                           LLDB_OPT_SET_1);
1679b842f2ecSJim Ingham     m_option_group.Append(&m_access_options,
1680b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1681b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1682e9632ebaSJim Ingham     m_option_group.Append(&m_bp_id,
1683e9632ebaSJim Ingham                           LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1684e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1685b842f2ecSJim Ingham     m_option_group.Finalize();
1686b842f2ecSJim Ingham   }
1687b842f2ecSJim Ingham 
1688b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1689b842f2ecSJim Ingham 
1690b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1691b842f2ecSJim Ingham 
1692b842f2ecSJim Ingham protected:
1693b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1694b842f2ecSJim Ingham 
1695b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1696b842f2ecSJim Ingham     if (argc == 0) {
1697b842f2ecSJim Ingham       result.AppendError("No names provided.");
1698b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1699b842f2ecSJim Ingham       return false;
1700b842f2ecSJim Ingham     }
1701b842f2ecSJim Ingham 
1702cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1703b842f2ecSJim Ingham 
1704b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1705cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1706b842f2ecSJim Ingham 
1707b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1708b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1709b842f2ecSJim Ingham       Status error;
1710*0d9a201eSRaphael Isemann       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error))
1711b842f2ecSJim Ingham       {
1712b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1713b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1714b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1715b842f2ecSJim Ingham         return false;
1716b842f2ecSJim Ingham       }
1717b842f2ecSJim Ingham     }
171805097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
171905097246SAdrian Prantl     // check the error:
1720b842f2ecSJim Ingham     BreakpointSP bp_sp;
1721b842f2ecSJim Ingham     if (m_bp_id.m_breakpoint.OptionWasSet())
1722b842f2ecSJim Ingham     {
1723b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1724cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1725b842f2ecSJim Ingham       if (!bp_sp)
1726b842f2ecSJim Ingham       {
1727b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1728b842f2ecSJim Ingham                            bp_id);
1729b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1730b842f2ecSJim Ingham         return false;
1731b842f2ecSJim Ingham       }
1732b842f2ecSJim Ingham     }
1733b842f2ecSJim Ingham 
1734b842f2ecSJim Ingham     Status error;
1735b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1736b842f2ecSJim Ingham       ConstString name(entry.c_str());
1737cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1738b842f2ecSJim Ingham       if (!bp_name)
1739b842f2ecSJim Ingham         continue;
1740e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1741e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1742e9632ebaSJim Ingham 
1743b842f2ecSJim Ingham       if (bp_sp)
1744cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
1745b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1746b842f2ecSJim Ingham       else
1747cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1748b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1749b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1750b842f2ecSJim Ingham     }
1751b842f2ecSJim Ingham     return true;
1752b842f2ecSJim Ingham   }
1753b842f2ecSJim Ingham 
1754b842f2ecSJim Ingham private:
1755b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1756b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1757b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1758b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1759b842f2ecSJim Ingham };
1760b842f2ecSJim Ingham 
1761b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17625e09c8c3SJim Ingham public:
1763b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1764b9c1b51eSKate Stone       : CommandObjectParsed(
1765b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
17665e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1767b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1768b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1769b9c1b51eSKate Stone     // command.
17705e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17715e09c8c3SJim Ingham     CommandArgumentData id_arg;
17725e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17735e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17745e09c8c3SJim Ingham     arg1.push_back(id_arg);
17755e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17765e09c8c3SJim Ingham 
17775e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17785e09c8c3SJim Ingham     m_option_group.Finalize();
17795e09c8c3SJim Ingham   }
17805e09c8c3SJim Ingham 
17819e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17825e09c8c3SJim Ingham 
1783b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
17845e09c8c3SJim Ingham 
17855e09c8c3SJim Ingham protected:
1786b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1787b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
17885e09c8c3SJim Ingham       result.SetError("No name option provided.");
17895e09c8c3SJim Ingham       return false;
17905e09c8c3SJim Ingham     }
17915e09c8c3SJim Ingham 
1792cb2380c9SRaphael Isemann     Target &target =
1793b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
17945e09c8c3SJim Ingham 
1795bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1796cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
17975e09c8c3SJim Ingham 
1798cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
17995e09c8c3SJim Ingham 
18005e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1801b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18025e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18035e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18045e09c8c3SJim Ingham       return false;
18055e09c8c3SJim Ingham     }
18065e09c8c3SJim Ingham 
18075e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18085e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1809b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1810cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1811b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18125e09c8c3SJim Ingham 
1813b9c1b51eSKate Stone     if (result.Succeeded()) {
1814b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18155e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18165e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18175e09c8c3SJim Ingham         return false;
18185e09c8c3SJim Ingham       }
18195e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1820b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1821b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1822b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1823b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1824b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1825b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18265e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1827cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18285e09c8c3SJim Ingham       }
18295e09c8c3SJim Ingham     }
18305e09c8c3SJim Ingham 
18315e09c8c3SJim Ingham     return true;
18325e09c8c3SJim Ingham   }
18335e09c8c3SJim Ingham 
18345e09c8c3SJim Ingham private:
18355e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18365e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18375e09c8c3SJim Ingham };
18385e09c8c3SJim Ingham 
1839b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18405e09c8c3SJim Ingham public:
1841b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1842b9c1b51eSKate Stone       : CommandObjectParsed(
1843b9c1b51eSKate Stone             interpreter, "delete",
18445e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18455e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1846b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1847b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1848b9c1b51eSKate Stone     // command.
18495e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18505e09c8c3SJim Ingham     CommandArgumentData id_arg;
18515e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18525e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18535e09c8c3SJim Ingham     arg1.push_back(id_arg);
18545e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18555e09c8c3SJim Ingham 
18565e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18575e09c8c3SJim Ingham     m_option_group.Finalize();
18585e09c8c3SJim Ingham   }
18595e09c8c3SJim Ingham 
18609e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18615e09c8c3SJim Ingham 
1862b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18635e09c8c3SJim Ingham 
18645e09c8c3SJim Ingham protected:
1865b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1866b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18675e09c8c3SJim Ingham       result.SetError("No name option provided.");
18685e09c8c3SJim Ingham       return false;
18695e09c8c3SJim Ingham     }
18705e09c8c3SJim Ingham 
1871cb2380c9SRaphael Isemann     Target &target =
1872b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18735e09c8c3SJim Ingham 
1874bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1875cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18765e09c8c3SJim Ingham 
1877cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18785e09c8c3SJim Ingham 
18795e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1880b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18815e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
18825e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18835e09c8c3SJim Ingham       return false;
18845e09c8c3SJim Ingham     }
18855e09c8c3SJim Ingham 
18865e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18875e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1888b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1889cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1890b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
18915e09c8c3SJim Ingham 
1892b9c1b51eSKate Stone     if (result.Succeeded()) {
1893b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18945e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
18955e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18965e09c8c3SJim Ingham         return false;
18975e09c8c3SJim Ingham       }
1898b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
18995e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1900b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1901b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1902b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19035e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1904cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19055e09c8c3SJim Ingham       }
19065e09c8c3SJim Ingham     }
19075e09c8c3SJim Ingham 
19085e09c8c3SJim Ingham     return true;
19095e09c8c3SJim Ingham   }
19105e09c8c3SJim Ingham 
19115e09c8c3SJim Ingham private:
19125e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19135e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19145e09c8c3SJim Ingham };
19155e09c8c3SJim Ingham 
1916b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19175e09c8c3SJim Ingham public:
1918b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1919b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1920b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1921b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1922b842f2ecSJim Ingham                             "names",
19235e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1924b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1925b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19265e09c8c3SJim Ingham     m_option_group.Finalize();
19275e09c8c3SJim Ingham   }
19285e09c8c3SJim Ingham 
19299e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19305e09c8c3SJim Ingham 
1931b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19325e09c8c3SJim Ingham 
19335e09c8c3SJim Ingham protected:
1934b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1935cb2380c9SRaphael Isemann     Target &target =
1936b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19375e09c8c3SJim Ingham 
1938b842f2ecSJim Ingham     std::vector<std::string> name_list;
1939b842f2ecSJim Ingham     if (command.empty()) {
1940cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1941b842f2ecSJim Ingham     } else {
1942b842f2ecSJim Ingham       for (const Args::ArgEntry &arg : command)
1943b842f2ecSJim Ingham       {
1944b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1945b842f2ecSJim Ingham       }
1946b842f2ecSJim Ingham     }
1947b842f2ecSJim Ingham 
1948b842f2ecSJim Ingham     if (name_list.empty()) {
1949b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1950b842f2ecSJim Ingham     } else {
1951b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1952b842f2ecSJim Ingham         const char *name = name_str.c_str();
1953b842f2ecSJim Ingham         // First print out the options for the name:
1954b842f2ecSJim Ingham         Status error;
1955cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1956cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1957b842f2ecSJim Ingham         if (bp_name)
1958b842f2ecSJim Ingham         {
1959b842f2ecSJim Ingham           StreamString s;
1960b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1961b842f2ecSJim Ingham           if (bp_name->GetDescription(&s, eDescriptionLevelFull))
1962b842f2ecSJim Ingham           {
1963b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1964b842f2ecSJim Ingham           }
1965b842f2ecSJim Ingham 
1966bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1967cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19685e09c8c3SJim Ingham 
1969cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1970b842f2ecSJim Ingham           bool any_set = false;
1971b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1972b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19735e09c8c3SJim Ingham               StreamString s;
1974b842f2ecSJim Ingham               any_set = true;
19755e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19765e09c8c3SJim Ingham               s.EOL();
1977c156427dSZachary Turner               result.AppendMessage(s.GetString());
19785e09c8c3SJim Ingham             }
19795e09c8c3SJim Ingham           }
1980b842f2ecSJim Ingham           if (!any_set)
1981b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
1982b9c1b51eSKate Stone         } else {
1983b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
19845e09c8c3SJim Ingham         }
1985b842f2ecSJim Ingham       }
19865e09c8c3SJim Ingham     }
19875e09c8c3SJim Ingham     return true;
19885e09c8c3SJim Ingham   }
19895e09c8c3SJim Ingham 
19905e09c8c3SJim Ingham private:
19915e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19925e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19935e09c8c3SJim Ingham };
19945e09c8c3SJim Ingham 
1995e14dc268SJim Ingham // CommandObjectBreakpointName
1996b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
19975e09c8c3SJim Ingham public:
19987428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
1999b9c1b51eSKate Stone       : CommandObjectMultiword(
2000b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2001b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2002b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2003b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2004b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2005b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2006b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2007b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2008b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2009b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
20105e09c8c3SJim Ingham 
20115e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20125e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20135e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2014b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
20155e09c8c3SJim Ingham   }
20165e09c8c3SJim Ingham 
20179e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20185e09c8c3SJim Ingham };
20195e09c8c3SJim Ingham 
2020e14dc268SJim Ingham // CommandObjectBreakpointRead
20213acdf385SJim Ingham #pragma mark Read::CommandOptions
2022f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2023f94668e3SRaphael Isemann #include "CommandOptions.inc"
20241f0f5b5bSZachary Turner 
20251f0f5b5bSZachary Turner #pragma mark Read
2026e14dc268SJim Ingham 
2027e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2028e14dc268SJim Ingham public:
2029e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2030e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2031e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2032e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2033e14dc268SJim Ingham                             nullptr),
2034e14dc268SJim Ingham         m_options() {
2035e14dc268SJim Ingham     CommandArgumentEntry arg;
2036e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2037e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2038e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2039e14dc268SJim Ingham     // arguments vector.
2040e14dc268SJim Ingham     m_arguments.push_back(arg);
2041e14dc268SJim Ingham   }
2042e14dc268SJim Ingham 
2043e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2044e14dc268SJim Ingham 
2045e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2046e14dc268SJim Ingham 
2047e14dc268SJim Ingham   class CommandOptions : public Options {
2048e14dc268SJim Ingham   public:
2049e14dc268SJim Ingham     CommandOptions() : Options() {}
2050e14dc268SJim Ingham 
2051e14dc268SJim Ingham     ~CommandOptions() override = default;
2052e14dc268SJim Ingham 
205397206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2054e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
205597206d57SZachary Turner       Status error;
2056e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2057e14dc268SJim Ingham 
2058e14dc268SJim Ingham       switch (short_option) {
2059e14dc268SJim Ingham       case 'f':
2060e14dc268SJim Ingham         m_filename.assign(option_arg);
2061e14dc268SJim Ingham         break;
20623acdf385SJim Ingham       case 'N': {
206397206d57SZachary Turner         Status name_error;
20643acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20653acdf385SJim Ingham                                                   name_error)) {
20663acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20673acdf385SJim Ingham                                          name_error.AsCString());
20683acdf385SJim Ingham         }
20693acdf385SJim Ingham         m_names.push_back(option_arg);
20703acdf385SJim Ingham         break;
20713acdf385SJim Ingham       }
2072e14dc268SJim Ingham       default:
207336162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2074e14dc268SJim Ingham       }
2075e14dc268SJim Ingham 
2076e14dc268SJim Ingham       return error;
2077e14dc268SJim Ingham     }
2078e14dc268SJim Ingham 
2079e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2080e14dc268SJim Ingham       m_filename.clear();
20813acdf385SJim Ingham       m_names.clear();
2082e14dc268SJim Ingham     }
2083e14dc268SJim Ingham 
20841f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
208570602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
20861f0f5b5bSZachary Turner     }
2087e14dc268SJim Ingham 
2088e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2089e14dc268SJim Ingham 
2090e14dc268SJim Ingham     std::string m_filename;
20913acdf385SJim Ingham     std::vector<std::string> m_names;
2092e14dc268SJim Ingham   };
2093e14dc268SJim Ingham 
2094e14dc268SJim Ingham protected:
2095e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2096cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2097e14dc268SJim Ingham 
20983acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2099cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
21003acdf385SJim Ingham 
21018f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
21028f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
210301f16664SJim Ingham     BreakpointIDList new_bps;
2104cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2105cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2106e14dc268SJim Ingham 
2107e14dc268SJim Ingham     if (!error.Success()) {
210801f16664SJim Ingham       result.AppendError(error.AsCString());
2109e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
211001f16664SJim Ingham       return false;
2111e14dc268SJim Ingham     }
21123acdf385SJim Ingham 
21133acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
21143acdf385SJim Ingham 
21153acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
21163acdf385SJim Ingham     if (num_breakpoints == 0) {
21173acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
21183acdf385SJim Ingham     } else {
21193acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
21203acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
21213acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
21223acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2123cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
21243acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
21253acdf385SJim Ingham                              .get();
21263acdf385SJim Ingham         if (bp)
21273acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
21283acdf385SJim Ingham                              false);
21293acdf385SJim Ingham       }
21303acdf385SJim Ingham     }
2131e14dc268SJim Ingham     return result.Succeeded();
2132e14dc268SJim Ingham   }
2133e14dc268SJim Ingham 
2134e14dc268SJim Ingham private:
2135e14dc268SJim Ingham   CommandOptions m_options;
2136e14dc268SJim Ingham };
2137e14dc268SJim Ingham 
2138e14dc268SJim Ingham // CommandObjectBreakpointWrite
21391f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2140f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2141f94668e3SRaphael Isemann #include "CommandOptions.inc"
21421f0f5b5bSZachary Turner 
21431f0f5b5bSZachary Turner #pragma mark Write
2144e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2145e14dc268SJim Ingham public:
2146e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2147e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2148e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2149e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2150e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2151e14dc268SJim Ingham                             nullptr),
2152e14dc268SJim Ingham         m_options() {
2153e14dc268SJim Ingham     CommandArgumentEntry arg;
2154e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2155e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2156e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2157e14dc268SJim Ingham     // arguments vector.
2158e14dc268SJim Ingham     m_arguments.push_back(arg);
2159e14dc268SJim Ingham   }
2160e14dc268SJim Ingham 
2161e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2162e14dc268SJim Ingham 
2163e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2164e14dc268SJim Ingham 
2165e14dc268SJim Ingham   class CommandOptions : public Options {
2166e14dc268SJim Ingham   public:
2167e14dc268SJim Ingham     CommandOptions() : Options() {}
2168e14dc268SJim Ingham 
2169e14dc268SJim Ingham     ~CommandOptions() override = default;
2170e14dc268SJim Ingham 
217197206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2172e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
217397206d57SZachary Turner       Status error;
2174e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2175e14dc268SJim Ingham 
2176e14dc268SJim Ingham       switch (short_option) {
2177e14dc268SJim Ingham       case 'f':
2178e14dc268SJim Ingham         m_filename.assign(option_arg);
2179e14dc268SJim Ingham         break;
21802d3628e1SJim Ingham       case 'a':
21812d3628e1SJim Ingham         m_append = true;
21822d3628e1SJim Ingham         break;
2183e14dc268SJim Ingham       default:
218436162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2185e14dc268SJim Ingham       }
2186e14dc268SJim Ingham 
2187e14dc268SJim Ingham       return error;
2188e14dc268SJim Ingham     }
2189e14dc268SJim Ingham 
2190e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2191e14dc268SJim Ingham       m_filename.clear();
21922d3628e1SJim Ingham       m_append = false;
2193e14dc268SJim Ingham     }
2194e14dc268SJim Ingham 
21951f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
219670602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
21971f0f5b5bSZachary Turner     }
2198e14dc268SJim Ingham 
2199e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2200e14dc268SJim Ingham 
2201e14dc268SJim Ingham     std::string m_filename;
22022d3628e1SJim Ingham     bool m_append = false;
2203e14dc268SJim Ingham   };
2204e14dc268SJim Ingham 
2205e14dc268SJim Ingham protected:
2206e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2207cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2208e14dc268SJim Ingham 
2209e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2210cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2211e14dc268SJim Ingham 
2212e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
221311eb9c64SZachary Turner     if (!command.empty()) {
2214e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2215cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2216b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2217e14dc268SJim Ingham 
221801f16664SJim Ingham       if (!result.Succeeded()) {
2219e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2220e14dc268SJim Ingham         return false;
2221e14dc268SJim Ingham       }
2222e14dc268SJim Ingham     }
22238f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
22248f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2225cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
22268f3be7a3SJonas Devlieghere                                                      m_options.m_append);
222701f16664SJim Ingham     if (!error.Success()) {
222801f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
222901f16664SJim Ingham                                    error.AsCString());
223001f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2231e14dc268SJim Ingham     }
2232e14dc268SJim Ingham     return result.Succeeded();
2233e14dc268SJim Ingham   }
2234e14dc268SJim Ingham 
2235e14dc268SJim Ingham private:
2236e14dc268SJim Ingham   CommandOptions m_options;
2237e14dc268SJim Ingham };
2238e14dc268SJim Ingham 
223930fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2240ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
224130fdc8d8SChris Lattner 
2242b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2243b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2244b9c1b51eSKate Stone     : CommandObjectMultiword(
2245b9c1b51eSKate Stone           interpreter, "breakpoint",
22467428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2247b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2248b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2249b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2250b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2251b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2252b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2253b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2254b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2255b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2256b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2257b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2258b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2259b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2260b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2261b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2262b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2263b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2264b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2265b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2266e14dc268SJim Ingham   CommandObjectSP write_command_object(
2267e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2268e14dc268SJim Ingham   CommandObjectSP read_command_object(
2269e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
227030fdc8d8SChris Lattner 
2271b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
227230fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
227330fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2274b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2275b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2276ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2277b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2278b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
22795e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2280e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2281e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
228230fdc8d8SChris Lattner 
228323f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
228423f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
228523f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
228623f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
228723f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
228823f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
228923f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
229023f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
22915e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2292e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2293e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
229430fdc8d8SChris Lattner }
229530fdc8d8SChris Lattner 
22969e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
229730fdc8d8SChris Lattner 
2298b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
22995e09c8c3SJim Ingham                                                  bool allow_locations,
23005e09c8c3SJim Ingham                                                  CommandReturnObject &result,
2301b842f2ecSJim Ingham                                                  BreakpointIDList *valid_ids,
2302b842f2ecSJim Ingham                                                  BreakpointName::Permissions
2303b842f2ecSJim Ingham                                                      ::PermissionKinds
2304b842f2ecSJim Ingham                                                      purpose) {
230530fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2306b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2307b9c1b51eSKate Stone   //                                  canonical representation
2308b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2309b9c1b51eSKate Stone   //                                  representing a range (in which case there
2310b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2311b9c1b51eSKate Stone   //                                      after of one of the first two types.
23125e09c8c3SJim Ingham   //                                  4). A breakpoint name
2313b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2314b9c1b51eSKate Stone   // one.)
231530fdc8d8SChris Lattner 
231630fdc8d8SChris Lattner   Args temp_args;
231730fdc8d8SChris Lattner 
231811eb9c64SZachary Turner   if (args.empty()) {
2319b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2320b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2321b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
232236f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2323b9c1b51eSKate Stone     } else {
2324b9c1b51eSKate Stone       result.AppendError(
2325b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
232636f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
232736f3b369SJim Ingham     }
232836f3b369SJim Ingham     return;
232936f3b369SJim Ingham   }
233036f3b369SJim Ingham 
2331b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
233205097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
233305097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
233405097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
233505097246SAdrian Prantl   // into TEMP_ARGS.
233630fdc8d8SChris Lattner 
2337b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2338b842f2ecSJim Ingham                                            purpose, result, temp_args);
233930fdc8d8SChris Lattner 
2340b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2341b9c1b51eSKate Stone   // BreakpointIDList:
234230fdc8d8SChris Lattner 
234316662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
234430fdc8d8SChris Lattner 
234505097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
234605097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
234730fdc8d8SChris Lattner 
2348b9c1b51eSKate Stone   if (result.Succeeded()) {
2349b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
235005097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
235105097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
235230fdc8d8SChris Lattner 
2353c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2354b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
235530fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2356b9c1b51eSKate Stone       Breakpoint *breakpoint =
2357b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2358b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2359c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2360b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
236130fdc8d8SChris Lattner           StreamString id_str;
2362b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2363b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2364c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2365b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2366b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
236730fdc8d8SChris Lattner               id_str.GetData());
236830fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
236930fdc8d8SChris Lattner         }
2370b9c1b51eSKate Stone       } else {
2371c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2372b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2373b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
23747428a18cSKate Stone             cur_bp_id.GetBreakpointID());
237530fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
237630fdc8d8SChris Lattner       }
237730fdc8d8SChris Lattner     }
237830fdc8d8SChris Lattner   }
237930fdc8d8SChris Lattner }
2380