180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h"
109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
16*7ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
19943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
2032abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
21bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h"
225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
235e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
24b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
250e0984eeSJim Ingham #include "lldb/Target/Language.h"
26b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
27b9c1b51eSKate Stone #include "lldb/Target/Target.h"
281b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
29bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
30bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3130fdc8d8SChris Lattner 
32796ac80bSJonas Devlieghere #include <memory>
33796ac80bSJonas Devlieghere #include <vector>
34796ac80bSJonas Devlieghere 
3530fdc8d8SChris Lattner using namespace lldb;
3630fdc8d8SChris Lattner using namespace lldb_private;
3730fdc8d8SChris Lattner 
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)38b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
39b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
4030fdc8d8SChris Lattner   s->IndentMore();
4130fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4230fdc8d8SChris Lattner   s->IndentLess();
4330fdc8d8SChris Lattner   s->EOL();
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner 
46b842f2ecSJim Ingham // Modifiable Breakpoint Options
47b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
48f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
49f94668e3SRaphael Isemann #include "CommandOptions.inc"
50bd68a052SRaphael Isemann 
51a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup {
52b842f2ecSJim Ingham public:
BreakpointOptionGroup()53abb0ed44SKazu Hirata   BreakpointOptionGroup() : m_bp_opts(false) {}
54b842f2ecSJim Ingham 
55b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
56b842f2ecSJim Ingham 
GetDefinitions()57b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
58b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
59b842f2ecSJim Ingham   }
60b842f2ecSJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)61b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
62b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
63b842f2ecSJim Ingham     Status error;
64a925974bSAdrian Prantl     const int short_option =
65a925974bSAdrian Prantl         g_breakpoint_modify_options[option_idx].short_option;
66b842f2ecSJim Ingham 
67b842f2ecSJim Ingham     switch (short_option) {
68b842f2ecSJim Ingham     case 'c':
6905097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
7005097246SAdrian Prantl       // to say it was passed in.
71b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
72b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
73b842f2ecSJim Ingham       break;
74b842f2ecSJim Ingham     case 'C':
75adcd0268SBenjamin Kramer       m_commands.push_back(std::string(option_arg));
76b842f2ecSJim Ingham       break;
77b842f2ecSJim Ingham     case 'd':
78b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
79b842f2ecSJim Ingham       break;
80b842f2ecSJim Ingham     case 'e':
81b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
82b842f2ecSJim Ingham       break;
83b842f2ecSJim Ingham     case 'G': {
84b842f2ecSJim Ingham       bool value, success;
8547cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
86b842f2ecSJim Ingham       if (success) {
87b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
88b842f2ecSJim Ingham       } else
89b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
90b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
91b842f2ecSJim Ingham             option_arg.str().c_str());
92a925974bSAdrian Prantl     } break;
93a925974bSAdrian Prantl     case 'i': {
94b842f2ecSJim Ingham       uint32_t ignore_count;
95b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
96b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
97b842f2ecSJim Ingham                                        option_arg.str().c_str());
98b842f2ecSJim Ingham       else
99b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
100a925974bSAdrian Prantl     } break;
101b842f2ecSJim Ingham     case 'o': {
102b842f2ecSJim Ingham       bool value, success;
10347cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
104b842f2ecSJim Ingham       if (success) {
105b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
106b842f2ecSJim Ingham       } else
107b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
108b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
109b842f2ecSJim Ingham             option_arg.str().c_str());
110b842f2ecSJim Ingham     } break;
111a925974bSAdrian Prantl     case 't': {
112b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
113b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
114f362b05dSJim Ingham         if (option_arg == "current") {
115f362b05dSJim Ingham           if (!execution_context) {
116f362b05dSJim Ingham             error.SetErrorStringWithFormat("No context to determine current "
117f362b05dSJim Ingham                                            "thread");
118f362b05dSJim Ingham           } else {
119f362b05dSJim Ingham             ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
120f362b05dSJim Ingham             if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
121f362b05dSJim Ingham               error.SetErrorStringWithFormat("No currently selected thread");
122f362b05dSJim Ingham             } else {
123f362b05dSJim Ingham               thread_id = ctx_thread_sp->GetID();
124f362b05dSJim Ingham             }
125f362b05dSJim Ingham           }
126f362b05dSJim Ingham         } else if (option_arg.getAsInteger(0, thread_id))
127b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
128b842f2ecSJim Ingham                                          option_arg.str().c_str());
129b842f2ecSJim Ingham       }
130b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
131a925974bSAdrian Prantl     } break;
132b842f2ecSJim Ingham     case 'T':
133b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
134b842f2ecSJim Ingham       break;
135b842f2ecSJim Ingham     case 'q':
136b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
137b842f2ecSJim Ingham       break;
138a925974bSAdrian Prantl     case 'x': {
139b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
140b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
141b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
142b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
143b842f2ecSJim Ingham                                          option_arg.str().c_str());
144b842f2ecSJim Ingham       }
145b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
146a925974bSAdrian Prantl     } break;
147b842f2ecSJim Ingham     default:
14836162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
149b842f2ecSJim Ingham     }
150b842f2ecSJim Ingham 
151b842f2ecSJim Ingham     return error;
152b842f2ecSJim Ingham   }
153b842f2ecSJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)154b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
155b842f2ecSJim Ingham     m_bp_opts.Clear();
156b842f2ecSJim Ingham     m_commands.clear();
157b842f2ecSJim Ingham   }
158b842f2ecSJim Ingham 
OptionParsingFinished(ExecutionContext * execution_context)159b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
160a925974bSAdrian Prantl     if (!m_commands.empty()) {
161a8f3ae7cSJonas Devlieghere       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
162b842f2ecSJim Ingham 
163b842f2ecSJim Ingham       for (std::string &str : m_commands)
164b842f2ecSJim Ingham         cmd_data->user_source.AppendString(str);
165b842f2ecSJim Ingham 
166b842f2ecSJim Ingham       cmd_data->stop_on_error = true;
167b842f2ecSJim Ingham       m_bp_opts.SetCommandDataCallback(cmd_data);
168b842f2ecSJim Ingham     }
169b842f2ecSJim Ingham     return Status();
170b842f2ecSJim Ingham   }
171b842f2ecSJim Ingham 
GetBreakpointOptions()172a925974bSAdrian Prantl   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
173b842f2ecSJim Ingham 
174b842f2ecSJim Ingham   std::vector<std::string> m_commands;
175b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
176b842f2ecSJim Ingham };
177bd68a052SRaphael Isemann 
178f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
179f94668e3SRaphael Isemann #include "CommandOptions.inc"
180b842f2ecSJim Ingham 
181a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
182b842f2ecSJim Ingham public:
18324f9a2f5SShafik Yaghmour   BreakpointDummyOptionGroup() = default;
184b842f2ecSJim Ingham 
185b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
186b842f2ecSJim Ingham 
GetDefinitions()187b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
188b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
189b842f2ecSJim Ingham   }
190b842f2ecSJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)191b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
192b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
193b842f2ecSJim Ingham     Status error;
194a925974bSAdrian Prantl     const int short_option =
195f1539b9dSJim Ingham         g_breakpoint_dummy_options[option_idx].short_option;
196b842f2ecSJim Ingham 
197b842f2ecSJim Ingham     switch (short_option) {
198b842f2ecSJim Ingham     case 'D':
199b842f2ecSJim Ingham       m_use_dummy = true;
200b842f2ecSJim Ingham       break;
201b842f2ecSJim Ingham     default:
20236162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
203b842f2ecSJim Ingham     }
204b842f2ecSJim Ingham 
205b842f2ecSJim Ingham     return error;
206b842f2ecSJim Ingham   }
207b842f2ecSJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)208b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
209b842f2ecSJim Ingham     m_use_dummy = false;
210b842f2ecSJim Ingham   }
211b842f2ecSJim Ingham 
212b842f2ecSJim Ingham   bool m_use_dummy;
213b842f2ecSJim Ingham };
214b842f2ecSJim Ingham 
215f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
216f94668e3SRaphael Isemann #include "CommandOptions.inc"
2171f0f5b5bSZachary Turner 
2185a988416SJim Ingham // CommandObjectBreakpointSet
21930fdc8d8SChris Lattner 
220b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2215a988416SJim Ingham public:
222efe8e7e3SFangrui Song   enum BreakpointSetType {
2235a988416SJim Ingham     eSetTypeInvalid,
2245a988416SJim Ingham     eSetTypeFileAndLine,
2255a988416SJim Ingham     eSetTypeAddress,
2265a988416SJim Ingham     eSetTypeFunctionName,
2275a988416SJim Ingham     eSetTypeFunctionRegexp,
2285a988416SJim Ingham     eSetTypeSourceRegexp,
2293815e702SJim Ingham     eSetTypeException,
2303815e702SJim Ingham     eSetTypeScripted,
231efe8e7e3SFangrui Song   };
2325a988416SJim Ingham 
CommandObjectBreakpointSet(CommandInterpreter & interpreter)233b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
234b9c1b51eSKate Stone       : CommandObjectParsed(
235b9c1b51eSKate Stone             interpreter, "breakpoint set",
2365a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2375a988416SJim Ingham             "breakpoint set <cmd-options>"),
238abb0ed44SKazu Hirata         m_python_class_options("scripted breakpoint", true, 'P') {
239b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
240a925974bSAdrian Prantl     m_all_options.Append(&m_python_class_options,
241a925974bSAdrian Prantl                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
242b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
243b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
244b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
245f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
246b842f2ecSJim Ingham     m_all_options.Append(&m_options);
247b842f2ecSJim Ingham     m_all_options.Finalize();
248b842f2ecSJim Ingham   }
2495a988416SJim Ingham 
2509e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2515a988416SJim Ingham 
GetOptions()252b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2535a988416SJim Ingham 
254b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2555a988416SJim Ingham   public:
25624f9a2f5SShafik Yaghmour     CommandOptions() = default;
25730fdc8d8SChris Lattner 
2589e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
25987df91b8SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)26097206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
261b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
26297206d57SZachary Turner       Status error;
263a925974bSAdrian Prantl       const int short_option =
264a925974bSAdrian Prantl           g_breakpoint_set_options[option_idx].short_option;
26530fdc8d8SChris Lattner 
266b9c1b51eSKate Stone       switch (short_option) {
267b9c1b51eSKate Stone       case 'a': {
26847cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
269e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
270b9c1b51eSKate Stone       } break;
27130fdc8d8SChris Lattner 
272e732052fSJim Ingham       case 'A':
273e732052fSJim Ingham         m_all_files = true;
274e732052fSJim Ingham         break;
275e732052fSJim Ingham 
276ca36cd16SJim Ingham       case 'b':
277adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
278ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
279ca36cd16SJim Ingham         break;
280ca36cd16SJim Ingham 
2816672a4f5SJonas Devlieghere       case 'u':
282fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
283b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
284fe11483bSZachary Turner                                          option_arg.str().c_str());
28530fdc8d8SChris Lattner         break;
2869e85e5a8SEugene Zelenko 
287b9c1b51eSKate Stone       case 'E': {
288fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
289fab10e89SJim Ingham 
290b9c1b51eSKate Stone         switch (language) {
291fab10e89SJim Ingham         case eLanguageTypeC89:
292fab10e89SJim Ingham         case eLanguageTypeC:
293fab10e89SJim Ingham         case eLanguageTypeC99:
2941d0089faSBruce Mitchener         case eLanguageTypeC11:
295a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
296fab10e89SJim Ingham           break;
297fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2981d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2991d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
3002ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
301a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
302fab10e89SJim Ingham           break;
303fab10e89SJim Ingham         case eLanguageTypeObjC:
304a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
305fab10e89SJim Ingham           break;
306fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
307b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
308b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
309fab10e89SJim Ingham           break;
310fab10e89SJim Ingham         case eLanguageTypeUnknown:
311b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
312b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
313fe11483bSZachary Turner               option_arg.str().c_str());
314fab10e89SJim Ingham           break;
315fab10e89SJim Ingham         default:
316b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
317b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
318fe11483bSZachary Turner               option_arg.str().c_str());
319fab10e89SJim Ingham         }
320b9c1b51eSKate Stone       } break;
321ca36cd16SJim Ingham 
322ca36cd16SJim Ingham       case 'f':
3238f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
324fab10e89SJim Ingham         break;
325ca36cd16SJim Ingham 
326ca36cd16SJim Ingham       case 'F':
327adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
328ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
329ca36cd16SJim Ingham         break;
330ca36cd16SJim Ingham 
331b9c1b51eSKate Stone       case 'h': {
332fab10e89SJim Ingham         bool success;
33347cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
334fab10e89SJim Ingham         if (!success)
335b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
336fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
337fe11483bSZachary Turner               option_arg.str().c_str());
338b9c1b51eSKate Stone       } break;
339eb023e75SGreg Clayton 
340eb023e75SGreg Clayton       case 'H':
341eb023e75SGreg Clayton         m_hardware = true;
342eb023e75SGreg Clayton         break;
343eb023e75SGreg Clayton 
344b9c1b51eSKate Stone       case 'K': {
345a8558b62SJim Ingham         bool success;
346a8558b62SJim Ingham         bool value;
34747cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
348a8558b62SJim Ingham         if (value)
349a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
350a8558b62SJim Ingham         else
351a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
352a8558b62SJim Ingham 
353a8558b62SJim Ingham         if (!success)
354b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
355b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
356fe11483bSZachary Turner               option_arg.str().c_str());
357b9c1b51eSKate Stone       } break;
358ca36cd16SJim Ingham 
359fe11483bSZachary Turner       case 'l':
360fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
361b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
362fe11483bSZachary Turner                                          option_arg.str().c_str());
363ca36cd16SJim Ingham         break;
364055ad9beSIlia K 
36523b1decbSDawn Perchik       case 'L':
366fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
36723b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
368b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
369fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
370fe11483bSZachary Turner               option_arg.str().c_str());
37123b1decbSDawn Perchik         break;
37223b1decbSDawn Perchik 
373b9c1b51eSKate Stone       case 'm': {
374055ad9beSIlia K         bool success;
375055ad9beSIlia K         bool value;
37647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
377055ad9beSIlia K         if (value)
378055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
379055ad9beSIlia K         else
380055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
381055ad9beSIlia K 
382055ad9beSIlia K         if (!success)
383b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
384b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
385fe11483bSZachary Turner               option_arg.str().c_str());
386055ad9beSIlia K         break;
387055ad9beSIlia K       }
388055ad9beSIlia K 
389ca36cd16SJim Ingham       case 'M':
390adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
391ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
392ca36cd16SJim Ingham         break;
393ca36cd16SJim Ingham 
394ca36cd16SJim Ingham       case 'n':
395adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
396ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
397ca36cd16SJim Ingham         break;
398ca36cd16SJim Ingham 
3996fa7681bSZachary Turner       case 'N': {
400fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
401adcd0268SBenjamin Kramer           m_breakpoint_names.push_back(std::string(option_arg));
402ff9a91eaSJim Ingham         else
403ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
404fe11483bSZachary Turner                                          option_arg.str().c_str());
4055e09c8c3SJim Ingham         break;
4066fa7681bSZachary Turner       }
4075e09c8c3SJim Ingham 
408b9c1b51eSKate Stone       case 'R': {
4092411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
41047cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
41147cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4122411167fSJim Ingham         if (error.Success())
4132411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
414b9c1b51eSKate Stone       } break;
4152411167fSJim Ingham 
416a72b31c7SJim Ingham       case 'O':
417fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
418fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
419a72b31c7SJim Ingham         break;
420a72b31c7SJim Ingham 
421ca36cd16SJim Ingham       case 'p':
422adcd0268SBenjamin Kramer         m_source_text_regexp.assign(std::string(option_arg));
423ca36cd16SJim Ingham         break;
424ca36cd16SJim Ingham 
425ca36cd16SJim Ingham       case 'r':
426adcd0268SBenjamin Kramer         m_func_regexp.assign(std::string(option_arg));
427ca36cd16SJim Ingham         break;
428ca36cd16SJim Ingham 
429ca36cd16SJim Ingham       case 's':
4308f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
431ca36cd16SJim Ingham         break;
432ca36cd16SJim Ingham 
433ca36cd16SJim Ingham       case 'S':
434adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
435ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
436ca36cd16SJim Ingham         break;
437ca36cd16SJim Ingham 
438b9c1b51eSKate Stone       case 'w': {
439ca36cd16SJim Ingham         bool success;
44047cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
441ca36cd16SJim Ingham         if (!success)
442b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
443fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
444fe11483bSZachary Turner               option_arg.str().c_str());
445b9c1b51eSKate Stone       } break;
446ca36cd16SJim Ingham 
44776bb8d67SJim Ingham       case 'X':
448adcd0268SBenjamin Kramer         m_source_regex_func_names.insert(std::string(option_arg));
44976bb8d67SJim Ingham         break;
45076bb8d67SJim Ingham 
451bc0a9a17SJim Ingham       case 'y':
452bc0a9a17SJim Ingham       {
453bc0a9a17SJim Ingham         OptionValueFileColonLine value;
454bc0a9a17SJim Ingham         Status fcl_err = value.SetValueFromString(option_arg);
455bc0a9a17SJim Ingham         if (!fcl_err.Success()) {
456bc0a9a17SJim Ingham           error.SetErrorStringWithFormat(
457bc0a9a17SJim Ingham               "Invalid value for file:line specifier: %s",
458bc0a9a17SJim Ingham               fcl_err.AsCString());
459bc0a9a17SJim Ingham         } else {
460bc0a9a17SJim Ingham           m_filenames.AppendIfUnique(value.GetFileSpec());
461bc0a9a17SJim Ingham           m_line_num = value.GetLineNumber();
462bc0a9a17SJim Ingham           m_column = value.GetColumnNumber();
463bc0a9a17SJim Ingham         }
464bc0a9a17SJim Ingham       } break;
465bc0a9a17SJim Ingham 
46630fdc8d8SChris Lattner       default:
46736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
46830fdc8d8SChris Lattner       }
46930fdc8d8SChris Lattner 
47030fdc8d8SChris Lattner       return error;
47130fdc8d8SChris Lattner     }
4729e85e5a8SEugene Zelenko 
OptionParsingStarting(ExecutionContext * execution_context)473b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
47487df91b8SJim Ingham       m_filenames.Clear();
47530fdc8d8SChris Lattner       m_line_num = 0;
47630fdc8d8SChris Lattner       m_column = 0;
477fab10e89SJim Ingham       m_func_names.clear();
4781f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
47930fdc8d8SChris Lattner       m_func_regexp.clear();
4801f746071SGreg Clayton       m_source_text_regexp.clear();
48187df91b8SJim Ingham       m_modules.Clear();
4821f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4832411167fSJim Ingham       m_offset_addr = 0;
484fab10e89SJim Ingham       m_catch_bp = false;
485fab10e89SJim Ingham       m_throw_bp = true;
486eb023e75SGreg Clayton       m_hardware = false;
487a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
48823b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
489a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4905e09c8c3SJim Ingham       m_breakpoint_names.clear();
491e732052fSJim Ingham       m_all_files = false;
492a72b31c7SJim Ingham       m_exception_extra_args.Clear();
493055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
49476bb8d67SJim Ingham       m_source_regex_func_names.clear();
4953815e702SJim Ingham       m_current_key.clear();
49630fdc8d8SChris Lattner     }
49730fdc8d8SChris Lattner 
GetDefinitions()4981f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
49970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
5001f0f5b5bSZachary Turner     }
50130fdc8d8SChris Lattner 
5025a988416SJim Ingham     // Instance variables to hold the values for command options.
503969795f1SJim Ingham 
5045a988416SJim Ingham     std::string m_condition;
5055a988416SJim Ingham     FileSpecList m_filenames;
5069494c510SJonas Devlieghere     uint32_t m_line_num = 0;
5079494c510SJonas Devlieghere     uint32_t m_column = 0;
5085a988416SJim Ingham     std::vector<std::string> m_func_names;
5095e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
5109494c510SJonas Devlieghere     lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5115a988416SJim Ingham     std::string m_func_regexp;
5125a988416SJim Ingham     std::string m_source_text_regexp;
5135a988416SJim Ingham     FileSpecList m_modules;
5149494c510SJonas Devlieghere     lldb::addr_t m_load_addr = 0;
5152411167fSJim Ingham     lldb::addr_t m_offset_addr;
5169494c510SJonas Devlieghere     bool m_catch_bp = false;
5179494c510SJonas Devlieghere     bool m_throw_bp = true;
5189494c510SJonas Devlieghere     bool m_hardware = false; // Request to use hardware breakpoints
5199494c510SJonas Devlieghere     lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
5209494c510SJonas Devlieghere     lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
5219494c510SJonas Devlieghere     LazyBool m_skip_prologue = eLazyBoolCalculate;
5229494c510SJonas Devlieghere     bool m_all_files = false;
523a72b31c7SJim Ingham     Args m_exception_extra_args;
5249494c510SJonas Devlieghere     LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
52576bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5263815e702SJim Ingham     std::string m_current_key;
5275a988416SJim Ingham   };
5285a988416SJim Ingham 
5295a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)530b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
531cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
53230fdc8d8SChris Lattner 
53330fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
53430fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
53530fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
53630fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
537b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
538b9c1b51eSKate Stone     //   expression)
539b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
540b9c1b51eSKate Stone     //   to source text)
541b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
542b9c1b51eSKate Stone     //   given language.)
54330fdc8d8SChris Lattner 
54430fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
54530fdc8d8SChris Lattner 
546738af7a6SJim Ingham     if (!m_python_class_options.GetName().empty())
5473815e702SJim Ingham       break_type = eSetTypeScripted;
5483815e702SJim Ingham     else if (m_options.m_line_num != 0)
54930fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
55030fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
55130fdc8d8SChris Lattner       break_type = eSetTypeAddress;
552fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
55330fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
55430fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
55530fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
556969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
557969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
558a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
559fab10e89SJim Ingham       break_type = eSetTypeException;
56030fdc8d8SChris Lattner 
561b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
562274060b6SGreg Clayton     FileSpec module_spec;
563a8558b62SJim Ingham     const bool internal = false;
564a8558b62SJim Ingham 
565b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
566b9c1b51eSKate Stone     // that off.
567b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
568b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5692411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5702411167fSJim Ingham 
571b9c1b51eSKate Stone     switch (break_type) {
57230fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
57330fdc8d8SChris Lattner     {
57430fdc8d8SChris Lattner       FileSpec file;
575c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
576b9c1b51eSKate Stone       if (num_files == 0) {
577b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
57887df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
57987df91b8SJim Ingham           return false;
58087df91b8SJim Ingham         }
581b9c1b51eSKate Stone       } else if (num_files > 1) {
582b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
583b9c1b51eSKate Stone                            "line breakpoints.");
58487df91b8SJim Ingham         return false;
585b9c1b51eSKate Stone       } else
58687df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
58730fdc8d8SChris Lattner 
5881f746071SGreg Clayton       // Only check for inline functions if
5891f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5901f746071SGreg Clayton 
591cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
592cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
593cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
594cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
595b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
596b9c1b51eSKate Stone     } break;
5976eee5aa0SGreg Clayton 
59830fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
599055a08a4SJim Ingham     {
600b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
601b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
602b842f2ecSJim Ingham       //  will track the load location of the library.
603055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
604b9c1b51eSKate Stone       if (num_modules_specified == 1) {
605b9c1b51eSKate Stone         const FileSpec *file_spec =
606b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
607cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
608cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
609b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
610cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
611b842f2ecSJim Ingham                                         m_options.m_hardware);
612b9c1b51eSKate Stone       } else {
613b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
614b9c1b51eSKate Stone                            "address breakpoints.");
615055a08a4SJim Ingham         return false;
616055a08a4SJim Ingham       }
61730fdc8d8SChris Lattner       break;
618055a08a4SJim Ingham     }
61930fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6200c5cd90dSGreg Clayton     {
621117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6220c5cd90dSGreg Clayton 
6230c5cd90dSGreg Clayton       if (name_type_mask == 0)
624e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6250c5cd90dSGreg Clayton 
626cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
627cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
628cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
629cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
630b842f2ecSJim Ingham           m_options.m_hardware);
631b9c1b51eSKate Stone     } break;
6320c5cd90dSGreg Clayton 
633b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
634b9c1b51eSKate Stone                                  // name
63530fdc8d8SChris Lattner     {
63695eae423SZachary Turner       RegularExpression regexp(m_options.m_func_regexp);
6373af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
638b9c1b51eSKate Stone         result.AppendErrorWithFormat(
639b58af8d2SRaphael Isemann             "Function name regular expression could not be compiled: %s",
6403af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
641aaf68cd9SRaphael Isemann         // Check if the incorrect regex looks like a globbing expression and
642aaf68cd9SRaphael Isemann         // warn the user about it.
643aaf68cd9SRaphael Isemann         if (!m_options.m_func_regexp.empty()) {
644aaf68cd9SRaphael Isemann           if (m_options.m_func_regexp[0] == '*' ||
645aaf68cd9SRaphael Isemann               m_options.m_func_regexp[0] == '?')
646aaf68cd9SRaphael Isemann             result.AppendWarning(
647aaf68cd9SRaphael Isemann                 "Function name regex does not accept glob patterns.");
648aaf68cd9SRaphael Isemann         }
649969795f1SJim Ingham         return false;
65030fdc8d8SChris Lattner       }
65187df91b8SJim Ingham 
652cb2380c9SRaphael Isemann       bp_sp = target.CreateFuncRegexBreakpoint(
6535aa1d819SJan Kratochvil           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
654cb2380c9SRaphael Isemann           m_options.m_language, m_options.m_skip_prologue, internal,
655b842f2ecSJim Ingham           m_options.m_hardware);
656a925974bSAdrian Prantl     } break;
657969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
658969795f1SJim Ingham     {
659c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
66087df91b8SJim Ingham 
661b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
662969795f1SJim Ingham         FileSpec file;
663b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
664b9c1b51eSKate Stone           result.AppendError(
665b9c1b51eSKate Stone               "No files provided and could not find default file.");
66687df91b8SJim Ingham           return false;
667b9c1b51eSKate Stone         } else {
66887df91b8SJim Ingham           m_options.m_filenames.Append(file);
66987df91b8SJim Ingham         }
67087df91b8SJim Ingham       }
6710c5cd90dSGreg Clayton 
67295eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6733af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
674b9c1b51eSKate Stone         result.AppendErrorWithFormat(
675b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6763af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
677969795f1SJim Ingham         return false;
678969795f1SJim Ingham       }
679cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
680cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6815aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
682cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
683b9c1b51eSKate Stone     } break;
684b9c1b51eSKate Stone     case eSetTypeException: {
68597206d57SZachary Turner       Status precond_error;
686cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
687cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
688cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
689b842f2ecSJim Ingham           &precond_error);
690b9c1b51eSKate Stone       if (precond_error.Fail()) {
691b9c1b51eSKate Stone         result.AppendErrorWithFormat(
692b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
693a72b31c7SJim Ingham             precond_error.AsCString());
694cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
695a72b31c7SJim Ingham         return false;
696a72b31c7SJim Ingham       }
697b9c1b51eSKate Stone     } break;
6983815e702SJim Ingham     case eSetTypeScripted: {
6993815e702SJim Ingham 
7003815e702SJim Ingham       Status error;
701cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
702738af7a6SJim Ingham           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
703cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
704943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
7053815e702SJim Ingham       if (error.Fail()) {
7063815e702SJim Ingham         result.AppendErrorWithFormat(
707a925974bSAdrian Prantl             "Error setting extra exception arguments: %s", error.AsCString());
708cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7093815e702SJim Ingham         return false;
7103815e702SJim Ingham       }
7113815e702SJim Ingham     } break;
71230fdc8d8SChris Lattner     default:
71330fdc8d8SChris Lattner       break;
71430fdc8d8SChris Lattner     }
71530fdc8d8SChris Lattner 
7161b54c88cSJim Ingham     // Now set the various options that were passed in:
717b842f2ecSJim Ingham     if (bp_sp) {
718cfb96d84SJim Ingham       bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
719ca36cd16SJim Ingham 
720b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
72197206d57SZachary Turner         Status name_error;
722ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
723cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
724ff9a91eaSJim Ingham           if (name_error.Fail()) {
725ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
726ff9a91eaSJim Ingham                                          name.c_str());
727cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
728ff9a91eaSJim Ingham             return false;
729ff9a91eaSJim Ingham           }
730ff9a91eaSJim Ingham         }
7315e09c8c3SJim Ingham       }
7321b54c88cSJim Ingham     }
7331b54c88cSJim Ingham 
734b842f2ecSJim Ingham     if (bp_sp) {
73585e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7361391cc7dSJim Ingham       const bool show_locations = false;
737b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
738b9c1b51eSKate Stone                             show_locations);
739cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
740b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
741b9c1b51eSKate Stone                              "into future targets.\n");
742b9c1b51eSKate Stone       else {
74305097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
74405097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
74505097246SAdrian Prantl         // set the breakpoint till we run.
746b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
747b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
748b9c1b51eSKate Stone                                "actual locations.\n");
7494aeb1989SJim Ingham         }
7504aeb1989SJim Ingham       }
75130fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
752b842f2ecSJim Ingham     } else if (!bp_sp) {
75330fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
75430fdc8d8SChris Lattner     }
75530fdc8d8SChris Lattner 
75630fdc8d8SChris Lattner     return result.Succeeded();
75730fdc8d8SChris Lattner   }
75830fdc8d8SChris Lattner 
7595a988416SJim Ingham private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)760cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
761b9c1b51eSKate Stone                       CommandReturnObject &result) {
7625a988416SJim Ingham     uint32_t default_line;
76305097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
76405097246SAdrian Prantl     // frame's file.
765cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
766b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
767b9c1b51eSKate Stone       if (cur_frame == nullptr) {
768b9c1b51eSKate Stone         result.AppendError(
769b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7705a988416SJim Ingham         return false;
771b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
772b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
773b9c1b51eSKate Stone                            "file, it has no debug info.");
7745a988416SJim Ingham         return false;
775b9c1b51eSKate Stone       } else {
776b9c1b51eSKate Stone         const SymbolContext &sc =
777b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
778b9c1b51eSKate Stone         if (sc.line_entry.file) {
7795a988416SJim Ingham           file = sc.line_entry.file;
780b9c1b51eSKate Stone         } else {
781b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
782b9c1b51eSKate Stone                              "use as the default file.");
7835a988416SJim Ingham           return false;
7845a988416SJim Ingham         }
7855a988416SJim Ingham       }
7865a988416SJim Ingham     }
7875a988416SJim Ingham     return true;
7885a988416SJim Ingham   }
7895a988416SJim Ingham 
790b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
791b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
792943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
7935a988416SJim Ingham   CommandOptions m_options;
794b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
7955a988416SJim Ingham };
7969e85e5a8SEugene Zelenko 
7975a988416SJim Ingham // CommandObjectBreakpointModify
7985a988416SJim Ingham #pragma mark Modify
7995a988416SJim Ingham 
800b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8015a988416SJim Ingham public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)802b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
803b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
804b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
805b9c1b51eSKate Stone                             "breakpoints in the executable.  "
806b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
807b9c1b51eSKate Stone                             "created breakpoint.  "
808b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
809b9c1b51eSKate Stone                             "empty argument clears the modification.",
810abb0ed44SKazu Hirata                             nullptr) {
8115a988416SJim Ingham     CommandArgumentEntry arg;
812b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
813b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
814b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
815b9c1b51eSKate Stone     // arguments vector.
8165a988416SJim Ingham     m_arguments.push_back(arg);
817b842f2ecSJim Ingham 
818b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
819b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
820b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
821b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
822b842f2ecSJim Ingham     m_options.Finalize();
8235a988416SJim Ingham   }
8245a988416SJim Ingham 
8259e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8265a988416SJim Ingham 
8270e50b9a4SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)8280e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8290e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8300e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
8310e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8320e50b9a4SGongyu Deng         request, nullptr);
8330e50b9a4SGongyu Deng   }
8340e50b9a4SGongyu Deng 
GetOptions()835b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8365a988416SJim Ingham 
8375a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)838b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
839cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8405a988416SJim Ingham 
841bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
842cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8435a988416SJim Ingham 
8445a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8455a988416SJim Ingham 
846b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
847cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
848b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8495a988416SJim Ingham 
850b9c1b51eSKate Stone     if (result.Succeeded()) {
8515a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
852b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8535a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8545a988416SJim Ingham 
855b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
856b9c1b51eSKate Stone           Breakpoint *bp =
857cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
858b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
859b9c1b51eSKate Stone             BreakpointLocation *location =
860b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
861b842f2ecSJim Ingham             if (location)
862cfb96d84SJim Ingham               location->GetLocationOptions().CopyOverSetOptions(
863a925974bSAdrian Prantl                   m_bp_opts.GetBreakpointOptions());
864b9c1b51eSKate Stone           } else {
865cfb96d84SJim Ingham             bp->GetOptions().CopyOverSetOptions(
866a925974bSAdrian Prantl                 m_bp_opts.GetBreakpointOptions());
8675a988416SJim Ingham           }
8685a988416SJim Ingham         }
8695a988416SJim Ingham       }
8705a988416SJim Ingham     }
8715a988416SJim Ingham 
8725a988416SJim Ingham     return result.Succeeded();
8735a988416SJim Ingham   }
8745a988416SJim Ingham 
8755a988416SJim Ingham private:
876b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
877b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
878b842f2ecSJim Ingham   OptionGroupOptions m_options;
8795a988416SJim Ingham };
8805a988416SJim Ingham 
8815a988416SJim Ingham // CommandObjectBreakpointEnable
8825a988416SJim Ingham #pragma mark Enable
8835a988416SJim Ingham 
884b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8855a988416SJim Ingham public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)886b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
887b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
888b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
889b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
890b9c1b51eSKate Stone                             nullptr) {
8915a988416SJim Ingham     CommandArgumentEntry arg;
892b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
893b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
894b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
895b9c1b51eSKate Stone     // arguments vector.
8965a988416SJim Ingham     m_arguments.push_back(arg);
8975a988416SJim Ingham   }
8985a988416SJim Ingham 
8999e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9005a988416SJim Ingham 
9010e50b9a4SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)9020e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
9030e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
9040e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
9050e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9060e50b9a4SGongyu Deng         request, nullptr);
9070e50b9a4SGongyu Deng   }
9080e50b9a4SGongyu Deng 
9095a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)910b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
911cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9125a988416SJim Ingham 
913bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
914cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9155a988416SJim Ingham 
916cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9175a988416SJim Ingham 
9185a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9195a988416SJim Ingham 
920b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9215a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9225a988416SJim Ingham       return false;
9235a988416SJim Ingham     }
9245a988416SJim Ingham 
92511eb9c64SZachary Turner     if (command.empty()) {
9265a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
927cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
928b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
929b9c1b51eSKate Stone                                      " breakpoints)\n",
930b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9315a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
932b9c1b51eSKate Stone     } else {
9335a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9345a988416SJim Ingham       BreakpointIDList valid_bp_ids;
935b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
936cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
937b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9385a988416SJim Ingham 
939b9c1b51eSKate Stone       if (result.Succeeded()) {
9405a988416SJim Ingham         int enable_count = 0;
9415a988416SJim Ingham         int loc_count = 0;
9425a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
943b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9445a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9455a988416SJim Ingham 
946b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
947b9c1b51eSKate Stone             Breakpoint *breakpoint =
948cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
949b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
950b9c1b51eSKate Stone               BreakpointLocation *location =
951b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
952b9c1b51eSKate Stone               if (location) {
9535a988416SJim Ingham                 location->SetEnabled(true);
9545a988416SJim Ingham                 ++loc_count;
9555a988416SJim Ingham               }
956b9c1b51eSKate Stone             } else {
9575a988416SJim Ingham               breakpoint->SetEnabled(true);
9585a988416SJim Ingham               ++enable_count;
9595a988416SJim Ingham             }
9605a988416SJim Ingham           }
9615a988416SJim Ingham         }
962b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
963b9c1b51eSKate Stone                                        enable_count + loc_count);
9645a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9655a988416SJim Ingham       }
9665a988416SJim Ingham     }
9675a988416SJim Ingham 
9685a988416SJim Ingham     return result.Succeeded();
9695a988416SJim Ingham   }
9705a988416SJim Ingham };
9715a988416SJim Ingham 
9725a988416SJim Ingham // CommandObjectBreakpointDisable
9735a988416SJim Ingham #pragma mark Disable
9745a988416SJim Ingham 
975b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9765a988416SJim Ingham public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)9777428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
978b9c1b51eSKate Stone       : CommandObjectParsed(
979b9c1b51eSKate Stone             interpreter, "breakpoint disable",
980b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9817428a18cSKate Stone             "them.  If none are specified, disable all "
9827428a18cSKate Stone             "breakpoints.",
983b9c1b51eSKate Stone             nullptr) {
984b9c1b51eSKate Stone     SetHelpLong(
985b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9867428a18cSKate Stone If none are specified, disable all breakpoints."
9877428a18cSKate Stone         R"(
988ea671fbdSKate Stone 
9897428a18cSKate Stone )"
9907428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
9917428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
9927428a18cSKate Stone         R"(
993ea671fbdSKate Stone 
994ea671fbdSKate Stone     (lldb) break disable 1
995ea671fbdSKate Stone     (lldb) break enable 1.1
996ea671fbdSKate Stone 
997ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
998ea671fbdSKate Stone 
999ea671fbdSKate Stone     (lldb) break disable 1.*
1000ea671fbdSKate Stone     (lldb) break enable 1.1
1001ea671fbdSKate Stone 
10027428a18cSKate Stone )"
10037428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10047428a18cSKate Stone the second re-enables the first location.");
1005b0fac509SJim Ingham 
10065a988416SJim Ingham     CommandArgumentEntry arg;
1007b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1008b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1009b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1010b9c1b51eSKate Stone     // arguments vector.
10115a988416SJim Ingham     m_arguments.push_back(arg);
10125a988416SJim Ingham   }
10135a988416SJim Ingham 
10149e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10155a988416SJim Ingham 
10160e50b9a4SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)10170e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
10180e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
10190e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
10200e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10210e50b9a4SGongyu Deng         request, nullptr);
10220e50b9a4SGongyu Deng   }
10230e50b9a4SGongyu Deng 
10245a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1025b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1026cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1027bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1028cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10295a988416SJim Ingham 
1030cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10315a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10325a988416SJim Ingham 
1033b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10345a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10355a988416SJim Ingham       return false;
10365a988416SJim Ingham     }
10375a988416SJim Ingham 
103811eb9c64SZachary Turner     if (command.empty()) {
10395a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1040cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1041b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1042b9c1b51eSKate Stone                                      " breakpoints)\n",
1043b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10445a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1045b9c1b51eSKate Stone     } else {
10465a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10475a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10485a988416SJim Ingham 
1049b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1050cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1051b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10525a988416SJim Ingham 
1053b9c1b51eSKate Stone       if (result.Succeeded()) {
10545a988416SJim Ingham         int disable_count = 0;
10555a988416SJim Ingham         int loc_count = 0;
10565a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1057b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10585a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10595a988416SJim Ingham 
1060b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1061b9c1b51eSKate Stone             Breakpoint *breakpoint =
1062cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1063b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1064b9c1b51eSKate Stone               BreakpointLocation *location =
1065b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1066b9c1b51eSKate Stone               if (location) {
10675a988416SJim Ingham                 location->SetEnabled(false);
10685a988416SJim Ingham                 ++loc_count;
10695a988416SJim Ingham               }
1070b9c1b51eSKate Stone             } else {
10715a988416SJim Ingham               breakpoint->SetEnabled(false);
10725a988416SJim Ingham               ++disable_count;
10735a988416SJim Ingham             }
10745a988416SJim Ingham           }
10755a988416SJim Ingham         }
1076b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1077b9c1b51eSKate Stone                                        disable_count + loc_count);
10785a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10795a988416SJim Ingham       }
10805a988416SJim Ingham     }
10815a988416SJim Ingham 
10825a988416SJim Ingham     return result.Succeeded();
10835a988416SJim Ingham   }
10845a988416SJim Ingham };
10855a988416SJim Ingham 
10865a988416SJim Ingham // CommandObjectBreakpointList
10871f0f5b5bSZachary Turner 
10881f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10896f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1090c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10911f0f5b5bSZachary Turner 
10925a988416SJim Ingham #pragma mark List
10935a988416SJim Ingham 
1094b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
10955a988416SJim Ingham public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)1096b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1097b9c1b51eSKate Stone       : CommandObjectParsed(
1098b9c1b51eSKate Stone             interpreter, "breakpoint list",
10995a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
1100abb0ed44SKazu Hirata             nullptr) {
11015a988416SJim Ingham     CommandArgumentEntry arg;
11025a988416SJim Ingham     CommandArgumentData bp_id_arg;
11035a988416SJim Ingham 
11045a988416SJim Ingham     // Define the first (and only) variant of this arg.
11055a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11065a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11075a988416SJim Ingham 
1108b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1109b9c1b51eSKate Stone     // argument entry.
11105a988416SJim Ingham     arg.push_back(bp_id_arg);
11115a988416SJim Ingham 
11125a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11135a988416SJim Ingham     m_arguments.push_back(arg);
11145a988416SJim Ingham   }
11155a988416SJim Ingham 
11169e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11175a988416SJim Ingham 
GetOptions()1118b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11195a988416SJim Ingham 
1120b9c1b51eSKate Stone   class CommandOptions : public Options {
11215a988416SJim Ingham   public:
112224f9a2f5SShafik Yaghmour     CommandOptions() = default;
11235a988416SJim Ingham 
11249e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11255a988416SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)112697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1127b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
112897206d57SZachary Turner       Status error;
11293bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11305a988416SJim Ingham 
1131b9c1b51eSKate Stone       switch (short_option) {
11325a988416SJim Ingham       case 'b':
11335a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11345a988416SJim Ingham         break;
113533df7cd3SJim Ingham       case 'D':
113633df7cd3SJim Ingham         m_use_dummy = true;
113733df7cd3SJim Ingham         break;
11385a988416SJim Ingham       case 'f':
11395a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11405a988416SJim Ingham         break;
11415a988416SJim Ingham       case 'v':
11425a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11435a988416SJim Ingham         break;
11445a988416SJim Ingham       case 'i':
11455a988416SJim Ingham         m_internal = true;
11465a988416SJim Ingham         break;
11475a988416SJim Ingham       default:
114836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11495a988416SJim Ingham       }
11505a988416SJim Ingham 
11515a988416SJim Ingham       return error;
11525a988416SJim Ingham     }
11535a988416SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)1154b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11555a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11565a988416SJim Ingham       m_internal = false;
115733df7cd3SJim Ingham       m_use_dummy = false;
11585a988416SJim Ingham     }
11595a988416SJim Ingham 
GetDefinitions()11601f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11621f0f5b5bSZachary Turner     }
11635a988416SJim Ingham 
11645a988416SJim Ingham     // Instance variables to hold the values for command options.
11655a988416SJim Ingham 
11669494c510SJonas Devlieghere     lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11675a988416SJim Ingham 
11685a988416SJim Ingham     bool m_internal;
11699494c510SJonas Devlieghere     bool m_use_dummy = false;
11705a988416SJim Ingham   };
11715a988416SJim Ingham 
11725a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1173b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1174cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11755a988416SJim Ingham 
1176b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1177cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1178bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1179cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11805a988416SJim Ingham 
11815a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11825a988416SJim Ingham 
1183b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11845a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11855a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11865a988416SJim Ingham       return true;
11875a988416SJim Ingham     }
11885a988416SJim Ingham 
11895a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
11905a988416SJim Ingham 
119111eb9c64SZachary Turner     if (command.empty()) {
11925a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
11935a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1194b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
11955a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1196b842f2ecSJim Ingham         if (breakpoint->AllowList())
1197b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1198b842f2ecSJim Ingham                                    m_options.m_level);
11995a988416SJim Ingham       }
12005a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1201b9c1b51eSKate Stone     } else {
12025a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12035a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1204b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1205cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1206b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12075a988416SJim Ingham 
1208b9c1b51eSKate Stone       if (result.Succeeded()) {
1209b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12105a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1211b9c1b51eSKate Stone           Breakpoint *breakpoint =
1212cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1213b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1214b9c1b51eSKate Stone                                    m_options.m_level);
12155a988416SJim Ingham         }
12165a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1217b9c1b51eSKate Stone       } else {
12187428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12195a988416SJim Ingham       }
12205a988416SJim Ingham     }
12215a988416SJim Ingham 
12225a988416SJim Ingham     return result.Succeeded();
12235a988416SJim Ingham   }
12245a988416SJim Ingham 
12255a988416SJim Ingham private:
12265a988416SJim Ingham   CommandOptions m_options;
12275a988416SJim Ingham };
12285a988416SJim Ingham 
12295a988416SJim Ingham // CommandObjectBreakpointClear
12301f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12311f0f5b5bSZachary Turner 
1232f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1233f94668e3SRaphael Isemann #include "CommandOptions.inc"
12341f0f5b5bSZachary Turner 
12355a988416SJim Ingham #pragma mark Clear
12365a988416SJim Ingham 
1237b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12385a988416SJim Ingham public:
1239efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12405a988416SJim Ingham 
CommandObjectBreakpointClear(CommandInterpreter & interpreter)12417428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12427428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1243b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1244b9c1b51eSKate Stone                             "specified source file and line.",
1245abb0ed44SKazu Hirata                             "breakpoint clear <cmd-options>") {}
12465a988416SJim Ingham 
12479e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12485a988416SJim Ingham 
GetOptions()1249b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12505a988416SJim Ingham 
1251b9c1b51eSKate Stone   class CommandOptions : public Options {
12525a988416SJim Ingham   public:
125324f9a2f5SShafik Yaghmour     CommandOptions() = default;
12545a988416SJim Ingham 
12559e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12565a988416SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)125797206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1258b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
125997206d57SZachary Turner       Status error;
12603bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12615a988416SJim Ingham 
1262b9c1b51eSKate Stone       switch (short_option) {
12635a988416SJim Ingham       case 'f':
1264adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
12655a988416SJim Ingham         break;
12665a988416SJim Ingham 
12675a988416SJim Ingham       case 'l':
1268fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12695a988416SJim Ingham         break;
12705a988416SJim Ingham 
12715a988416SJim Ingham       default:
127236162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12735a988416SJim Ingham       }
12745a988416SJim Ingham 
12755a988416SJim Ingham       return error;
12765a988416SJim Ingham     }
12775a988416SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)1278b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12795a988416SJim Ingham       m_filename.clear();
12805a988416SJim Ingham       m_line_num = 0;
12815a988416SJim Ingham     }
12825a988416SJim Ingham 
GetDefinitions()12831f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
128470602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12851f0f5b5bSZachary Turner     }
12865a988416SJim Ingham 
12875a988416SJim Ingham     // Instance variables to hold the values for command options.
12885a988416SJim Ingham 
12895a988416SJim Ingham     std::string m_filename;
12909494c510SJonas Devlieghere     uint32_t m_line_num = 0;
12915a988416SJim Ingham   };
12925a988416SJim Ingham 
12935a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1294b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1295cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
12965a988416SJim Ingham 
129705097246SAdrian Prantl     // The following are the various types of breakpoints that could be
129805097246SAdrian Prantl     // cleared:
12995a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13005a988416SJim Ingham 
13015a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13025a988416SJim Ingham 
13035a988416SJim Ingham     if (m_options.m_line_num != 0)
13045a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13055a988416SJim Ingham 
1306bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1307cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13085a988416SJim Ingham 
1309cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13105a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13115a988416SJim Ingham 
13125a988416SJim Ingham     // Early return if there's no breakpoint at all.
1313b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13145a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13155a988416SJim Ingham       return result.Succeeded();
13165a988416SJim Ingham     }
13175a988416SJim Ingham 
13185a988416SJim Ingham     // Find matching breakpoints and delete them.
13195a988416SJim Ingham 
13205a988416SJim Ingham     // First create a copy of all the IDs.
13215a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13225a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13239e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13245a988416SJim Ingham 
13255a988416SJim Ingham     int num_cleared = 0;
13265a988416SJim Ingham     StreamString ss;
1327b9c1b51eSKate Stone     switch (break_type) {
13285a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13295a988416SJim Ingham     {
13305a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13315a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13325a988416SJim Ingham 
1333b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13345a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13355a988416SJim Ingham 
1336b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1337b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1338b9c1b51eSKate Stone           // remove the breakpoint.
1339b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13405a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13415a988416SJim Ingham             ss.EOL();
1342cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13435a988416SJim Ingham             ++num_cleared;
13445a988416SJim Ingham           }
13455a988416SJim Ingham         }
13465a988416SJim Ingham       }
1347b9c1b51eSKate Stone     } break;
13485a988416SJim Ingham 
13495a988416SJim Ingham     default:
13505a988416SJim Ingham       break;
13515a988416SJim Ingham     }
13525a988416SJim Ingham 
1353b9c1b51eSKate Stone     if (num_cleared > 0) {
13545a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13555a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1356c156427dSZachary Turner       output_stream << ss.GetString();
13575a988416SJim Ingham       output_stream.EOL();
13585a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1359b9c1b51eSKate Stone     } else {
13605a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13615a988416SJim Ingham     }
13625a988416SJim Ingham 
13635a988416SJim Ingham     return result.Succeeded();
13645a988416SJim Ingham   }
13655a988416SJim Ingham 
13665a988416SJim Ingham private:
13675a988416SJim Ingham   CommandOptions m_options;
13685a988416SJim Ingham };
13695a988416SJim Ingham 
13705a988416SJim Ingham // CommandObjectBreakpointDelete
1371f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1372f94668e3SRaphael Isemann #include "CommandOptions.inc"
13731f0f5b5bSZachary Turner 
13745a988416SJim Ingham #pragma mark Delete
13755a988416SJim Ingham 
1376b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13775a988416SJim Ingham public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)1378b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1379b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1380b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1381b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
1382abb0ed44SKazu Hirata                             nullptr) {
13835a988416SJim Ingham     CommandArgumentEntry arg;
1384b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1385b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1386b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1387b9c1b51eSKate Stone     // arguments vector.
13885a988416SJim Ingham     m_arguments.push_back(arg);
13895a988416SJim Ingham   }
13905a988416SJim Ingham 
13919e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
13925a988416SJim Ingham 
13930e50b9a4SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)13940e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
13950e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
13960e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
13970e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
13980e50b9a4SGongyu Deng         request, nullptr);
13990e50b9a4SGongyu Deng   }
14000e50b9a4SGongyu Deng 
GetOptions()1401b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
140233df7cd3SJim Ingham 
1403b9c1b51eSKate Stone   class CommandOptions : public Options {
140433df7cd3SJim Ingham   public:
140524f9a2f5SShafik Yaghmour     CommandOptions() = default;
140633df7cd3SJim Ingham 
14079e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
140833df7cd3SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)140997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1410b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
141197206d57SZachary Turner       Status error;
141233df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
141333df7cd3SJim Ingham 
1414b9c1b51eSKate Stone       switch (short_option) {
141533df7cd3SJim Ingham       case 'f':
141633df7cd3SJim Ingham         m_force = true;
141733df7cd3SJim Ingham         break;
141833df7cd3SJim Ingham 
141933df7cd3SJim Ingham       case 'D':
142033df7cd3SJim Ingham         m_use_dummy = true;
142133df7cd3SJim Ingham         break;
142233df7cd3SJim Ingham 
14233726ac41SJim Ingham       case 'd':
14243726ac41SJim Ingham         m_delete_disabled = true;
14253726ac41SJim Ingham         break;
14263726ac41SJim Ingham 
142733df7cd3SJim Ingham       default:
142836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
142933df7cd3SJim Ingham       }
143033df7cd3SJim Ingham 
143133df7cd3SJim Ingham       return error;
143233df7cd3SJim Ingham     }
143333df7cd3SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)1434b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
143533df7cd3SJim Ingham       m_use_dummy = false;
143633df7cd3SJim Ingham       m_force = false;
14373726ac41SJim Ingham       m_delete_disabled = false;
143833df7cd3SJim Ingham     }
143933df7cd3SJim Ingham 
GetDefinitions()14401f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
144170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14421f0f5b5bSZachary Turner     }
144333df7cd3SJim Ingham 
144433df7cd3SJim Ingham     // Instance variables to hold the values for command options.
14459494c510SJonas Devlieghere     bool m_use_dummy = false;
14469494c510SJonas Devlieghere     bool m_force = false;
14479494c510SJonas Devlieghere     bool m_delete_disabled = false;
144833df7cd3SJim Ingham   };
144933df7cd3SJim Ingham 
14505a988416SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1451b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1452cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14533726ac41SJim Ingham     result.Clear();
14545a988416SJim Ingham 
1455bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1456cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14575a988416SJim Ingham 
14583726ac41SJim Ingham     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       return false;
14655a988416SJim Ingham     }
14665a988416SJim Ingham 
14670018c712SJim Ingham     // Handle the delete all breakpoints case:
14683726ac41SJim Ingham     if (command.empty() && !m_options.m_delete_disabled) {
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);
14810018c712SJim Ingham       return result.Succeeded();
14820018c712SJim Ingham     }
14830018c712SJim Ingham 
14840018c712SJim Ingham     // Either we have some kind of breakpoint specification(s),
14850018c712SJim Ingham     // or we are handling "break disable --deleted".  Gather the list
14860018c712SJim Ingham     // of breakpoints to delete here, the we'll delete them below.
14875a988416SJim Ingham     BreakpointIDList valid_bp_ids;
14883726ac41SJim Ingham 
14893726ac41SJim Ingham     if (m_options.m_delete_disabled) {
14903726ac41SJim Ingham       BreakpointIDList excluded_bp_ids;
14913726ac41SJim Ingham 
14923726ac41SJim Ingham       if (!command.empty()) {
14933726ac41SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
14943726ac41SJim Ingham             command, &target, result, &excluded_bp_ids,
14953726ac41SJim Ingham             BreakpointName::Permissions::PermissionKinds::deletePerm);
14960018c712SJim Ingham         if (!result.Succeeded())
14970018c712SJim Ingham           return false;
14983726ac41SJim Ingham       }
14990018c712SJim Ingham 
15003726ac41SJim Ingham       for (auto breakpoint_sp : breakpoints.Breakpoints()) {
15013726ac41SJim Ingham         if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
15023726ac41SJim Ingham           BreakpointID bp_id(breakpoint_sp->GetID());
15033726ac41SJim Ingham           size_t pos = 0;
15043726ac41SJim Ingham           if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
15053726ac41SJim Ingham             valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
15063726ac41SJim Ingham         }
15073726ac41SJim Ingham       }
15083726ac41SJim Ingham       if (valid_bp_ids.GetSize() == 0) {
15093726ac41SJim Ingham         result.AppendError("No disabled breakpoints.");
15103726ac41SJim Ingham         return false;
15113726ac41SJim Ingham       }
15123726ac41SJim Ingham     } else {
1513b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1514cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1515b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
15160018c712SJim Ingham       if (!result.Succeeded())
15170018c712SJim Ingham         return false;
15183726ac41SJim Ingham     }
15195a988416SJim Ingham 
15205a988416SJim Ingham     int delete_count = 0;
15215a988416SJim Ingham     int disable_count = 0;
15225a988416SJim Ingham     const size_t count = valid_bp_ids.GetSize();
1523b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
15245a988416SJim Ingham       BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15255a988416SJim Ingham 
1526b9c1b51eSKate Stone       if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1527b9c1b51eSKate Stone         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1528b9c1b51eSKate Stone           Breakpoint *breakpoint =
1529cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1530b9c1b51eSKate Stone           BreakpointLocation *location =
1531b9c1b51eSKate Stone               breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1532b9c1b51eSKate Stone           // It makes no sense to try to delete individual locations, so we
1533b9c1b51eSKate Stone           // disable them instead.
1534b9c1b51eSKate Stone           if (location) {
15355a988416SJim Ingham             location->SetEnabled(false);
15365a988416SJim Ingham             ++disable_count;
15375a988416SJim Ingham           }
1538b9c1b51eSKate Stone         } else {
1539cb2380c9SRaphael Isemann           target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15405a988416SJim Ingham           ++delete_count;
15415a988416SJim Ingham         }
15425a988416SJim Ingham       }
15435a988416SJim Ingham     }
1544b9c1b51eSKate Stone     result.AppendMessageWithFormat(
1545b9c1b51eSKate Stone         "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15465a988416SJim Ingham         delete_count, disable_count);
15475a988416SJim Ingham     result.SetStatus(eReturnStatusSuccessFinishNoResult);
15485a988416SJim Ingham     return result.Succeeded();
15495a988416SJim Ingham   }
15509e85e5a8SEugene Zelenko 
155133df7cd3SJim Ingham private:
155233df7cd3SJim Ingham   CommandOptions m_options;
155333df7cd3SJim Ingham };
155433df7cd3SJim Ingham 
15555e09c8c3SJim Ingham // CommandObjectBreakpointName
1556f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1557f94668e3SRaphael Isemann #include "CommandOptions.inc"
1558bd68a052SRaphael Isemann 
1559b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15605e09c8c3SJim Ingham public:
BreakpointNameOptionGroup()1561b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1562abb0ed44SKazu Hirata       : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
15635e09c8c3SJim Ingham 
15649e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15655e09c8c3SJim Ingham 
GetDefinitions()15661f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
156770602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15685e09c8c3SJim Ingham   }
15695e09c8c3SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)157097206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1571b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
157297206d57SZachary Turner     Status error;
15735e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15745e09c8c3SJim Ingham 
1575b9c1b51eSKate Stone     switch (short_option) {
15765e09c8c3SJim Ingham     case 'N':
1577fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1578b9c1b51eSKate Stone           error.Success())
1579fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15805e09c8c3SJim Ingham       break;
15815e09c8c3SJim Ingham     case 'B':
1582fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1583b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15848cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1585fe11483bSZachary Turner             option_arg.str().c_str());
15865e09c8c3SJim Ingham       break;
15875e09c8c3SJim Ingham     case 'D':
1588fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1589b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15908cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1591fe11483bSZachary Turner             option_arg.str().c_str());
15925e09c8c3SJim Ingham       break;
1593e9632ebaSJim Ingham     case 'H':
1594e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1595e9632ebaSJim Ingham       break;
15965e09c8c3SJim Ingham 
15975e09c8c3SJim Ingham     default:
159836162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15995e09c8c3SJim Ingham     }
16005e09c8c3SJim Ingham     return error;
16015e09c8c3SJim Ingham   }
16025e09c8c3SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)1603b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
16045e09c8c3SJim Ingham     m_name.Clear();
16055e09c8c3SJim Ingham     m_breakpoint.Clear();
16065e09c8c3SJim Ingham     m_use_dummy.Clear();
16075e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1608e9632ebaSJim Ingham     m_help_string.Clear();
16095e09c8c3SJim Ingham   }
16105e09c8c3SJim Ingham 
16115e09c8c3SJim Ingham   OptionValueString m_name;
16125e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
16135e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1614e9632ebaSJim Ingham   OptionValueString m_help_string;
16155e09c8c3SJim Ingham };
16165e09c8c3SJim Ingham 
1617f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1618f94668e3SRaphael Isemann #include "CommandOptions.inc"
1619b842f2ecSJim Ingham 
16208fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1621b842f2ecSJim Ingham public:
162224f9a2f5SShafik Yaghmour   BreakpointAccessOptionGroup() = default;
1623b842f2ecSJim Ingham 
1624b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1625b842f2ecSJim Ingham 
GetDefinitions()1626b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1627b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1628b842f2ecSJim Ingham   }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1629b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1630b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1631b842f2ecSJim Ingham     Status error;
1632a925974bSAdrian Prantl     const int short_option =
1633a925974bSAdrian Prantl         g_breakpoint_access_options[option_idx].short_option;
1634b842f2ecSJim Ingham 
1635b842f2ecSJim Ingham     switch (short_option) {
1636b842f2ecSJim Ingham     case 'L': {
1637b842f2ecSJim Ingham       bool value, success;
163847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1639b842f2ecSJim Ingham       if (success) {
1640b842f2ecSJim Ingham         m_permissions.SetAllowList(value);
1641b842f2ecSJim Ingham       } else
1642b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1643b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1644b842f2ecSJim Ingham             option_arg.str().c_str());
1645b842f2ecSJim Ingham     } break;
1646b842f2ecSJim Ingham     case 'A': {
1647b842f2ecSJim Ingham       bool value, success;
164847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1649b842f2ecSJim Ingham       if (success) {
1650b842f2ecSJim Ingham         m_permissions.SetAllowDisable(value);
1651b842f2ecSJim Ingham       } else
1652b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1653b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1654b842f2ecSJim Ingham             option_arg.str().c_str());
1655b842f2ecSJim Ingham     } break;
1656b842f2ecSJim Ingham     case 'D': {
1657b842f2ecSJim Ingham       bool value, success;
165847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1659b842f2ecSJim Ingham       if (success) {
1660b842f2ecSJim Ingham         m_permissions.SetAllowDelete(value);
1661b842f2ecSJim Ingham       } else
1662b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1663b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1664b842f2ecSJim Ingham             option_arg.str().c_str());
1665b842f2ecSJim Ingham     } break;
166636162014SRaphael Isemann     default:
166736162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
1668b842f2ecSJim Ingham     }
1669b842f2ecSJim Ingham 
1670b842f2ecSJim Ingham     return error;
1671b842f2ecSJim Ingham   }
1672b842f2ecSJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)1673a925974bSAdrian Prantl   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1674b842f2ecSJim Ingham 
GetPermissions() const1675a925974bSAdrian Prantl   const BreakpointName::Permissions &GetPermissions() const {
1676b842f2ecSJim Ingham     return m_permissions;
1677b842f2ecSJim Ingham   }
1678b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1679b842f2ecSJim Ingham };
1680b842f2ecSJim Ingham 
1681b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1682b842f2ecSJim Ingham public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)1683b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1684b842f2ecSJim Ingham       : CommandObjectParsed(
1685a925974bSAdrian Prantl             interpreter, "configure",
1686a925974bSAdrian Prantl             "Configure the options for the breakpoint"
1687b842f2ecSJim Ingham             " name provided.  "
1688b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1689b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1690b842f2ecSJim Ingham             "on the name.",
1691b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1692abb0ed44SKazu Hirata             "<breakpoint-name-list>") {
1693b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1694b842f2ecSJim Ingham     // command.
1695b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1696b842f2ecSJim Ingham     CommandArgumentData id_arg;
1697b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1698b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1699b842f2ecSJim Ingham     arg1.push_back(id_arg);
1700b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1701b842f2ecSJim Ingham 
1702a925974bSAdrian Prantl     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1703a925974bSAdrian Prantl     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1704b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1705a925974bSAdrian Prantl     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1706e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1707b842f2ecSJim Ingham     m_option_group.Finalize();
1708b842f2ecSJim Ingham   }
1709b842f2ecSJim Ingham 
1710b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1711b842f2ecSJim Ingham 
GetOptions()1712b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1713b842f2ecSJim Ingham 
1714b842f2ecSJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1715b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1716b842f2ecSJim Ingham 
1717b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1718b842f2ecSJim Ingham     if (argc == 0) {
1719b842f2ecSJim Ingham       result.AppendError("No names provided.");
1720b842f2ecSJim Ingham       return false;
1721b842f2ecSJim Ingham     }
1722b842f2ecSJim Ingham 
1723cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1724b842f2ecSJim Ingham 
1725b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1726cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1727b842f2ecSJim Ingham 
1728b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1729b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1730b842f2ecSJim Ingham       Status error;
1731a925974bSAdrian Prantl       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1732b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1733b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1734b842f2ecSJim Ingham         return false;
1735b842f2ecSJim Ingham       }
1736b842f2ecSJim Ingham     }
173705097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
173805097246SAdrian Prantl     // check the error:
1739b842f2ecSJim Ingham     BreakpointSP bp_sp;
1740a925974bSAdrian Prantl     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1741b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1742cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1743a925974bSAdrian Prantl       if (!bp_sp) {
1744b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1745b842f2ecSJim Ingham                                       bp_id);
1746b842f2ecSJim Ingham         return false;
1747b842f2ecSJim Ingham       }
1748b842f2ecSJim Ingham     }
1749b842f2ecSJim Ingham 
1750b842f2ecSJim Ingham     Status error;
1751b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1752b842f2ecSJim Ingham       ConstString name(entry.c_str());
1753cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1754b842f2ecSJim Ingham       if (!bp_name)
1755b842f2ecSJim Ingham         continue;
1756e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1757e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1758e9632ebaSJim Ingham 
1759b842f2ecSJim Ingham       if (bp_sp)
1760cfb96d84SJim Ingham         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1761b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1762b842f2ecSJim Ingham       else
1763cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1764b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1765b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1766b842f2ecSJim Ingham     }
1767b842f2ecSJim Ingham     return true;
1768b842f2ecSJim Ingham   }
1769b842f2ecSJim Ingham 
1770b842f2ecSJim Ingham private:
1771b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1772b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1773b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1774b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1775b842f2ecSJim Ingham };
1776b842f2ecSJim Ingham 
1777b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17785e09c8c3SJim Ingham public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)1779b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1780b9c1b51eSKate Stone       : CommandObjectParsed(
1781b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
1782abb0ed44SKazu Hirata             "breakpoint name add <command-options> <breakpoint-id-list>") {
1783b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1784b9c1b51eSKate Stone     // command.
17855e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17865e09c8c3SJim Ingham     CommandArgumentData id_arg;
17875e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17885e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17895e09c8c3SJim Ingham     arg1.push_back(id_arg);
17905e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17915e09c8c3SJim Ingham 
17925e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17935e09c8c3SJim Ingham     m_option_group.Finalize();
17945e09c8c3SJim Ingham   }
17955e09c8c3SJim Ingham 
17969e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17975e09c8c3SJim Ingham 
1798e87362e6SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1799e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1800e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1801e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1802e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1803e87362e6SGongyu Deng         request, nullptr);
1804e87362e6SGongyu Deng   }
1805e87362e6SGongyu Deng 
GetOptions()1806b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18075e09c8c3SJim Ingham 
18085e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1809b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1810b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18111b1c8e4aSDavid Spickett       result.AppendError("No name option provided.");
18125e09c8c3SJim Ingham       return false;
18135e09c8c3SJim Ingham     }
18145e09c8c3SJim Ingham 
1815cb2380c9SRaphael Isemann     Target &target =
1816b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18175e09c8c3SJim Ingham 
1818bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1819cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18205e09c8c3SJim Ingham 
1821cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18225e09c8c3SJim Ingham 
18235e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1824b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18251b1c8e4aSDavid Spickett       result.AppendError("No breakpoints, cannot add names.");
18265e09c8c3SJim Ingham       return false;
18275e09c8c3SJim Ingham     }
18285e09c8c3SJim Ingham 
18295e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18305e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1831b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1832cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1833b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18345e09c8c3SJim Ingham 
1835b9c1b51eSKate Stone     if (result.Succeeded()) {
1836b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18371b1c8e4aSDavid Spickett         result.AppendError("No breakpoints specified, cannot add names.");
18385e09c8c3SJim Ingham         return false;
18395e09c8c3SJim Ingham       }
18405e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1841b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1842b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1843b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1844b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1845b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1846b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18475e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1848cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18495e09c8c3SJim Ingham       }
18505e09c8c3SJim Ingham     }
18515e09c8c3SJim Ingham 
18525e09c8c3SJim Ingham     return true;
18535e09c8c3SJim Ingham   }
18545e09c8c3SJim Ingham 
18555e09c8c3SJim Ingham private:
18565e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18575e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18585e09c8c3SJim Ingham };
18595e09c8c3SJim Ingham 
1860b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18615e09c8c3SJim Ingham public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)1862b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1863b9c1b51eSKate Stone       : CommandObjectParsed(
1864b9c1b51eSKate Stone             interpreter, "delete",
18655e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
1866abb0ed44SKazu Hirata             "breakpoint name delete <command-options> <breakpoint-id-list>") {
1867b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1868b9c1b51eSKate Stone     // command.
18695e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18705e09c8c3SJim Ingham     CommandArgumentData id_arg;
18715e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18725e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18735e09c8c3SJim Ingham     arg1.push_back(id_arg);
18745e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18755e09c8c3SJim Ingham 
18765e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18775e09c8c3SJim Ingham     m_option_group.Finalize();
18785e09c8c3SJim Ingham   }
18795e09c8c3SJim Ingham 
18809e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18815e09c8c3SJim Ingham 
1882e87362e6SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1883e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1884e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1885e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1886e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1887e87362e6SGongyu Deng         request, nullptr);
1888e87362e6SGongyu Deng   }
1889e87362e6SGongyu Deng 
GetOptions()1890b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18915e09c8c3SJim Ingham 
18925e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1893b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1894b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18951b1c8e4aSDavid Spickett       result.AppendError("No name option provided.");
18965e09c8c3SJim Ingham       return false;
18975e09c8c3SJim Ingham     }
18985e09c8c3SJim Ingham 
1899cb2380c9SRaphael Isemann     Target &target =
1900b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19015e09c8c3SJim Ingham 
1902bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1903cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
19045e09c8c3SJim Ingham 
1905cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
19065e09c8c3SJim Ingham 
19075e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1908b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19091b1c8e4aSDavid Spickett       result.AppendError("No breakpoints, cannot delete names.");
19105e09c8c3SJim Ingham       return false;
19115e09c8c3SJim Ingham     }
19125e09c8c3SJim Ingham 
19135e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19145e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1915b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1916cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1917b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
19185e09c8c3SJim Ingham 
1919b9c1b51eSKate Stone     if (result.Succeeded()) {
1920b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19211b1c8e4aSDavid Spickett         result.AppendError("No breakpoints specified, cannot delete names.");
19225e09c8c3SJim Ingham         return false;
19235e09c8c3SJim Ingham       }
1924b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19255e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1926b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1927b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1928b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19295e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1930cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19315e09c8c3SJim Ingham       }
19325e09c8c3SJim Ingham     }
19335e09c8c3SJim Ingham 
19345e09c8c3SJim Ingham     return true;
19355e09c8c3SJim Ingham   }
19365e09c8c3SJim Ingham 
19375e09c8c3SJim Ingham private:
19385e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19395e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19405e09c8c3SJim Ingham };
19415e09c8c3SJim Ingham 
1942b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19435e09c8c3SJim Ingham public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)1944b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1945b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1946b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1947b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1948b842f2ecSJim Ingham                             "names",
1949abb0ed44SKazu Hirata                             "breakpoint name list <command-options>") {
1950b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19515e09c8c3SJim Ingham     m_option_group.Finalize();
19525e09c8c3SJim Ingham   }
19535e09c8c3SJim Ingham 
19549e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19555e09c8c3SJim Ingham 
GetOptions()1956b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19575e09c8c3SJim Ingham 
19585e09c8c3SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)1959b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1960cb2380c9SRaphael Isemann     Target &target =
1961b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19625e09c8c3SJim Ingham 
1963b842f2ecSJim Ingham     std::vector<std::string> name_list;
1964b842f2ecSJim Ingham     if (command.empty()) {
1965cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1966b842f2ecSJim Ingham     } else {
1967a925974bSAdrian Prantl       for (const Args::ArgEntry &arg : command) {
1968b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1969b842f2ecSJim Ingham       }
1970b842f2ecSJim Ingham     }
1971b842f2ecSJim Ingham 
1972b842f2ecSJim Ingham     if (name_list.empty()) {
1973b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1974b842f2ecSJim Ingham     } else {
1975b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1976b842f2ecSJim Ingham         const char *name = name_str.c_str();
1977b842f2ecSJim Ingham         // First print out the options for the name:
1978b842f2ecSJim Ingham         Status error;
1979cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1980cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1981a925974bSAdrian Prantl         if (bp_name) {
1982b842f2ecSJim Ingham           StreamString s;
1983b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1984a925974bSAdrian Prantl           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1985b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1986b842f2ecSJim Ingham           }
1987b842f2ecSJim Ingham 
1988bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1989cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19905e09c8c3SJim Ingham 
1991cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1992b842f2ecSJim Ingham           bool any_set = false;
1993b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1994b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19955e09c8c3SJim Ingham               StreamString s;
1996b842f2ecSJim Ingham               any_set = true;
19975e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19985e09c8c3SJim Ingham               s.EOL();
1999c156427dSZachary Turner               result.AppendMessage(s.GetString());
20005e09c8c3SJim Ingham             }
20015e09c8c3SJim Ingham           }
2002b842f2ecSJim Ingham           if (!any_set)
2003b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
2004b9c1b51eSKate Stone         } else {
2005b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
20065e09c8c3SJim Ingham         }
2007b842f2ecSJim Ingham       }
20085e09c8c3SJim Ingham     }
20095e09c8c3SJim Ingham     return true;
20105e09c8c3SJim Ingham   }
20115e09c8c3SJim Ingham 
20125e09c8c3SJim Ingham private:
20135e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20145e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20155e09c8c3SJim Ingham };
20165e09c8c3SJim Ingham 
2017e14dc268SJim Ingham // CommandObjectBreakpointName
2018b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20195e09c8c3SJim Ingham public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)20207428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2021b9c1b51eSKate Stone       : CommandObjectMultiword(
2022aaaf8e4cSJim Ingham             interpreter, "name", "Commands to manage breakpoint names") {
2023aaaf8e4cSJim Ingham 
2024aaaf8e4cSJim Ingham 
2025aaaf8e4cSJim Ingham     SetHelpLong(
2026aaaf8e4cSJim Ingham             R"(
2027aaaf8e4cSJim Ingham Breakpoint names provide a general tagging mechanism for breakpoints.  Each
2028aaaf8e4cSJim Ingham breakpoint name can be added to any number of breakpoints, and each breakpoint
2029aaaf8e4cSJim Ingham can have any number of breakpoint names attached to it. For instance:
2030aaaf8e4cSJim Ingham 
2031aaaf8e4cSJim Ingham     (lldb) break name add -N MyName 1-10
2032aaaf8e4cSJim Ingham 
2033aaaf8e4cSJim Ingham adds the name MyName to breakpoints 1-10, and:
2034aaaf8e4cSJim Ingham 
2035aaaf8e4cSJim Ingham     (lldb) break set -n myFunc -N Name1 -N Name2
2036aaaf8e4cSJim Ingham 
2037aaaf8e4cSJim Ingham adds two names to the breakpoint set at myFunc.
2038aaaf8e4cSJim Ingham 
2039aaaf8e4cSJim Ingham They have a number of interrelated uses:
2040aaaf8e4cSJim Ingham 
2041aaaf8e4cSJim Ingham 1) They provide a stable way to refer to a breakpoint (e.g. in another
2042aaaf8e4cSJim Ingham breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
2043aaaf8e4cSJim Ingham it depends on the order of breakpoint creation.  Giving a name to the breakpoint
2044aaaf8e4cSJim Ingham you want to act on, and then referring to it by name, is more robust:
2045aaaf8e4cSJim Ingham 
2046aaaf8e4cSJim Ingham     (lldb) break set -n myFunc -N BKPT1
2047aaaf8e4cSJim Ingham     (lldb) break set -n myOtherFunc -C "break disable BKPT1"
2048aaaf8e4cSJim Ingham 
2049aaaf8e4cSJim Ingham 2) This is actually just a specific use of a more general feature of breakpoint
2050aaaf8e4cSJim Ingham names.  The <breakpt-id-list> argument type used to specify one or more
2051aaaf8e4cSJim Ingham breakpoints in most of the commands that deal with breakpoints also accepts
2052aaaf8e4cSJim Ingham breakpoint names.  That allows you to refer to one breakpoint in a stable
2053aaaf8e4cSJim Ingham manner, but also makes them a convenient grouping mechanism, allowing you to
2054aaaf8e4cSJim Ingham easily act on a group of breakpoints by using their name, for instance disabling
2055aaaf8e4cSJim Ingham them all in one action:
2056aaaf8e4cSJim Ingham 
2057aaaf8e4cSJim Ingham     (lldb) break set -n myFunc -N Group1
2058aaaf8e4cSJim Ingham     (lldb) break set -n myOtherFunc -N Group1
2059aaaf8e4cSJim Ingham     (lldb) break disable Group1
2060aaaf8e4cSJim Ingham 
2061aaaf8e4cSJim Ingham 3) But breakpoint names are also entities in their own right, and can be
2062aaaf8e4cSJim Ingham configured with all the modifiable attributes of a breakpoint.  Then when you
2063aaaf8e4cSJim Ingham add a breakpoint name to a breakpoint, the breakpoint will be configured to
2064aaaf8e4cSJim Ingham match the state of the breakpoint name.  The link between the name and the
2065aaaf8e4cSJim Ingham breakpoints sharing it remains live, so if you change the configuration on the
2066aaaf8e4cSJim Ingham name, it will also change the configurations on the breakpoints:
2067aaaf8e4cSJim Ingham 
2068aaaf8e4cSJim Ingham     (lldb) break name configure -i 10 IgnoreSome
2069aaaf8e4cSJim Ingham     (lldb) break set -n myFunc -N IgnoreSome
2070aaaf8e4cSJim Ingham     (lldb) break list IgnoreSome
2071aaaf8e4cSJim Ingham     2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2072aaaf8e4cSJim Ingham       Names:
2073aaaf8e4cSJim Ingham         IgnoreSome
2074aaaf8e4cSJim Ingham     (lldb) break name configure -i 5 IgnoreSome
2075aaaf8e4cSJim Ingham     (lldb) break list IgnoreSome
2076aaaf8e4cSJim Ingham     2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2077aaaf8e4cSJim Ingham       Names:
2078aaaf8e4cSJim Ingham         IgnoreSome
2079aaaf8e4cSJim Ingham 
2080aaaf8e4cSJim Ingham Options that are not configured on a breakpoint name don't affect the value of
2081aaaf8e4cSJim Ingham those options on the breakpoints they are added to.  So for instance, if Name1
2082aaaf8e4cSJim Ingham has the -i option configured and Name2 the -c option, adding both names to a
2083aaaf8e4cSJim Ingham breakpoint will set the -i option from Name1 and the -c option from Name2, and
2084aaaf8e4cSJim Ingham the other options will be unaltered.
2085aaaf8e4cSJim Ingham 
2086aaaf8e4cSJim Ingham If you add multiple names to a breakpoint which have configured values for
2087aaaf8e4cSJim Ingham the same option, the last name added's value wins.
2088aaaf8e4cSJim Ingham 
2089aaaf8e4cSJim Ingham The "liveness" of these settings is one way, from name to breakpoint.
2090aaaf8e4cSJim Ingham If you use "break modify" to change an option that is also configured on a name
2091aaaf8e4cSJim Ingham which that breakpoint has, the "break modify" command will override the setting
2092aaaf8e4cSJim Ingham for that breakpoint, but won't change the value configured in the name or on the
2093aaaf8e4cSJim Ingham other breakpoints sharing that name.
2094aaaf8e4cSJim Ingham 
2095aaaf8e4cSJim Ingham 4) Breakpoint names are also a convenient way to copy option sets from one
2096aaaf8e4cSJim Ingham breakpoint to another.  Using the -B option to "breakpoint name configure" makes
2097aaaf8e4cSJim Ingham a name configured with all the options of the original breakpoint.  Then
2098aaaf8e4cSJim Ingham adding that name to another breakpoint copies over all the values from the
2099aaaf8e4cSJim Ingham original breakpoint to the new one.
2100aaaf8e4cSJim Ingham 
2101aaaf8e4cSJim Ingham 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2102aaaf8e4cSJim Ingham operations that act on all breakpoints: "break delete", "break disable" and
2103aaaf8e4cSJim Ingham "break list".  You do that by specifying a "false" value for the
2104aaaf8e4cSJim Ingham --allow-{list,delete,disable} options to "breakpoint name configure" and then
2105aaaf8e4cSJim Ingham adding that name to a breakpoint.
2106aaaf8e4cSJim Ingham 
2107aaaf8e4cSJim Ingham This won't keep the breakpoint from being deleted or disabled if you refer to it
2108aaaf8e4cSJim Ingham specifically by ID. The point of the feature is to make sure users don't
2109aaaf8e4cSJim Ingham inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2110aaaf8e4cSJim Ingham for its own purposes) as part of a "delete all" or "disable all" operation.  The
2111aaaf8e4cSJim Ingham list hiding is because it's confusing for people to see breakpoints they
2112aaaf8e4cSJim Ingham didn't set.
2113aaaf8e4cSJim Ingham 
2114aaaf8e4cSJim Ingham )");
2115b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2116b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2117b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2118b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2119b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2120b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2121b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2122b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
21235e09c8c3SJim Ingham 
21245e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
21255e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
21265e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2127b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
21285e09c8c3SJim Ingham   }
21295e09c8c3SJim Ingham 
21309e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
21315e09c8c3SJim Ingham };
21325e09c8c3SJim Ingham 
2133e14dc268SJim Ingham // CommandObjectBreakpointRead
21343acdf385SJim Ingham #pragma mark Read::CommandOptions
2135f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2136f94668e3SRaphael Isemann #include "CommandOptions.inc"
21371f0f5b5bSZachary Turner 
21381f0f5b5bSZachary Turner #pragma mark Read
2139e14dc268SJim Ingham 
2140e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2141e14dc268SJim Ingham public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)2142e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2143e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2144e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2145e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2146abb0ed44SKazu Hirata                             nullptr) {}
2147e14dc268SJim Ingham 
2148e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2149e14dc268SJim Ingham 
GetOptions()2150e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2151e14dc268SJim Ingham 
2152e14dc268SJim Ingham   class CommandOptions : public Options {
2153e14dc268SJim Ingham   public:
215424f9a2f5SShafik Yaghmour     CommandOptions() = default;
2155e14dc268SJim Ingham 
2156e14dc268SJim Ingham     ~CommandOptions() override = default;
2157e14dc268SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)215897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2159e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
216097206d57SZachary Turner       Status error;
2161e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2162e14dc268SJim Ingham 
2163e14dc268SJim Ingham       switch (short_option) {
2164e14dc268SJim Ingham       case 'f':
2165adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2166e14dc268SJim Ingham         break;
21673acdf385SJim Ingham       case 'N': {
216897206d57SZachary Turner         Status name_error;
21693acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
21703acdf385SJim Ingham                                                   name_error)) {
21713acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21723acdf385SJim Ingham                                          name_error.AsCString());
21733acdf385SJim Ingham         }
2174adcd0268SBenjamin Kramer         m_names.push_back(std::string(option_arg));
21753acdf385SJim Ingham         break;
21763acdf385SJim Ingham       }
2177e14dc268SJim Ingham       default:
217836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2179e14dc268SJim Ingham       }
2180e14dc268SJim Ingham 
2181e14dc268SJim Ingham       return error;
2182e14dc268SJim Ingham     }
2183e14dc268SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)2184e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2185e14dc268SJim Ingham       m_filename.clear();
21863acdf385SJim Ingham       m_names.clear();
2187e14dc268SJim Ingham     }
2188e14dc268SJim Ingham 
GetDefinitions()21891f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
219070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
21911f0f5b5bSZachary Turner     }
2192e14dc268SJim Ingham 
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)219322e63cbaSGongyu Deng     void HandleOptionArgumentCompletion(
219422e63cbaSGongyu Deng         CompletionRequest &request, OptionElementVector &opt_element_vector,
219522e63cbaSGongyu Deng         int opt_element_index, CommandInterpreter &interpreter) override {
219622e63cbaSGongyu Deng       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
219722e63cbaSGongyu Deng       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
219822e63cbaSGongyu Deng 
219922e63cbaSGongyu Deng       switch (GetDefinitions()[opt_defs_index].short_option) {
220022e63cbaSGongyu Deng       case 'f':
220122e63cbaSGongyu Deng         CommandCompletions::InvokeCommonCompletionCallbacks(
220222e63cbaSGongyu Deng             interpreter, CommandCompletions::eDiskFileCompletion, request,
220322e63cbaSGongyu Deng             nullptr);
220422e63cbaSGongyu Deng         break;
220522e63cbaSGongyu Deng 
220622e63cbaSGongyu Deng       case 'N':
220722e63cbaSGongyu Deng         llvm::Optional<FileSpec> file_spec;
220822e63cbaSGongyu Deng         const llvm::StringRef dash_f("-f");
220922e63cbaSGongyu Deng         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
221022e63cbaSGongyu Deng           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
221122e63cbaSGongyu Deng             file_spec.emplace(
221222e63cbaSGongyu Deng                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
221322e63cbaSGongyu Deng             break;
221422e63cbaSGongyu Deng           }
221522e63cbaSGongyu Deng         }
221622e63cbaSGongyu Deng         if (!file_spec)
221722e63cbaSGongyu Deng           return;
221822e63cbaSGongyu Deng 
221922e63cbaSGongyu Deng         FileSystem::Instance().Resolve(*file_spec);
222022e63cbaSGongyu Deng         Status error;
222122e63cbaSGongyu Deng         StructuredData::ObjectSP input_data_sp =
222222e63cbaSGongyu Deng             StructuredData::ParseJSONFromFile(*file_spec, error);
222322e63cbaSGongyu Deng         if (!error.Success())
222422e63cbaSGongyu Deng           return;
222522e63cbaSGongyu Deng 
222622e63cbaSGongyu Deng         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
222722e63cbaSGongyu Deng         if (!bkpt_array)
222822e63cbaSGongyu Deng           return;
222922e63cbaSGongyu Deng 
223022e63cbaSGongyu Deng         const size_t num_bkpts = bkpt_array->GetSize();
223122e63cbaSGongyu Deng         for (size_t i = 0; i < num_bkpts; i++) {
223222e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_object_sp =
223322e63cbaSGongyu Deng               bkpt_array->GetItemAtIndex(i);
223422e63cbaSGongyu Deng           if (!bkpt_object_sp)
223522e63cbaSGongyu Deng             return;
223622e63cbaSGongyu Deng 
223722e63cbaSGongyu Deng           StructuredData::Dictionary *bkpt_dict =
223822e63cbaSGongyu Deng               bkpt_object_sp->GetAsDictionary();
223922e63cbaSGongyu Deng           if (!bkpt_dict)
224022e63cbaSGongyu Deng             return;
224122e63cbaSGongyu Deng 
224222e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_data_sp =
224322e63cbaSGongyu Deng               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
224422e63cbaSGongyu Deng           if (!bkpt_data_sp)
224522e63cbaSGongyu Deng             return;
224622e63cbaSGongyu Deng 
224722e63cbaSGongyu Deng           bkpt_dict = bkpt_data_sp->GetAsDictionary();
224822e63cbaSGongyu Deng           if (!bkpt_dict)
224922e63cbaSGongyu Deng             return;
225022e63cbaSGongyu Deng 
225122e63cbaSGongyu Deng           StructuredData::Array *names_array;
225222e63cbaSGongyu Deng 
225322e63cbaSGongyu Deng           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
225422e63cbaSGongyu Deng             return;
225522e63cbaSGongyu Deng 
225622e63cbaSGongyu Deng           size_t num_names = names_array->GetSize();
225722e63cbaSGongyu Deng 
225822e63cbaSGongyu Deng           for (size_t i = 0; i < num_names; i++) {
225922e63cbaSGongyu Deng             llvm::StringRef name;
226022e63cbaSGongyu Deng             if (names_array->GetItemAtIndexAsString(i, name))
226122e63cbaSGongyu Deng               request.TryCompleteCurrentArg(name);
226222e63cbaSGongyu Deng           }
226322e63cbaSGongyu Deng         }
226422e63cbaSGongyu Deng       }
226522e63cbaSGongyu Deng     }
2266e14dc268SJim Ingham 
2267e14dc268SJim Ingham     std::string m_filename;
22683acdf385SJim Ingham     std::vector<std::string> m_names;
2269e14dc268SJim Ingham   };
2270e14dc268SJim Ingham 
2271e14dc268SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)2272e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2273cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2274e14dc268SJim Ingham 
22753acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2276cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
22773acdf385SJim Ingham 
22788f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
22798f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
228001f16664SJim Ingham     BreakpointIDList new_bps;
2281cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2282cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2283e14dc268SJim Ingham 
2284e14dc268SJim Ingham     if (!error.Success()) {
228501f16664SJim Ingham       result.AppendError(error.AsCString());
228601f16664SJim Ingham       return false;
2287e14dc268SJim Ingham     }
22883acdf385SJim Ingham 
22893acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
22903acdf385SJim Ingham 
22913acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
22923acdf385SJim Ingham     if (num_breakpoints == 0) {
22933acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
22943acdf385SJim Ingham     } else {
22953acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
22963acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
22973acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
22983acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2299cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
23003acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
23013acdf385SJim Ingham                              .get();
23023acdf385SJim Ingham         if (bp)
23033acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
23043acdf385SJim Ingham                              false);
23053acdf385SJim Ingham       }
23063acdf385SJim Ingham     }
2307e14dc268SJim Ingham     return result.Succeeded();
2308e14dc268SJim Ingham   }
2309e14dc268SJim Ingham 
2310e14dc268SJim Ingham private:
2311e14dc268SJim Ingham   CommandOptions m_options;
2312e14dc268SJim Ingham };
2313e14dc268SJim Ingham 
2314e14dc268SJim Ingham // CommandObjectBreakpointWrite
23151f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2316f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2317f94668e3SRaphael Isemann #include "CommandOptions.inc"
23181f0f5b5bSZachary Turner 
23191f0f5b5bSZachary Turner #pragma mark Write
2320e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2321e14dc268SJim Ingham public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)2322e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2323e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2324e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2325e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2326e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2327abb0ed44SKazu Hirata                             nullptr) {
2328e14dc268SJim Ingham     CommandArgumentEntry arg;
2329e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2330e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2331e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2332e14dc268SJim Ingham     // arguments vector.
2333e14dc268SJim Ingham     m_arguments.push_back(arg);
2334e14dc268SJim Ingham   }
2335e14dc268SJim Ingham 
2336e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2337e14dc268SJim Ingham 
2338e87362e6SGongyu Deng   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2339e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
2340e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
2341e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
2342e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2343e87362e6SGongyu Deng         request, nullptr);
2344e87362e6SGongyu Deng   }
2345e87362e6SGongyu Deng 
GetOptions()2346e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2347e14dc268SJim Ingham 
2348e14dc268SJim Ingham   class CommandOptions : public Options {
2349e14dc268SJim Ingham   public:
235024f9a2f5SShafik Yaghmour     CommandOptions() = default;
2351e14dc268SJim Ingham 
2352e14dc268SJim Ingham     ~CommandOptions() override = default;
2353e14dc268SJim Ingham 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)235497206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2355e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
235697206d57SZachary Turner       Status error;
2357e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2358e14dc268SJim Ingham 
2359e14dc268SJim Ingham       switch (short_option) {
2360e14dc268SJim Ingham       case 'f':
2361adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2362e14dc268SJim Ingham         break;
23632d3628e1SJim Ingham       case 'a':
23642d3628e1SJim Ingham         m_append = true;
23652d3628e1SJim Ingham         break;
2366e14dc268SJim Ingham       default:
236736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2368e14dc268SJim Ingham       }
2369e14dc268SJim Ingham 
2370e14dc268SJim Ingham       return error;
2371e14dc268SJim Ingham     }
2372e14dc268SJim Ingham 
OptionParsingStarting(ExecutionContext * execution_context)2373e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2374e14dc268SJim Ingham       m_filename.clear();
23752d3628e1SJim Ingham       m_append = false;
2376e14dc268SJim Ingham     }
2377e14dc268SJim Ingham 
GetDefinitions()23781f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
237970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
23801f0f5b5bSZachary Turner     }
2381e14dc268SJim Ingham 
2382e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2383e14dc268SJim Ingham 
2384e14dc268SJim Ingham     std::string m_filename;
23852d3628e1SJim Ingham     bool m_append = false;
2386e14dc268SJim Ingham   };
2387e14dc268SJim Ingham 
2388e14dc268SJim Ingham protected:
DoExecute(Args & command,CommandReturnObject & result)2389e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2390cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2391e14dc268SJim Ingham 
2392e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2393cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2394e14dc268SJim Ingham 
2395e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
239611eb9c64SZachary Turner     if (!command.empty()) {
2397e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2398cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2399b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2400e14dc268SJim Ingham 
240101f16664SJim Ingham       if (!result.Succeeded()) {
2402e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2403e14dc268SJim Ingham         return false;
2404e14dc268SJim Ingham       }
2405e14dc268SJim Ingham     }
24068f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
24078f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2408cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
24098f3be7a3SJonas Devlieghere                                                      m_options.m_append);
241001f16664SJim Ingham     if (!error.Success()) {
241101f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
241201f16664SJim Ingham                                    error.AsCString());
2413e14dc268SJim Ingham     }
2414e14dc268SJim Ingham     return result.Succeeded();
2415e14dc268SJim Ingham   }
2416e14dc268SJim Ingham 
2417e14dc268SJim Ingham private:
2418e14dc268SJim Ingham   CommandOptions m_options;
2419e14dc268SJim Ingham };
2420e14dc268SJim Ingham 
242130fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2422ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
242330fdc8d8SChris Lattner 
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)2424b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2425b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2426b9c1b51eSKate Stone     : CommandObjectMultiword(
2427b9c1b51eSKate Stone           interpreter, "breakpoint",
24287428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2429b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2430b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2431b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2432b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2433b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2434b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2435b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2436b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2437b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2438b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2439b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2440b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2441b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2442b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2443b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2444b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2445b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2446b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2447b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2448e14dc268SJim Ingham   CommandObjectSP write_command_object(
2449e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2450e14dc268SJim Ingham   CommandObjectSP read_command_object(
2451e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
245230fdc8d8SChris Lattner 
2453b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
245430fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
245530fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2456b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2457b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2458ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2459b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2460b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
24615e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2462e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2463e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
246430fdc8d8SChris Lattner 
246523f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
246623f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
246723f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
246823f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
246923f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
247023f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
247123f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
247223f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
24735e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2474e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2475e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
247630fdc8d8SChris Lattner }
247730fdc8d8SChris Lattner 
24789e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
247930fdc8d8SChris Lattner 
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2480a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2481a925974bSAdrian Prantl     Args &args, Target *target, bool allow_locations,
2482a925974bSAdrian Prantl     CommandReturnObject &result, BreakpointIDList *valid_ids,
2483a925974bSAdrian Prantl     BreakpointName::Permissions ::PermissionKinds purpose) {
248430fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2485b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2486b9c1b51eSKate Stone   //                                  canonical representation
2487b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2488b9c1b51eSKate Stone   //                                  representing a range (in which case there
2489b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2490b9c1b51eSKate Stone   //                                      after of one of the first two types.
24915e09c8c3SJim Ingham   //                                  4). A breakpoint name
2492b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2493b9c1b51eSKate Stone   // one.)
249430fdc8d8SChris Lattner 
249530fdc8d8SChris Lattner   Args temp_args;
249630fdc8d8SChris Lattner 
249711eb9c64SZachary Turner   if (args.empty()) {
2498b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2499b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2500b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
250136f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2502b9c1b51eSKate Stone     } else {
2503b9c1b51eSKate Stone       result.AppendError(
2504b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
250536f3b369SJim Ingham     }
250636f3b369SJim Ingham     return;
250736f3b369SJim Ingham   }
250836f3b369SJim Ingham 
2509b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
251005097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
251105097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
251205097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
251305097246SAdrian Prantl   // into TEMP_ARGS.
251430fdc8d8SChris Lattner 
2515b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2516b842f2ecSJim Ingham                                            purpose, result, temp_args);
251730fdc8d8SChris Lattner 
2518b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2519b9c1b51eSKate Stone   // BreakpointIDList:
252030fdc8d8SChris Lattner 
252116662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
252230fdc8d8SChris Lattner 
252305097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
252405097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
252530fdc8d8SChris Lattner 
2526b9c1b51eSKate Stone   if (result.Succeeded()) {
2527b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
252805097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
252905097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
253030fdc8d8SChris Lattner 
2531c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2532b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
253330fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2534b9c1b51eSKate Stone       Breakpoint *breakpoint =
2535b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2536b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2537c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2538b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
253930fdc8d8SChris Lattner           StreamString id_str;
2540b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2541b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2542c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2543b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2544b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
254530fdc8d8SChris Lattner               id_str.GetData());
254630fdc8d8SChris Lattner         }
2547b9c1b51eSKate Stone       } else {
2548c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2549b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2550b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
25517428a18cSKate Stone             cur_bp_id.GetBreakpointID());
255230fdc8d8SChris Lattner       }
255330fdc8d8SChris Lattner     }
255430fdc8d8SChris Lattner   }
255530fdc8d8SChris Lattner }
2556