180814287SRaphael Isemann //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h"
109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1747cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
18943a2481SJim Ingham #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
20bc0a9a17SJim Ingham #include "lldb/Interpreter/OptionValueFileColonLine.h"
215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
225e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
23b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
240e0984eeSJim Ingham #include "lldb/Target/Language.h"
25b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
26b9c1b51eSKate Stone #include "lldb/Target/Target.h"
271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3030fdc8d8SChris Lattner 
31796ac80bSJonas Devlieghere #include <memory>
32796ac80bSJonas Devlieghere #include <vector>
33796ac80bSJonas Devlieghere 
3430fdc8d8SChris Lattner using namespace lldb;
3530fdc8d8SChris Lattner using namespace lldb_private;
3630fdc8d8SChris Lattner 
37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
3930fdc8d8SChris Lattner   s->IndentMore();
4030fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4130fdc8d8SChris Lattner   s->IndentLess();
4230fdc8d8SChris Lattner   s->EOL();
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
45b842f2ecSJim Ingham // Modifiable Breakpoint Options
46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
47f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
48f94668e3SRaphael Isemann #include "CommandOptions.inc"
49bd68a052SRaphael Isemann 
50a925974bSAdrian Prantl class lldb_private::BreakpointOptionGroup : public OptionGroup {
51b842f2ecSJim Ingham public:
52a925974bSAdrian Prantl   BreakpointOptionGroup() : OptionGroup(), m_bp_opts(false) {}
53b842f2ecSJim Ingham 
54b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
55b842f2ecSJim Ingham 
56b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
57b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
58b842f2ecSJim Ingham   }
59b842f2ecSJim Ingham 
60b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
61b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
62b842f2ecSJim Ingham     Status error;
63a925974bSAdrian Prantl     const int short_option =
64a925974bSAdrian Prantl         g_breakpoint_modify_options[option_idx].short_option;
65b842f2ecSJim Ingham 
66b842f2ecSJim Ingham     switch (short_option) {
67b842f2ecSJim Ingham     case 'c':
6805097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
6905097246SAdrian Prantl       // to say it was passed in.
70b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
71b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
72b842f2ecSJim Ingham       break;
73b842f2ecSJim Ingham     case 'C':
74adcd0268SBenjamin Kramer       m_commands.push_back(std::string(option_arg));
75b842f2ecSJim Ingham       break;
76b842f2ecSJim Ingham     case 'd':
77b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
78b842f2ecSJim Ingham       break;
79b842f2ecSJim Ingham     case 'e':
80b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
81b842f2ecSJim Ingham       break;
82b842f2ecSJim Ingham     case 'G': {
83b842f2ecSJim Ingham       bool value, success;
8447cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
85b842f2ecSJim Ingham       if (success) {
86b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
87b842f2ecSJim Ingham       } else
88b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
89b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
90b842f2ecSJim Ingham             option_arg.str().c_str());
91a925974bSAdrian Prantl     } break;
92a925974bSAdrian Prantl     case 'i': {
93b842f2ecSJim Ingham       uint32_t ignore_count;
94b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
95b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
96b842f2ecSJim Ingham                                        option_arg.str().c_str());
97b842f2ecSJim Ingham       else
98b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
99a925974bSAdrian Prantl     } break;
100b842f2ecSJim Ingham     case 'o': {
101b842f2ecSJim Ingham       bool value, success;
10247cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
103b842f2ecSJim Ingham       if (success) {
104b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
105b842f2ecSJim Ingham       } else
106b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
107b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
108b842f2ecSJim Ingham             option_arg.str().c_str());
109b842f2ecSJim Ingham     } break;
110a925974bSAdrian Prantl     case 't': {
111b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
112b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
113b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
114b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
115b842f2ecSJim Ingham                                          option_arg.str().c_str());
116b842f2ecSJim Ingham       }
117b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
118a925974bSAdrian Prantl     } break;
119b842f2ecSJim Ingham     case 'T':
120b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
121b842f2ecSJim Ingham       break;
122b842f2ecSJim Ingham     case 'q':
123b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
124b842f2ecSJim Ingham       break;
125a925974bSAdrian Prantl     case 'x': {
126b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
127b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
128b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
129b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
130b842f2ecSJim Ingham                                          option_arg.str().c_str());
131b842f2ecSJim Ingham       }
132b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
133a925974bSAdrian Prantl     } break;
134b842f2ecSJim Ingham     default:
13536162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
136b842f2ecSJim Ingham     }
137b842f2ecSJim Ingham 
138b842f2ecSJim Ingham     return error;
139b842f2ecSJim Ingham   }
140b842f2ecSJim Ingham 
141b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
142b842f2ecSJim Ingham     m_bp_opts.Clear();
143b842f2ecSJim Ingham     m_commands.clear();
144b842f2ecSJim Ingham   }
145b842f2ecSJim Ingham 
146b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
147a925974bSAdrian Prantl     if (!m_commands.empty()) {
148a8f3ae7cSJonas Devlieghere       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
149b842f2ecSJim Ingham 
150b842f2ecSJim Ingham       for (std::string &str : m_commands)
151b842f2ecSJim Ingham         cmd_data->user_source.AppendString(str);
152b842f2ecSJim Ingham 
153b842f2ecSJim Ingham       cmd_data->stop_on_error = true;
154b842f2ecSJim Ingham       m_bp_opts.SetCommandDataCallback(cmd_data);
155b842f2ecSJim Ingham     }
156b842f2ecSJim Ingham     return Status();
157b842f2ecSJim Ingham   }
158b842f2ecSJim Ingham 
159a925974bSAdrian Prantl   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
160b842f2ecSJim Ingham 
161b842f2ecSJim Ingham   std::vector<std::string> m_commands;
162b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
163b842f2ecSJim Ingham };
164bd68a052SRaphael Isemann 
165f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
166f94668e3SRaphael Isemann #include "CommandOptions.inc"
167b842f2ecSJim Ingham 
168a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
169b842f2ecSJim Ingham public:
170a925974bSAdrian Prantl   BreakpointDummyOptionGroup() : OptionGroup() {}
171b842f2ecSJim Ingham 
172b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
173b842f2ecSJim Ingham 
174b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
175b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
176b842f2ecSJim Ingham   }
177b842f2ecSJim Ingham 
178b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
179b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
180b842f2ecSJim Ingham     Status error;
181a925974bSAdrian Prantl     const int short_option =
182f1539b9dSJim Ingham         g_breakpoint_dummy_options[option_idx].short_option;
183b842f2ecSJim Ingham 
184b842f2ecSJim Ingham     switch (short_option) {
185b842f2ecSJim Ingham     case 'D':
186b842f2ecSJim Ingham       m_use_dummy = true;
187b842f2ecSJim Ingham       break;
188b842f2ecSJim Ingham     default:
18936162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
190b842f2ecSJim Ingham     }
191b842f2ecSJim Ingham 
192b842f2ecSJim Ingham     return error;
193b842f2ecSJim Ingham   }
194b842f2ecSJim Ingham 
195b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
196b842f2ecSJim Ingham     m_use_dummy = false;
197b842f2ecSJim Ingham   }
198b842f2ecSJim Ingham 
199b842f2ecSJim Ingham   bool m_use_dummy;
200b842f2ecSJim Ingham };
201b842f2ecSJim Ingham 
202f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
203f94668e3SRaphael Isemann #include "CommandOptions.inc"
2041f0f5b5bSZachary Turner 
2055a988416SJim Ingham // CommandObjectBreakpointSet
20630fdc8d8SChris Lattner 
207b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2085a988416SJim Ingham public:
209efe8e7e3SFangrui Song   enum BreakpointSetType {
2105a988416SJim Ingham     eSetTypeInvalid,
2115a988416SJim Ingham     eSetTypeFileAndLine,
2125a988416SJim Ingham     eSetTypeAddress,
2135a988416SJim Ingham     eSetTypeFunctionName,
2145a988416SJim Ingham     eSetTypeFunctionRegexp,
2155a988416SJim Ingham     eSetTypeSourceRegexp,
2163815e702SJim Ingham     eSetTypeException,
2173815e702SJim Ingham     eSetTypeScripted,
218efe8e7e3SFangrui Song   };
2195a988416SJim Ingham 
220b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
221b9c1b51eSKate Stone       : CommandObjectParsed(
222b9c1b51eSKate Stone             interpreter, "breakpoint set",
2235a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2245a988416SJim Ingham             "breakpoint set <cmd-options>"),
225738af7a6SJim Ingham         m_bp_opts(), m_python_class_options("scripted breakpoint", true, 'P'),
226f6a2086dSSam McCall         m_options() {
227b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
228a925974bSAdrian Prantl     m_all_options.Append(&m_python_class_options,
229a925974bSAdrian Prantl                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
230b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
231b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
232b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
233f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
234b842f2ecSJim Ingham     m_all_options.Append(&m_options);
235b842f2ecSJim Ingham     m_all_options.Finalize();
236b842f2ecSJim Ingham   }
2375a988416SJim Ingham 
2389e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2395a988416SJim Ingham 
240b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2415a988416SJim Ingham 
242b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2435a988416SJim Ingham   public:
244b9c1b51eSKate Stone     CommandOptions()
2459494c510SJonas Devlieghere         : OptionGroup(), m_condition(), m_filenames(), m_func_names(),
2469494c510SJonas Devlieghere           m_func_regexp(), m_source_text_regexp(), m_modules() {}
24730fdc8d8SChris Lattner 
2489e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
24987df91b8SJim Ingham 
25097206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
251b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
25297206d57SZachary Turner       Status error;
253a925974bSAdrian Prantl       const int short_option =
254a925974bSAdrian Prantl           g_breakpoint_set_options[option_idx].short_option;
25530fdc8d8SChris Lattner 
256b9c1b51eSKate Stone       switch (short_option) {
257b9c1b51eSKate Stone       case 'a': {
25847cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
259e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
260b9c1b51eSKate Stone       } break;
26130fdc8d8SChris Lattner 
262e732052fSJim Ingham       case 'A':
263e732052fSJim Ingham         m_all_files = true;
264e732052fSJim Ingham         break;
265e732052fSJim Ingham 
266ca36cd16SJim Ingham       case 'b':
267adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
268ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
269ca36cd16SJim Ingham         break;
270ca36cd16SJim Ingham 
2716672a4f5SJonas Devlieghere       case 'u':
272fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
273b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
274fe11483bSZachary Turner                                          option_arg.str().c_str());
27530fdc8d8SChris Lattner         break;
2769e85e5a8SEugene Zelenko 
277b9c1b51eSKate Stone       case 'E': {
278fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
279fab10e89SJim Ingham 
280b9c1b51eSKate Stone         switch (language) {
281fab10e89SJim Ingham         case eLanguageTypeC89:
282fab10e89SJim Ingham         case eLanguageTypeC:
283fab10e89SJim Ingham         case eLanguageTypeC99:
2841d0089faSBruce Mitchener         case eLanguageTypeC11:
285a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
286fab10e89SJim Ingham           break;
287fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2881d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2891d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
2902ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
291a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
292fab10e89SJim Ingham           break;
293fab10e89SJim Ingham         case eLanguageTypeObjC:
294a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
295fab10e89SJim Ingham           break;
296fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
297b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
298b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
299fab10e89SJim Ingham           break;
300fab10e89SJim Ingham         case eLanguageTypeUnknown:
301b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
302b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
303fe11483bSZachary Turner               option_arg.str().c_str());
304fab10e89SJim Ingham           break;
305fab10e89SJim Ingham         default:
306b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
307b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
308fe11483bSZachary Turner               option_arg.str().c_str());
309fab10e89SJim Ingham         }
310b9c1b51eSKate Stone       } break;
311ca36cd16SJim Ingham 
312ca36cd16SJim Ingham       case 'f':
3138f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
314fab10e89SJim Ingham         break;
315ca36cd16SJim Ingham 
316ca36cd16SJim Ingham       case 'F':
317adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
318ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
319ca36cd16SJim Ingham         break;
320ca36cd16SJim Ingham 
321b9c1b51eSKate Stone       case 'h': {
322fab10e89SJim Ingham         bool success;
32347cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
324fab10e89SJim Ingham         if (!success)
325b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
326fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
327fe11483bSZachary Turner               option_arg.str().c_str());
328b9c1b51eSKate Stone       } break;
329eb023e75SGreg Clayton 
330eb023e75SGreg Clayton       case 'H':
331eb023e75SGreg Clayton         m_hardware = true;
332eb023e75SGreg Clayton         break;
333eb023e75SGreg Clayton 
334b9c1b51eSKate Stone       case 'K': {
335a8558b62SJim Ingham         bool success;
336a8558b62SJim Ingham         bool value;
33747cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
338a8558b62SJim Ingham         if (value)
339a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
340a8558b62SJim Ingham         else
341a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
342a8558b62SJim Ingham 
343a8558b62SJim Ingham         if (!success)
344b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
345b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
346fe11483bSZachary Turner               option_arg.str().c_str());
347b9c1b51eSKate Stone       } break;
348ca36cd16SJim Ingham 
349fe11483bSZachary Turner       case 'l':
350fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
351b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
352fe11483bSZachary Turner                                          option_arg.str().c_str());
353ca36cd16SJim Ingham         break;
354055ad9beSIlia K 
35523b1decbSDawn Perchik       case 'L':
356fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
35723b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
358b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
359fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
360fe11483bSZachary Turner               option_arg.str().c_str());
36123b1decbSDawn Perchik         break;
36223b1decbSDawn Perchik 
363b9c1b51eSKate Stone       case 'm': {
364055ad9beSIlia K         bool success;
365055ad9beSIlia K         bool value;
36647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
367055ad9beSIlia K         if (value)
368055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
369055ad9beSIlia K         else
370055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
371055ad9beSIlia K 
372055ad9beSIlia K         if (!success)
373b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
374b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
375fe11483bSZachary Turner               option_arg.str().c_str());
376055ad9beSIlia K         break;
377055ad9beSIlia K       }
378055ad9beSIlia K 
379ca36cd16SJim Ingham       case 'M':
380adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
381ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
382ca36cd16SJim Ingham         break;
383ca36cd16SJim Ingham 
384ca36cd16SJim Ingham       case 'n':
385adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
386ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
387ca36cd16SJim Ingham         break;
388ca36cd16SJim Ingham 
3896fa7681bSZachary Turner       case 'N': {
390fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
391adcd0268SBenjamin Kramer           m_breakpoint_names.push_back(std::string(option_arg));
392ff9a91eaSJim Ingham         else
393ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
394fe11483bSZachary Turner                                          option_arg.str().c_str());
3955e09c8c3SJim Ingham         break;
3966fa7681bSZachary Turner       }
3975e09c8c3SJim Ingham 
398b9c1b51eSKate Stone       case 'R': {
3992411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
40047cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
40147cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4022411167fSJim Ingham         if (error.Success())
4032411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
404b9c1b51eSKate Stone       } break;
4052411167fSJim Ingham 
406a72b31c7SJim Ingham       case 'O':
407fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
408fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
409a72b31c7SJim Ingham         break;
410a72b31c7SJim Ingham 
411ca36cd16SJim Ingham       case 'p':
412adcd0268SBenjamin Kramer         m_source_text_regexp.assign(std::string(option_arg));
413ca36cd16SJim Ingham         break;
414ca36cd16SJim Ingham 
415ca36cd16SJim Ingham       case 'r':
416adcd0268SBenjamin Kramer         m_func_regexp.assign(std::string(option_arg));
417ca36cd16SJim Ingham         break;
418ca36cd16SJim Ingham 
419ca36cd16SJim Ingham       case 's':
4208f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
421ca36cd16SJim Ingham         break;
422ca36cd16SJim Ingham 
423ca36cd16SJim Ingham       case 'S':
424adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
425ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
426ca36cd16SJim Ingham         break;
427ca36cd16SJim Ingham 
428b9c1b51eSKate Stone       case 'w': {
429ca36cd16SJim Ingham         bool success;
43047cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
431ca36cd16SJim Ingham         if (!success)
432b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
433fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
434fe11483bSZachary Turner               option_arg.str().c_str());
435b9c1b51eSKate Stone       } break;
436ca36cd16SJim Ingham 
43776bb8d67SJim Ingham       case 'X':
438adcd0268SBenjamin Kramer         m_source_regex_func_names.insert(std::string(option_arg));
43976bb8d67SJim Ingham         break;
44076bb8d67SJim Ingham 
441bc0a9a17SJim Ingham       case 'y':
442bc0a9a17SJim Ingham       {
443bc0a9a17SJim Ingham         OptionValueFileColonLine value;
444bc0a9a17SJim Ingham         Status fcl_err = value.SetValueFromString(option_arg);
445bc0a9a17SJim Ingham         if (!fcl_err.Success()) {
446bc0a9a17SJim Ingham           error.SetErrorStringWithFormat(
447bc0a9a17SJim Ingham               "Invalid value for file:line specifier: %s",
448bc0a9a17SJim Ingham               fcl_err.AsCString());
449bc0a9a17SJim Ingham         } else {
450bc0a9a17SJim Ingham           m_filenames.AppendIfUnique(value.GetFileSpec());
451bc0a9a17SJim Ingham           m_line_num = value.GetLineNumber();
452bc0a9a17SJim Ingham           m_column = value.GetColumnNumber();
453bc0a9a17SJim Ingham         }
454bc0a9a17SJim Ingham       } break;
455bc0a9a17SJim Ingham 
45630fdc8d8SChris Lattner       default:
45736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
45830fdc8d8SChris Lattner       }
45930fdc8d8SChris Lattner 
46030fdc8d8SChris Lattner       return error;
46130fdc8d8SChris Lattner     }
4629e85e5a8SEugene Zelenko 
463b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
46487df91b8SJim Ingham       m_filenames.Clear();
46530fdc8d8SChris Lattner       m_line_num = 0;
46630fdc8d8SChris Lattner       m_column = 0;
467fab10e89SJim Ingham       m_func_names.clear();
4681f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
46930fdc8d8SChris Lattner       m_func_regexp.clear();
4701f746071SGreg Clayton       m_source_text_regexp.clear();
47187df91b8SJim Ingham       m_modules.Clear();
4721f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4732411167fSJim Ingham       m_offset_addr = 0;
474fab10e89SJim Ingham       m_catch_bp = false;
475fab10e89SJim Ingham       m_throw_bp = true;
476eb023e75SGreg Clayton       m_hardware = false;
477a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
47823b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
479a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4805e09c8c3SJim Ingham       m_breakpoint_names.clear();
481e732052fSJim Ingham       m_all_files = false;
482a72b31c7SJim Ingham       m_exception_extra_args.Clear();
483055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
48476bb8d67SJim Ingham       m_source_regex_func_names.clear();
4853815e702SJim Ingham       m_current_key.clear();
48630fdc8d8SChris Lattner     }
48730fdc8d8SChris Lattner 
4881f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
48970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
4901f0f5b5bSZachary Turner     }
49130fdc8d8SChris Lattner 
4925a988416SJim Ingham     // Instance variables to hold the values for command options.
493969795f1SJim Ingham 
4945a988416SJim Ingham     std::string m_condition;
4955a988416SJim Ingham     FileSpecList m_filenames;
4969494c510SJonas Devlieghere     uint32_t m_line_num = 0;
4979494c510SJonas Devlieghere     uint32_t m_column = 0;
4985a988416SJim Ingham     std::vector<std::string> m_func_names;
4995e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
5009494c510SJonas Devlieghere     lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5015a988416SJim Ingham     std::string m_func_regexp;
5025a988416SJim Ingham     std::string m_source_text_regexp;
5035a988416SJim Ingham     FileSpecList m_modules;
5049494c510SJonas Devlieghere     lldb::addr_t m_load_addr = 0;
5052411167fSJim Ingham     lldb::addr_t m_offset_addr;
5069494c510SJonas Devlieghere     bool m_catch_bp = false;
5079494c510SJonas Devlieghere     bool m_throw_bp = true;
5089494c510SJonas Devlieghere     bool m_hardware = false; // Request to use hardware breakpoints
5099494c510SJonas Devlieghere     lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
5109494c510SJonas Devlieghere     lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
5119494c510SJonas Devlieghere     LazyBool m_skip_prologue = eLazyBoolCalculate;
5129494c510SJonas Devlieghere     bool m_all_files = false;
513a72b31c7SJim Ingham     Args m_exception_extra_args;
5149494c510SJonas Devlieghere     LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
51576bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5163815e702SJim Ingham     std::string m_current_key;
5175a988416SJim Ingham   };
5185a988416SJim Ingham 
5195a988416SJim Ingham protected:
520b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
521cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
52230fdc8d8SChris Lattner 
52330fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
52430fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
52530fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
52630fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
527b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
528b9c1b51eSKate Stone     //   expression)
529b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
530b9c1b51eSKate Stone     //   to source text)
531b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
532b9c1b51eSKate Stone     //   given language.)
53330fdc8d8SChris Lattner 
53430fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
53530fdc8d8SChris Lattner 
536738af7a6SJim Ingham     if (!m_python_class_options.GetName().empty())
5373815e702SJim Ingham       break_type = eSetTypeScripted;
5383815e702SJim Ingham     else if (m_options.m_line_num != 0)
53930fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
54030fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
54130fdc8d8SChris Lattner       break_type = eSetTypeAddress;
542fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
54330fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
54430fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
54530fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
546969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
547969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
548a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
549fab10e89SJim Ingham       break_type = eSetTypeException;
55030fdc8d8SChris Lattner 
551b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
552274060b6SGreg Clayton     FileSpec module_spec;
553a8558b62SJim Ingham     const bool internal = false;
554a8558b62SJim Ingham 
555b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
556b9c1b51eSKate Stone     // that off.
557b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
558b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5592411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5602411167fSJim Ingham 
561b9c1b51eSKate Stone     switch (break_type) {
56230fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
56330fdc8d8SChris Lattner     {
56430fdc8d8SChris Lattner       FileSpec file;
565c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
566b9c1b51eSKate Stone       if (num_files == 0) {
567b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
56887df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
56987df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
57087df91b8SJim Ingham           return false;
57187df91b8SJim Ingham         }
572b9c1b51eSKate Stone       } else if (num_files > 1) {
573b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
574b9c1b51eSKate Stone                            "line breakpoints.");
57587df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
57687df91b8SJim Ingham         return false;
577b9c1b51eSKate Stone       } else
57887df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
57930fdc8d8SChris Lattner 
5801f746071SGreg Clayton       // Only check for inline functions if
5811f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5821f746071SGreg Clayton 
583cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
584cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
585cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
586cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
587b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
588b9c1b51eSKate Stone     } break;
5896eee5aa0SGreg Clayton 
59030fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
591055a08a4SJim Ingham     {
592b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
593b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
594b842f2ecSJim Ingham       //  will track the load location of the library.
595055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
596b9c1b51eSKate Stone       if (num_modules_specified == 1) {
597b9c1b51eSKate Stone         const FileSpec *file_spec =
598b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
599cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
600cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
601b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
602cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
603b842f2ecSJim Ingham                                         m_options.m_hardware);
604b9c1b51eSKate Stone       } else {
605b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
606b9c1b51eSKate Stone                            "address breakpoints.");
607055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
608055a08a4SJim Ingham         return false;
609055a08a4SJim Ingham       }
61030fdc8d8SChris Lattner       break;
611055a08a4SJim Ingham     }
61230fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6130c5cd90dSGreg Clayton     {
614117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6150c5cd90dSGreg Clayton 
6160c5cd90dSGreg Clayton       if (name_type_mask == 0)
617e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6180c5cd90dSGreg Clayton 
619cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
620cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
621cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
622cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
623b842f2ecSJim Ingham           m_options.m_hardware);
624b9c1b51eSKate Stone     } break;
6250c5cd90dSGreg Clayton 
626b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
627b9c1b51eSKate Stone                                  // name
62830fdc8d8SChris Lattner     {
62995eae423SZachary Turner       RegularExpression regexp(m_options.m_func_regexp);
6303af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
631b9c1b51eSKate Stone         result.AppendErrorWithFormat(
632b58af8d2SRaphael Isemann             "Function name regular expression could not be compiled: %s",
6333af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
634aaf68cd9SRaphael Isemann         // Check if the incorrect regex looks like a globbing expression and
635aaf68cd9SRaphael Isemann         // warn the user about it.
636aaf68cd9SRaphael Isemann         if (!m_options.m_func_regexp.empty()) {
637aaf68cd9SRaphael Isemann           if (m_options.m_func_regexp[0] == '*' ||
638aaf68cd9SRaphael Isemann               m_options.m_func_regexp[0] == '?')
639aaf68cd9SRaphael Isemann             result.AppendWarning(
640aaf68cd9SRaphael Isemann                 "Function name regex does not accept glob patterns.");
641aaf68cd9SRaphael Isemann         }
64230fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
643969795f1SJim Ingham         return false;
64430fdc8d8SChris Lattner       }
64587df91b8SJim Ingham 
646cb2380c9SRaphael Isemann       bp_sp = target.CreateFuncRegexBreakpoint(
6475aa1d819SJan Kratochvil           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
648cb2380c9SRaphael Isemann           m_options.m_language, m_options.m_skip_prologue, internal,
649b842f2ecSJim Ingham           m_options.m_hardware);
650a925974bSAdrian Prantl     } break;
651969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
652969795f1SJim Ingham     {
653c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
65487df91b8SJim Ingham 
655b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
656969795f1SJim Ingham         FileSpec file;
657b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
658b9c1b51eSKate Stone           result.AppendError(
659b9c1b51eSKate Stone               "No files provided and could not find default file.");
66087df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
66187df91b8SJim Ingham           return false;
662b9c1b51eSKate Stone         } else {
66387df91b8SJim Ingham           m_options.m_filenames.Append(file);
66487df91b8SJim Ingham         }
66587df91b8SJim Ingham       }
6660c5cd90dSGreg Clayton 
66795eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6683af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
669b9c1b51eSKate Stone         result.AppendErrorWithFormat(
670b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6713af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
672969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
673969795f1SJim Ingham         return false;
674969795f1SJim Ingham       }
675cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
676cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6775aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
678cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
679b9c1b51eSKate Stone     } break;
680b9c1b51eSKate Stone     case eSetTypeException: {
68197206d57SZachary Turner       Status precond_error;
682cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
683cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
684cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
685b842f2ecSJim Ingham           &precond_error);
686b9c1b51eSKate Stone       if (precond_error.Fail()) {
687b9c1b51eSKate Stone         result.AppendErrorWithFormat(
688b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
689a72b31c7SJim Ingham             precond_error.AsCString());
690cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
691a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
692a72b31c7SJim Ingham         return false;
693a72b31c7SJim Ingham       }
694b9c1b51eSKate Stone     } break;
6953815e702SJim Ingham     case eSetTypeScripted: {
6963815e702SJim Ingham 
6973815e702SJim Ingham       Status error;
698cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
699738af7a6SJim Ingham           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
700cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
701943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
7023815e702SJim Ingham       if (error.Fail()) {
7033815e702SJim Ingham         result.AppendErrorWithFormat(
704a925974bSAdrian Prantl             "Error setting extra exception arguments: %s", error.AsCString());
705cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7063815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
7073815e702SJim Ingham         return false;
7083815e702SJim Ingham       }
7093815e702SJim Ingham     } break;
71030fdc8d8SChris Lattner     default:
71130fdc8d8SChris Lattner       break;
71230fdc8d8SChris Lattner     }
71330fdc8d8SChris Lattner 
7141b54c88cSJim Ingham     // Now set the various options that were passed in:
715b842f2ecSJim Ingham     if (bp_sp) {
716*cfb96d84SJim Ingham       bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
717ca36cd16SJim Ingham 
718b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
71997206d57SZachary Turner         Status name_error;
720ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
721cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
722ff9a91eaSJim Ingham           if (name_error.Fail()) {
723ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
724ff9a91eaSJim Ingham                                          name.c_str());
725cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
726ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
727ff9a91eaSJim Ingham             return false;
728ff9a91eaSJim Ingham           }
729ff9a91eaSJim Ingham         }
7305e09c8c3SJim Ingham       }
7311b54c88cSJim Ingham     }
7321b54c88cSJim Ingham 
733b842f2ecSJim Ingham     if (bp_sp) {
73485e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
7351391cc7dSJim Ingham       const bool show_locations = false;
736b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
737b9c1b51eSKate Stone                             show_locations);
738cb2380c9SRaphael Isemann       if (&target == &GetDummyTarget())
739b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
740b9c1b51eSKate Stone                              "into future targets.\n");
741b9c1b51eSKate Stone       else {
74205097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
74305097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
74405097246SAdrian Prantl         // set the breakpoint till we run.
745b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
746b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
747b9c1b51eSKate Stone                                "actual locations.\n");
7484aeb1989SJim Ingham         }
7494aeb1989SJim Ingham       }
75030fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
751b842f2ecSJim Ingham     } else if (!bp_sp) {
75230fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
75330fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
75430fdc8d8SChris Lattner     }
75530fdc8d8SChris Lattner 
75630fdc8d8SChris Lattner     return result.Succeeded();
75730fdc8d8SChris Lattner   }
75830fdc8d8SChris Lattner 
7595a988416SJim Ingham private:
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         result.SetStatus(eReturnStatusFailed);
7715a988416SJim Ingham         return false;
772b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
773b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
774b9c1b51eSKate Stone                            "file, it has no debug info.");
7755a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
7765a988416SJim Ingham         return false;
777b9c1b51eSKate Stone       } else {
778b9c1b51eSKate Stone         const SymbolContext &sc =
779b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
780b9c1b51eSKate Stone         if (sc.line_entry.file) {
7815a988416SJim Ingham           file = sc.line_entry.file;
782b9c1b51eSKate Stone         } else {
783b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
784b9c1b51eSKate Stone                              "use as the default file.");
7855a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
7865a988416SJim Ingham           return false;
7875a988416SJim Ingham         }
7885a988416SJim Ingham       }
7895a988416SJim Ingham     }
7905a988416SJim Ingham     return true;
7915a988416SJim Ingham   }
7925a988416SJim Ingham 
793b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
794b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
795943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
7965a988416SJim Ingham   CommandOptions m_options;
797b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
7985a988416SJim Ingham };
7999e85e5a8SEugene Zelenko 
8005a988416SJim Ingham // CommandObjectBreakpointModify
8015a988416SJim Ingham #pragma mark Modify
8025a988416SJim Ingham 
803b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8045a988416SJim Ingham public:
805b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
806b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
807b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
808b9c1b51eSKate Stone                             "breakpoints in the executable.  "
809b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
810b9c1b51eSKate Stone                             "created breakpoint.  "
811b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
812b9c1b51eSKate Stone                             "empty argument clears the modification.",
8139e85e5a8SEugene Zelenko                             nullptr),
814b9c1b51eSKate Stone         m_options() {
8155a988416SJim Ingham     CommandArgumentEntry arg;
816b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
817b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
818b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
819b9c1b51eSKate Stone     // arguments vector.
8205a988416SJim Ingham     m_arguments.push_back(arg);
821b842f2ecSJim Ingham 
822b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
823b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
824b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
825b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
826b842f2ecSJim Ingham     m_options.Finalize();
8275a988416SJim Ingham   }
8285a988416SJim Ingham 
8299e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8305a988416SJim Ingham 
8310e50b9a4SGongyu Deng   void
8320e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8330e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8340e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
8350e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8360e50b9a4SGongyu Deng         request, nullptr);
8370e50b9a4SGongyu Deng   }
8380e50b9a4SGongyu Deng 
839b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8405a988416SJim Ingham 
8415a988416SJim Ingham protected:
842b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
843cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8445a988416SJim Ingham 
845bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
846cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8475a988416SJim Ingham 
8485a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8495a988416SJim Ingham 
850b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
851cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
852b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8535a988416SJim Ingham 
854b9c1b51eSKate Stone     if (result.Succeeded()) {
8555a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
856b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8575a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8585a988416SJim Ingham 
859b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
860b9c1b51eSKate Stone           Breakpoint *bp =
861cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
862b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
863b9c1b51eSKate Stone             BreakpointLocation *location =
864b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
865b842f2ecSJim Ingham             if (location)
866*cfb96d84SJim Ingham               location->GetLocationOptions().CopyOverSetOptions(
867a925974bSAdrian Prantl                   m_bp_opts.GetBreakpointOptions());
868b9c1b51eSKate Stone           } else {
869*cfb96d84SJim Ingham             bp->GetOptions().CopyOverSetOptions(
870a925974bSAdrian Prantl                 m_bp_opts.GetBreakpointOptions());
8715a988416SJim Ingham           }
8725a988416SJim Ingham         }
8735a988416SJim Ingham       }
8745a988416SJim Ingham     }
8755a988416SJim Ingham 
8765a988416SJim Ingham     return result.Succeeded();
8775a988416SJim Ingham   }
8785a988416SJim Ingham 
8795a988416SJim Ingham private:
880b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
881b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
882b842f2ecSJim Ingham   OptionGroupOptions m_options;
8835a988416SJim Ingham };
8845a988416SJim Ingham 
8855a988416SJim Ingham // CommandObjectBreakpointEnable
8865a988416SJim Ingham #pragma mark Enable
8875a988416SJim Ingham 
888b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8895a988416SJim Ingham public:
890b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
891b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
892b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
893b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
894b9c1b51eSKate Stone                             nullptr) {
8955a988416SJim Ingham     CommandArgumentEntry arg;
896b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
897b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
898b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
899b9c1b51eSKate Stone     // arguments vector.
9005a988416SJim Ingham     m_arguments.push_back(arg);
9015a988416SJim Ingham   }
9025a988416SJim Ingham 
9039e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9045a988416SJim Ingham 
9050e50b9a4SGongyu Deng   void
9060e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
9070e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
9080e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
9090e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9100e50b9a4SGongyu Deng         request, nullptr);
9110e50b9a4SGongyu Deng   }
9120e50b9a4SGongyu Deng 
9135a988416SJim Ingham protected:
914b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
915cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9165a988416SJim Ingham 
917bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
918cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9195a988416SJim Ingham 
920cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9215a988416SJim Ingham 
9225a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9235a988416SJim Ingham 
924b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9255a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9265a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9275a988416SJim Ingham       return false;
9285a988416SJim Ingham     }
9295a988416SJim Ingham 
93011eb9c64SZachary Turner     if (command.empty()) {
9315a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
932cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
933b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
934b9c1b51eSKate Stone                                      " breakpoints)\n",
935b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9365a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
937b9c1b51eSKate Stone     } else {
9385a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9395a988416SJim Ingham       BreakpointIDList valid_bp_ids;
940b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
941cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
942b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9435a988416SJim Ingham 
944b9c1b51eSKate Stone       if (result.Succeeded()) {
9455a988416SJim Ingham         int enable_count = 0;
9465a988416SJim Ingham         int loc_count = 0;
9475a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
948b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9495a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9505a988416SJim Ingham 
951b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
952b9c1b51eSKate Stone             Breakpoint *breakpoint =
953cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
954b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
955b9c1b51eSKate Stone               BreakpointLocation *location =
956b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
957b9c1b51eSKate Stone               if (location) {
9585a988416SJim Ingham                 location->SetEnabled(true);
9595a988416SJim Ingham                 ++loc_count;
9605a988416SJim Ingham               }
961b9c1b51eSKate Stone             } else {
9625a988416SJim Ingham               breakpoint->SetEnabled(true);
9635a988416SJim Ingham               ++enable_count;
9645a988416SJim Ingham             }
9655a988416SJim Ingham           }
9665a988416SJim Ingham         }
967b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
968b9c1b51eSKate Stone                                        enable_count + loc_count);
9695a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9705a988416SJim Ingham       }
9715a988416SJim Ingham     }
9725a988416SJim Ingham 
9735a988416SJim Ingham     return result.Succeeded();
9745a988416SJim Ingham   }
9755a988416SJim Ingham };
9765a988416SJim Ingham 
9775a988416SJim Ingham // CommandObjectBreakpointDisable
9785a988416SJim Ingham #pragma mark Disable
9795a988416SJim Ingham 
980b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9815a988416SJim Ingham public:
9827428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
983b9c1b51eSKate Stone       : CommandObjectParsed(
984b9c1b51eSKate Stone             interpreter, "breakpoint disable",
985b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9867428a18cSKate Stone             "them.  If none are specified, disable all "
9877428a18cSKate Stone             "breakpoints.",
988b9c1b51eSKate Stone             nullptr) {
989b9c1b51eSKate Stone     SetHelpLong(
990b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9917428a18cSKate Stone If none are specified, disable all breakpoints."
9927428a18cSKate Stone         R"(
993ea671fbdSKate Stone 
9947428a18cSKate Stone )"
9957428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
9967428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
9977428a18cSKate Stone         R"(
998ea671fbdSKate Stone 
999ea671fbdSKate Stone     (lldb) break disable 1
1000ea671fbdSKate Stone     (lldb) break enable 1.1
1001ea671fbdSKate Stone 
1002ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1003ea671fbdSKate Stone 
1004ea671fbdSKate Stone     (lldb) break disable 1.*
1005ea671fbdSKate Stone     (lldb) break enable 1.1
1006ea671fbdSKate Stone 
10077428a18cSKate Stone )"
10087428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10097428a18cSKate Stone the second re-enables the first location.");
1010b0fac509SJim Ingham 
10115a988416SJim Ingham     CommandArgumentEntry arg;
1012b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1013b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1014b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1015b9c1b51eSKate Stone     // arguments vector.
10165a988416SJim Ingham     m_arguments.push_back(arg);
10175a988416SJim Ingham   }
10185a988416SJim Ingham 
10199e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10205a988416SJim Ingham 
10210e50b9a4SGongyu Deng   void
10220e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
10230e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
10240e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
10250e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10260e50b9a4SGongyu Deng         request, nullptr);
10270e50b9a4SGongyu Deng   }
10280e50b9a4SGongyu Deng 
10295a988416SJim Ingham protected:
1030b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1031cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1032bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1033cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10345a988416SJim Ingham 
1035cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10365a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10375a988416SJim Ingham 
1038b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10395a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10405a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10415a988416SJim Ingham       return false;
10425a988416SJim Ingham     }
10435a988416SJim Ingham 
104411eb9c64SZachary Turner     if (command.empty()) {
10455a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1046cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1047b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1048b9c1b51eSKate Stone                                      " breakpoints)\n",
1049b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10505a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1051b9c1b51eSKate Stone     } else {
10525a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10535a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10545a988416SJim Ingham 
1055b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1056cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1057b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10585a988416SJim Ingham 
1059b9c1b51eSKate Stone       if (result.Succeeded()) {
10605a988416SJim Ingham         int disable_count = 0;
10615a988416SJim Ingham         int loc_count = 0;
10625a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1063b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10645a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10655a988416SJim Ingham 
1066b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1067b9c1b51eSKate Stone             Breakpoint *breakpoint =
1068cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1069b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1070b9c1b51eSKate Stone               BreakpointLocation *location =
1071b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1072b9c1b51eSKate Stone               if (location) {
10735a988416SJim Ingham                 location->SetEnabled(false);
10745a988416SJim Ingham                 ++loc_count;
10755a988416SJim Ingham               }
1076b9c1b51eSKate Stone             } else {
10775a988416SJim Ingham               breakpoint->SetEnabled(false);
10785a988416SJim Ingham               ++disable_count;
10795a988416SJim Ingham             }
10805a988416SJim Ingham           }
10815a988416SJim Ingham         }
1082b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1083b9c1b51eSKate Stone                                        disable_count + loc_count);
10845a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10855a988416SJim Ingham       }
10865a988416SJim Ingham     }
10875a988416SJim Ingham 
10885a988416SJim Ingham     return result.Succeeded();
10895a988416SJim Ingham   }
10905a988416SJim Ingham };
10915a988416SJim Ingham 
10925a988416SJim Ingham // CommandObjectBreakpointList
10931f0f5b5bSZachary Turner 
10941f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10956f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1096c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10971f0f5b5bSZachary Turner 
10985a988416SJim Ingham #pragma mark List
10995a988416SJim Ingham 
1100b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
11015a988416SJim Ingham public:
1102b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1103b9c1b51eSKate Stone       : CommandObjectParsed(
1104b9c1b51eSKate Stone             interpreter, "breakpoint list",
11055a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
11069e85e5a8SEugene Zelenko             nullptr),
1107b9c1b51eSKate Stone         m_options() {
11085a988416SJim Ingham     CommandArgumentEntry arg;
11095a988416SJim Ingham     CommandArgumentData bp_id_arg;
11105a988416SJim Ingham 
11115a988416SJim Ingham     // Define the first (and only) variant of this arg.
11125a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11135a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11145a988416SJim Ingham 
1115b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1116b9c1b51eSKate Stone     // argument entry.
11175a988416SJim Ingham     arg.push_back(bp_id_arg);
11185a988416SJim Ingham 
11195a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11205a988416SJim Ingham     m_arguments.push_back(arg);
11215a988416SJim Ingham   }
11225a988416SJim Ingham 
11239e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11245a988416SJim Ingham 
1125b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11265a988416SJim Ingham 
1127b9c1b51eSKate Stone   class CommandOptions : public Options {
11285a988416SJim Ingham   public:
11299494c510SJonas Devlieghere     CommandOptions() : Options() {}
11305a988416SJim Ingham 
11319e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11325a988416SJim Ingham 
113397206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1134b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
113597206d57SZachary Turner       Status error;
11363bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11375a988416SJim Ingham 
1138b9c1b51eSKate Stone       switch (short_option) {
11395a988416SJim Ingham       case 'b':
11405a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11415a988416SJim Ingham         break;
114233df7cd3SJim Ingham       case 'D':
114333df7cd3SJim Ingham         m_use_dummy = true;
114433df7cd3SJim Ingham         break;
11455a988416SJim Ingham       case 'f':
11465a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11475a988416SJim Ingham         break;
11485a988416SJim Ingham       case 'v':
11495a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11505a988416SJim Ingham         break;
11515a988416SJim Ingham       case 'i':
11525a988416SJim Ingham         m_internal = true;
11535a988416SJim Ingham         break;
11545a988416SJim Ingham       default:
115536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11565a988416SJim Ingham       }
11575a988416SJim Ingham 
11585a988416SJim Ingham       return error;
11595a988416SJim Ingham     }
11605a988416SJim Ingham 
1161b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11625a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11635a988416SJim Ingham       m_internal = false;
116433df7cd3SJim Ingham       m_use_dummy = false;
11655a988416SJim Ingham     }
11665a988416SJim Ingham 
11671f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116870602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11691f0f5b5bSZachary Turner     }
11705a988416SJim Ingham 
11715a988416SJim Ingham     // Instance variables to hold the values for command options.
11725a988416SJim Ingham 
11739494c510SJonas Devlieghere     lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11745a988416SJim Ingham 
11755a988416SJim Ingham     bool m_internal;
11769494c510SJonas Devlieghere     bool m_use_dummy = false;
11775a988416SJim Ingham   };
11785a988416SJim Ingham 
11795a988416SJim Ingham protected:
1180b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1181cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11825a988416SJim Ingham 
1183b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1184cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1185bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1186cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11875a988416SJim Ingham 
11885a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11895a988416SJim Ingham 
1190b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11915a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11925a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11935a988416SJim Ingham       return true;
11945a988416SJim Ingham     }
11955a988416SJim Ingham 
11965a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
11975a988416SJim Ingham 
119811eb9c64SZachary Turner     if (command.empty()) {
11995a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
12005a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1201b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
12025a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1203b842f2ecSJim Ingham         if (breakpoint->AllowList())
1204b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1205b842f2ecSJim Ingham                                    m_options.m_level);
12065a988416SJim Ingham       }
12075a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1208b9c1b51eSKate Stone     } else {
12095a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12105a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1211b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1212cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1213b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12145a988416SJim Ingham 
1215b9c1b51eSKate Stone       if (result.Succeeded()) {
1216b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12175a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1218b9c1b51eSKate Stone           Breakpoint *breakpoint =
1219cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1220b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1221b9c1b51eSKate Stone                                    m_options.m_level);
12225a988416SJim Ingham         }
12235a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1224b9c1b51eSKate Stone       } else {
12257428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12265a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
12275a988416SJim Ingham       }
12285a988416SJim Ingham     }
12295a988416SJim Ingham 
12305a988416SJim Ingham     return result.Succeeded();
12315a988416SJim Ingham   }
12325a988416SJim Ingham 
12335a988416SJim Ingham private:
12345a988416SJim Ingham   CommandOptions m_options;
12355a988416SJim Ingham };
12365a988416SJim Ingham 
12375a988416SJim Ingham // CommandObjectBreakpointClear
12381f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12391f0f5b5bSZachary Turner 
1240f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1241f94668e3SRaphael Isemann #include "CommandOptions.inc"
12421f0f5b5bSZachary Turner 
12435a988416SJim Ingham #pragma mark Clear
12445a988416SJim Ingham 
1245b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12465a988416SJim Ingham public:
1247efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12485a988416SJim Ingham 
12497428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12507428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1251b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1252b9c1b51eSKate Stone                             "specified source file and line.",
12535a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1254b9c1b51eSKate Stone         m_options() {}
12555a988416SJim Ingham 
12569e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12575a988416SJim Ingham 
1258b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12595a988416SJim Ingham 
1260b9c1b51eSKate Stone   class CommandOptions : public Options {
12615a988416SJim Ingham   public:
12629494c510SJonas Devlieghere     CommandOptions() : Options(), m_filename() {}
12635a988416SJim Ingham 
12649e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12655a988416SJim Ingham 
126697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1267b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
126897206d57SZachary Turner       Status error;
12693bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12705a988416SJim Ingham 
1271b9c1b51eSKate Stone       switch (short_option) {
12725a988416SJim Ingham       case 'f':
1273adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
12745a988416SJim Ingham         break;
12755a988416SJim Ingham 
12765a988416SJim Ingham       case 'l':
1277fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12785a988416SJim Ingham         break;
12795a988416SJim Ingham 
12805a988416SJim Ingham       default:
128136162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12825a988416SJim Ingham       }
12835a988416SJim Ingham 
12845a988416SJim Ingham       return error;
12855a988416SJim Ingham     }
12865a988416SJim Ingham 
1287b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12885a988416SJim Ingham       m_filename.clear();
12895a988416SJim Ingham       m_line_num = 0;
12905a988416SJim Ingham     }
12915a988416SJim Ingham 
12921f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
129370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12941f0f5b5bSZachary Turner     }
12955a988416SJim Ingham 
12965a988416SJim Ingham     // Instance variables to hold the values for command options.
12975a988416SJim Ingham 
12985a988416SJim Ingham     std::string m_filename;
12999494c510SJonas Devlieghere     uint32_t m_line_num = 0;
13005a988416SJim Ingham   };
13015a988416SJim Ingham 
13025a988416SJim Ingham protected:
1303b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1304cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
13055a988416SJim Ingham 
130605097246SAdrian Prantl     // The following are the various types of breakpoints that could be
130705097246SAdrian Prantl     // cleared:
13085a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13095a988416SJim Ingham 
13105a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13115a988416SJim Ingham 
13125a988416SJim Ingham     if (m_options.m_line_num != 0)
13135a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13145a988416SJim Ingham 
1315bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1316cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13175a988416SJim Ingham 
1318cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13195a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13205a988416SJim Ingham 
13215a988416SJim Ingham     // Early return if there's no breakpoint at all.
1322b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13235a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13245a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13255a988416SJim Ingham       return result.Succeeded();
13265a988416SJim Ingham     }
13275a988416SJim Ingham 
13285a988416SJim Ingham     // Find matching breakpoints and delete them.
13295a988416SJim Ingham 
13305a988416SJim Ingham     // First create a copy of all the IDs.
13315a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13325a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13339e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13345a988416SJim Ingham 
13355a988416SJim Ingham     int num_cleared = 0;
13365a988416SJim Ingham     StreamString ss;
1337b9c1b51eSKate Stone     switch (break_type) {
13385a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13395a988416SJim Ingham     {
13405a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13415a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13425a988416SJim Ingham 
1343b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13445a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13455a988416SJim Ingham 
1346b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1347b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1348b9c1b51eSKate Stone           // remove the breakpoint.
1349b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13505a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13515a988416SJim Ingham             ss.EOL();
1352cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13535a988416SJim Ingham             ++num_cleared;
13545a988416SJim Ingham           }
13555a988416SJim Ingham         }
13565a988416SJim Ingham       }
1357b9c1b51eSKate Stone     } break;
13585a988416SJim Ingham 
13595a988416SJim Ingham     default:
13605a988416SJim Ingham       break;
13615a988416SJim Ingham     }
13625a988416SJim Ingham 
1363b9c1b51eSKate Stone     if (num_cleared > 0) {
13645a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13655a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1366c156427dSZachary Turner       output_stream << ss.GetString();
13675a988416SJim Ingham       output_stream.EOL();
13685a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1369b9c1b51eSKate Stone     } else {
13705a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13715a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13725a988416SJim Ingham     }
13735a988416SJim Ingham 
13745a988416SJim Ingham     return result.Succeeded();
13755a988416SJim Ingham   }
13765a988416SJim Ingham 
13775a988416SJim Ingham private:
13785a988416SJim Ingham   CommandOptions m_options;
13795a988416SJim Ingham };
13805a988416SJim Ingham 
13815a988416SJim Ingham // CommandObjectBreakpointDelete
1382f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1383f94668e3SRaphael Isemann #include "CommandOptions.inc"
13841f0f5b5bSZachary Turner 
13855a988416SJim Ingham #pragma mark Delete
13865a988416SJim Ingham 
1387b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13885a988416SJim Ingham public:
1389b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1390b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1391b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1392b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
13939e85e5a8SEugene Zelenko                             nullptr),
1394b9c1b51eSKate Stone         m_options() {
13955a988416SJim Ingham     CommandArgumentEntry arg;
1396b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1397b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1398b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1399b9c1b51eSKate Stone     // arguments vector.
14005a988416SJim Ingham     m_arguments.push_back(arg);
14015a988416SJim Ingham   }
14025a988416SJim Ingham 
14039e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
14045a988416SJim Ingham 
14050e50b9a4SGongyu Deng   void
14060e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
14070e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
14080e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
14090e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
14100e50b9a4SGongyu Deng         request, nullptr);
14110e50b9a4SGongyu Deng   }
14120e50b9a4SGongyu Deng 
1413b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
141433df7cd3SJim Ingham 
1415b9c1b51eSKate Stone   class CommandOptions : public Options {
141633df7cd3SJim Ingham   public:
14179494c510SJonas Devlieghere     CommandOptions() : Options() {}
141833df7cd3SJim Ingham 
14199e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
142033df7cd3SJim Ingham 
142197206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1422b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
142397206d57SZachary Turner       Status error;
142433df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
142533df7cd3SJim Ingham 
1426b9c1b51eSKate Stone       switch (short_option) {
142733df7cd3SJim Ingham       case 'f':
142833df7cd3SJim Ingham         m_force = true;
142933df7cd3SJim Ingham         break;
143033df7cd3SJim Ingham 
143133df7cd3SJim Ingham       case 'D':
143233df7cd3SJim Ingham         m_use_dummy = true;
143333df7cd3SJim Ingham         break;
143433df7cd3SJim Ingham 
14353726ac41SJim Ingham       case 'd':
14363726ac41SJim Ingham         m_delete_disabled = true;
14373726ac41SJim Ingham         break;
14383726ac41SJim Ingham 
143933df7cd3SJim Ingham       default:
144036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
144133df7cd3SJim Ingham       }
144233df7cd3SJim Ingham 
144333df7cd3SJim Ingham       return error;
144433df7cd3SJim Ingham     }
144533df7cd3SJim Ingham 
1446b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
144733df7cd3SJim Ingham       m_use_dummy = false;
144833df7cd3SJim Ingham       m_force = false;
14493726ac41SJim Ingham       m_delete_disabled = false;
145033df7cd3SJim Ingham     }
145133df7cd3SJim Ingham 
14521f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
145370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14541f0f5b5bSZachary Turner     }
145533df7cd3SJim Ingham 
145633df7cd3SJim Ingham     // Instance variables to hold the values for command options.
14579494c510SJonas Devlieghere     bool m_use_dummy = false;
14589494c510SJonas Devlieghere     bool m_force = false;
14599494c510SJonas Devlieghere     bool m_delete_disabled = false;
146033df7cd3SJim Ingham   };
146133df7cd3SJim Ingham 
14625a988416SJim Ingham protected:
1463b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1464cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14653726ac41SJim Ingham     result.Clear();
14665a988416SJim Ingham 
1467bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1468cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14695a988416SJim Ingham 
14703726ac41SJim Ingham     BreakpointList &breakpoints = target.GetBreakpointList();
14715a988416SJim Ingham 
14725a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14735a988416SJim Ingham 
1474b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14755a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14765a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14775a988416SJim Ingham       return false;
14785a988416SJim Ingham     }
14795a988416SJim Ingham 
14803726ac41SJim Ingham     if (command.empty() && !m_options.m_delete_disabled) {
1481b9c1b51eSKate Stone       if (!m_options.m_force &&
1482b9c1b51eSKate Stone           !m_interpreter.Confirm(
1483b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1484b9c1b51eSKate Stone               true)) {
14855a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1486b9c1b51eSKate Stone       } else {
1487cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1488b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1489b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1490b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14915a988416SJim Ingham       }
14925a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1493b9c1b51eSKate Stone     } else {
14945a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
14955a988416SJim Ingham       BreakpointIDList valid_bp_ids;
14963726ac41SJim Ingham 
14973726ac41SJim Ingham       if (m_options.m_delete_disabled) {
14983726ac41SJim Ingham         BreakpointIDList excluded_bp_ids;
14993726ac41SJim Ingham 
15003726ac41SJim Ingham         if (!command.empty()) {
15013726ac41SJim Ingham           CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
15023726ac41SJim Ingham               command, &target, result, &excluded_bp_ids,
15033726ac41SJim Ingham               BreakpointName::Permissions::PermissionKinds::deletePerm);
15043726ac41SJim Ingham         }
15053726ac41SJim Ingham         for (auto breakpoint_sp : breakpoints.Breakpoints()) {
15063726ac41SJim Ingham           if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
15073726ac41SJim Ingham             BreakpointID bp_id(breakpoint_sp->GetID());
15083726ac41SJim Ingham             size_t pos = 0;
15093726ac41SJim Ingham             if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
15103726ac41SJim Ingham               valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
15113726ac41SJim Ingham           }
15123726ac41SJim Ingham         }
15133726ac41SJim Ingham         if (valid_bp_ids.GetSize() == 0) {
15143726ac41SJim Ingham           result.AppendError("No disabled breakpoints.");
15153726ac41SJim Ingham           result.SetStatus(eReturnStatusFailed);
15163726ac41SJim Ingham           return false;
15173726ac41SJim Ingham         }
15183726ac41SJim Ingham       } else {
1519b9c1b51eSKate Stone         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1520cb2380c9SRaphael Isemann             command, &target, result, &valid_bp_ids,
1521b842f2ecSJim Ingham             BreakpointName::Permissions::PermissionKinds::deletePerm);
15223726ac41SJim Ingham       }
15235a988416SJim Ingham 
1524b9c1b51eSKate Stone       if (result.Succeeded()) {
15255a988416SJim Ingham         int delete_count = 0;
15265a988416SJim Ingham         int disable_count = 0;
15275a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1528b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
15295a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15305a988416SJim Ingham 
1531b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1532b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1533b9c1b51eSKate Stone               Breakpoint *breakpoint =
1534cb2380c9SRaphael Isemann                   target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1535b9c1b51eSKate Stone               BreakpointLocation *location =
1536b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1537b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1538b9c1b51eSKate Stone               // disable them instead.
1539b9c1b51eSKate Stone               if (location) {
15405a988416SJim Ingham                 location->SetEnabled(false);
15415a988416SJim Ingham                 ++disable_count;
15425a988416SJim Ingham               }
1543b9c1b51eSKate Stone             } else {
1544cb2380c9SRaphael Isemann               target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15455a988416SJim Ingham               ++delete_count;
15465a988416SJim Ingham             }
15475a988416SJim Ingham           }
15485a988416SJim Ingham         }
1549b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1550b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15515a988416SJim Ingham             delete_count, disable_count);
15525a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
15535a988416SJim Ingham       }
15545a988416SJim Ingham     }
15555a988416SJim Ingham     return result.Succeeded();
15565a988416SJim Ingham   }
15579e85e5a8SEugene Zelenko 
155833df7cd3SJim Ingham private:
155933df7cd3SJim Ingham   CommandOptions m_options;
156033df7cd3SJim Ingham };
156133df7cd3SJim Ingham 
15625e09c8c3SJim Ingham // CommandObjectBreakpointName
1563f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1564f94668e3SRaphael Isemann #include "CommandOptions.inc"
1565bd68a052SRaphael Isemann 
1566b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15675e09c8c3SJim Ingham public:
1568b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1569b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
15705e09c8c3SJim Ingham   }
15715e09c8c3SJim Ingham 
15729e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15735e09c8c3SJim Ingham 
15741f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
157570602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15765e09c8c3SJim Ingham   }
15775e09c8c3SJim Ingham 
157897206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1579b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
158097206d57SZachary Turner     Status error;
15815e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15825e09c8c3SJim Ingham 
1583b9c1b51eSKate Stone     switch (short_option) {
15845e09c8c3SJim Ingham     case 'N':
1585fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1586b9c1b51eSKate Stone           error.Success())
1587fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15885e09c8c3SJim Ingham       break;
15895e09c8c3SJim Ingham     case 'B':
1590fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1591b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15928cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1593fe11483bSZachary Turner             option_arg.str().c_str());
15945e09c8c3SJim Ingham       break;
15955e09c8c3SJim Ingham     case 'D':
1596fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1597b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15988cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1599fe11483bSZachary Turner             option_arg.str().c_str());
16005e09c8c3SJim Ingham       break;
1601e9632ebaSJim Ingham     case 'H':
1602e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1603e9632ebaSJim Ingham       break;
16045e09c8c3SJim Ingham 
16055e09c8c3SJim Ingham     default:
160636162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
16075e09c8c3SJim Ingham     }
16085e09c8c3SJim Ingham     return error;
16095e09c8c3SJim Ingham   }
16105e09c8c3SJim Ingham 
1611b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
16125e09c8c3SJim Ingham     m_name.Clear();
16135e09c8c3SJim Ingham     m_breakpoint.Clear();
16145e09c8c3SJim Ingham     m_use_dummy.Clear();
16155e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1616e9632ebaSJim Ingham     m_help_string.Clear();
16175e09c8c3SJim Ingham   }
16185e09c8c3SJim Ingham 
16195e09c8c3SJim Ingham   OptionValueString m_name;
16205e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
16215e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1622e9632ebaSJim Ingham   OptionValueString m_help_string;
16235e09c8c3SJim Ingham };
16245e09c8c3SJim Ingham 
1625f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1626f94668e3SRaphael Isemann #include "CommandOptions.inc"
1627b842f2ecSJim Ingham 
16288fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1629b842f2ecSJim Ingham public:
16308fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1631b842f2ecSJim Ingham 
1632b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1633b842f2ecSJim Ingham 
1634b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1635b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1636b842f2ecSJim Ingham   }
1637b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1638b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1639b842f2ecSJim Ingham     Status error;
1640a925974bSAdrian Prantl     const int short_option =
1641a925974bSAdrian Prantl         g_breakpoint_access_options[option_idx].short_option;
1642b842f2ecSJim Ingham 
1643b842f2ecSJim Ingham     switch (short_option) {
1644b842f2ecSJim Ingham     case 'L': {
1645b842f2ecSJim Ingham       bool value, success;
164647cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1647b842f2ecSJim Ingham       if (success) {
1648b842f2ecSJim Ingham         m_permissions.SetAllowList(value);
1649b842f2ecSJim Ingham       } else
1650b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1651b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1652b842f2ecSJim Ingham             option_arg.str().c_str());
1653b842f2ecSJim Ingham     } break;
1654b842f2ecSJim Ingham     case 'A': {
1655b842f2ecSJim Ingham       bool value, success;
165647cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1657b842f2ecSJim Ingham       if (success) {
1658b842f2ecSJim Ingham         m_permissions.SetAllowDisable(value);
1659b842f2ecSJim Ingham       } else
1660b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1661b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1662b842f2ecSJim Ingham             option_arg.str().c_str());
1663b842f2ecSJim Ingham     } break;
1664b842f2ecSJim Ingham     case 'D': {
1665b842f2ecSJim Ingham       bool value, success;
166647cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1667b842f2ecSJim Ingham       if (success) {
1668b842f2ecSJim Ingham         m_permissions.SetAllowDelete(value);
1669b842f2ecSJim Ingham       } else
1670b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1671b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1672b842f2ecSJim Ingham             option_arg.str().c_str());
1673b842f2ecSJim Ingham     } break;
167436162014SRaphael Isemann     default:
167536162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
1676b842f2ecSJim Ingham     }
1677b842f2ecSJim Ingham 
1678b842f2ecSJim Ingham     return error;
1679b842f2ecSJim Ingham   }
1680b842f2ecSJim Ingham 
1681a925974bSAdrian Prantl   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1682b842f2ecSJim Ingham 
1683a925974bSAdrian Prantl   const BreakpointName::Permissions &GetPermissions() const {
1684b842f2ecSJim Ingham     return m_permissions;
1685b842f2ecSJim Ingham   }
1686b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1687b842f2ecSJim Ingham };
1688b842f2ecSJim Ingham 
1689b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1690b842f2ecSJim Ingham public:
1691b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1692b842f2ecSJim Ingham       : CommandObjectParsed(
1693a925974bSAdrian Prantl             interpreter, "configure",
1694a925974bSAdrian Prantl             "Configure the options for the breakpoint"
1695b842f2ecSJim Ingham             " name provided.  "
1696b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1697b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1698b842f2ecSJim Ingham             "on the name.",
1699b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1700b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1701b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1702b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1703b842f2ecSJim Ingham     // command.
1704b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1705b842f2ecSJim Ingham     CommandArgumentData id_arg;
1706b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1707b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1708b842f2ecSJim Ingham     arg1.push_back(id_arg);
1709b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1710b842f2ecSJim Ingham 
1711a925974bSAdrian Prantl     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1712a925974bSAdrian Prantl     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1713b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1714a925974bSAdrian Prantl     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1715e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1716b842f2ecSJim Ingham     m_option_group.Finalize();
1717b842f2ecSJim Ingham   }
1718b842f2ecSJim Ingham 
1719b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1720b842f2ecSJim Ingham 
1721b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1722b842f2ecSJim Ingham 
1723b842f2ecSJim Ingham protected:
1724b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1725b842f2ecSJim Ingham 
1726b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1727b842f2ecSJim Ingham     if (argc == 0) {
1728b842f2ecSJim Ingham       result.AppendError("No names provided.");
1729b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1730b842f2ecSJim Ingham       return false;
1731b842f2ecSJim Ingham     }
1732b842f2ecSJim Ingham 
1733cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1734b842f2ecSJim Ingham 
1735b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1736cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1737b842f2ecSJim Ingham 
1738b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1739b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1740b842f2ecSJim Ingham       Status error;
1741a925974bSAdrian Prantl       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1742b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1743b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1744b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1745b842f2ecSJim Ingham         return false;
1746b842f2ecSJim Ingham       }
1747b842f2ecSJim Ingham     }
174805097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
174905097246SAdrian Prantl     // check the error:
1750b842f2ecSJim Ingham     BreakpointSP bp_sp;
1751a925974bSAdrian Prantl     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1752b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1753cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1754a925974bSAdrian Prantl       if (!bp_sp) {
1755b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1756b842f2ecSJim Ingham                                       bp_id);
1757b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1758b842f2ecSJim Ingham         return false;
1759b842f2ecSJim Ingham       }
1760b842f2ecSJim Ingham     }
1761b842f2ecSJim Ingham 
1762b842f2ecSJim Ingham     Status error;
1763b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1764b842f2ecSJim Ingham       ConstString name(entry.c_str());
1765cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1766b842f2ecSJim Ingham       if (!bp_name)
1767b842f2ecSJim Ingham         continue;
1768e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1769e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1770e9632ebaSJim Ingham 
1771b842f2ecSJim Ingham       if (bp_sp)
1772*cfb96d84SJim Ingham         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1773b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1774b842f2ecSJim Ingham       else
1775cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1776b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1777b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1778b842f2ecSJim Ingham     }
1779b842f2ecSJim Ingham     return true;
1780b842f2ecSJim Ingham   }
1781b842f2ecSJim Ingham 
1782b842f2ecSJim Ingham private:
1783b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1784b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1785b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1786b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1787b842f2ecSJim Ingham };
1788b842f2ecSJim Ingham 
1789b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17905e09c8c3SJim Ingham public:
1791b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1792b9c1b51eSKate Stone       : CommandObjectParsed(
1793b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
17945e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1795b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1796b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1797b9c1b51eSKate Stone     // command.
17985e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17995e09c8c3SJim Ingham     CommandArgumentData id_arg;
18005e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18015e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18025e09c8c3SJim Ingham     arg1.push_back(id_arg);
18035e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18045e09c8c3SJim Ingham 
18055e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18065e09c8c3SJim Ingham     m_option_group.Finalize();
18075e09c8c3SJim Ingham   }
18085e09c8c3SJim Ingham 
18099e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
18105e09c8c3SJim Ingham 
1811e87362e6SGongyu Deng   void
1812e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1813e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1814e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1815e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1816e87362e6SGongyu Deng         request, nullptr);
1817e87362e6SGongyu Deng   }
1818e87362e6SGongyu Deng 
1819b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18205e09c8c3SJim Ingham 
18215e09c8c3SJim Ingham protected:
1822b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1823b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18245e09c8c3SJim Ingham       result.SetError("No name option provided.");
18255e09c8c3SJim Ingham       return false;
18265e09c8c3SJim Ingham     }
18275e09c8c3SJim Ingham 
1828cb2380c9SRaphael Isemann     Target &target =
1829b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18305e09c8c3SJim Ingham 
1831bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1832cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18335e09c8c3SJim Ingham 
1834cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18355e09c8c3SJim Ingham 
18365e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1837b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18385e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
18395e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
18405e09c8c3SJim Ingham       return false;
18415e09c8c3SJim Ingham     }
18425e09c8c3SJim Ingham 
18435e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18445e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1845b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1846cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1847b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18485e09c8c3SJim Ingham 
1849b9c1b51eSKate Stone     if (result.Succeeded()) {
1850b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18515e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
18525e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
18535e09c8c3SJim Ingham         return false;
18545e09c8c3SJim Ingham       }
18555e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1856b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1857b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1858b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1859b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1860b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1861b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18625e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1863cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18645e09c8c3SJim Ingham       }
18655e09c8c3SJim Ingham     }
18665e09c8c3SJim Ingham 
18675e09c8c3SJim Ingham     return true;
18685e09c8c3SJim Ingham   }
18695e09c8c3SJim Ingham 
18705e09c8c3SJim Ingham private:
18715e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18725e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18735e09c8c3SJim Ingham };
18745e09c8c3SJim Ingham 
1875b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18765e09c8c3SJim Ingham public:
1877b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1878b9c1b51eSKate Stone       : CommandObjectParsed(
1879b9c1b51eSKate Stone             interpreter, "delete",
18805e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
18815e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1882b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1883b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1884b9c1b51eSKate Stone     // command.
18855e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18865e09c8c3SJim Ingham     CommandArgumentData id_arg;
18875e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18885e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18895e09c8c3SJim Ingham     arg1.push_back(id_arg);
18905e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18915e09c8c3SJim Ingham 
18925e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18935e09c8c3SJim Ingham     m_option_group.Finalize();
18945e09c8c3SJim Ingham   }
18955e09c8c3SJim Ingham 
18969e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18975e09c8c3SJim Ingham 
1898e87362e6SGongyu Deng   void
1899e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1900e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1901e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1902e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1903e87362e6SGongyu Deng         request, nullptr);
1904e87362e6SGongyu Deng   }
1905e87362e6SGongyu Deng 
1906b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19075e09c8c3SJim Ingham 
19085e09c8c3SJim Ingham protected:
1909b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1910b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
19115e09c8c3SJim Ingham       result.SetError("No name option provided.");
19125e09c8c3SJim Ingham       return false;
19135e09c8c3SJim Ingham     }
19145e09c8c3SJim Ingham 
1915cb2380c9SRaphael Isemann     Target &target =
1916b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19175e09c8c3SJim Ingham 
1918bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1919cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
19205e09c8c3SJim Ingham 
1921cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
19225e09c8c3SJim Ingham 
19235e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1924b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19255e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
19265e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19275e09c8c3SJim Ingham       return false;
19285e09c8c3SJim Ingham     }
19295e09c8c3SJim Ingham 
19305e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19315e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1932b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1933cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1934b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
19355e09c8c3SJim Ingham 
1936b9c1b51eSKate Stone     if (result.Succeeded()) {
1937b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19385e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
19395e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19405e09c8c3SJim Ingham         return false;
19415e09c8c3SJim Ingham       }
1942b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19435e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1944b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1945b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1946b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19475e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1948cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19495e09c8c3SJim Ingham       }
19505e09c8c3SJim Ingham     }
19515e09c8c3SJim Ingham 
19525e09c8c3SJim Ingham     return true;
19535e09c8c3SJim Ingham   }
19545e09c8c3SJim Ingham 
19555e09c8c3SJim Ingham private:
19565e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19575e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19585e09c8c3SJim Ingham };
19595e09c8c3SJim Ingham 
1960b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19615e09c8c3SJim Ingham public:
1962b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1963b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1964b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1965b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1966b842f2ecSJim Ingham                             "names",
19675e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
1968b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1969b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19705e09c8c3SJim Ingham     m_option_group.Finalize();
19715e09c8c3SJim Ingham   }
19725e09c8c3SJim Ingham 
19739e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19745e09c8c3SJim Ingham 
1975b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19765e09c8c3SJim Ingham 
19775e09c8c3SJim Ingham protected:
1978b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1979cb2380c9SRaphael Isemann     Target &target =
1980b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19815e09c8c3SJim Ingham 
1982b842f2ecSJim Ingham     std::vector<std::string> name_list;
1983b842f2ecSJim Ingham     if (command.empty()) {
1984cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1985b842f2ecSJim Ingham     } else {
1986a925974bSAdrian Prantl       for (const Args::ArgEntry &arg : command) {
1987b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1988b842f2ecSJim Ingham       }
1989b842f2ecSJim Ingham     }
1990b842f2ecSJim Ingham 
1991b842f2ecSJim Ingham     if (name_list.empty()) {
1992b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1993b842f2ecSJim Ingham     } else {
1994b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1995b842f2ecSJim Ingham         const char *name = name_str.c_str();
1996b842f2ecSJim Ingham         // First print out the options for the name:
1997b842f2ecSJim Ingham         Status error;
1998cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1999cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
2000a925974bSAdrian Prantl         if (bp_name) {
2001b842f2ecSJim Ingham           StreamString s;
2002b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
2003a925974bSAdrian Prantl           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
2004b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
2005b842f2ecSJim Ingham           }
2006b842f2ecSJim Ingham 
2007bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
2008cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
20095e09c8c3SJim Ingham 
2010cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
2011b842f2ecSJim Ingham           bool any_set = false;
2012b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2013b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
20145e09c8c3SJim Ingham               StreamString s;
2015b842f2ecSJim Ingham               any_set = true;
20165e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
20175e09c8c3SJim Ingham               s.EOL();
2018c156427dSZachary Turner               result.AppendMessage(s.GetString());
20195e09c8c3SJim Ingham             }
20205e09c8c3SJim Ingham           }
2021b842f2ecSJim Ingham           if (!any_set)
2022b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
2023b9c1b51eSKate Stone         } else {
2024b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
20255e09c8c3SJim Ingham         }
2026b842f2ecSJim Ingham       }
20275e09c8c3SJim Ingham     }
20285e09c8c3SJim Ingham     return true;
20295e09c8c3SJim Ingham   }
20305e09c8c3SJim Ingham 
20315e09c8c3SJim Ingham private:
20325e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20335e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20345e09c8c3SJim Ingham };
20355e09c8c3SJim Ingham 
2036e14dc268SJim Ingham // CommandObjectBreakpointName
2037b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20385e09c8c3SJim Ingham public:
20397428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2040b9c1b51eSKate Stone       : CommandObjectMultiword(
2041b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2042b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2043b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2044b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2045b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2046b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2047b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2048b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2049b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2050b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
20515e09c8c3SJim Ingham 
20525e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20535e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20545e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2055b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
20565e09c8c3SJim Ingham   }
20575e09c8c3SJim Ingham 
20589e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20595e09c8c3SJim Ingham };
20605e09c8c3SJim Ingham 
2061e14dc268SJim Ingham // CommandObjectBreakpointRead
20623acdf385SJim Ingham #pragma mark Read::CommandOptions
2063f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2064f94668e3SRaphael Isemann #include "CommandOptions.inc"
20651f0f5b5bSZachary Turner 
20661f0f5b5bSZachary Turner #pragma mark Read
2067e14dc268SJim Ingham 
2068e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2069e14dc268SJim Ingham public:
2070e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2071e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2072e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2073e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2074e14dc268SJim Ingham                             nullptr),
20757c89297cSGongyu Deng         m_options() {}
2076e14dc268SJim Ingham 
2077e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2078e14dc268SJim Ingham 
2079e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2080e14dc268SJim Ingham 
2081e14dc268SJim Ingham   class CommandOptions : public Options {
2082e14dc268SJim Ingham   public:
2083e14dc268SJim Ingham     CommandOptions() : Options() {}
2084e14dc268SJim Ingham 
2085e14dc268SJim Ingham     ~CommandOptions() override = default;
2086e14dc268SJim Ingham 
208797206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2088e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
208997206d57SZachary Turner       Status error;
2090e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2091e14dc268SJim Ingham 
2092e14dc268SJim Ingham       switch (short_option) {
2093e14dc268SJim Ingham       case 'f':
2094adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2095e14dc268SJim Ingham         break;
20963acdf385SJim Ingham       case 'N': {
209797206d57SZachary Turner         Status name_error;
20983acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20993acdf385SJim Ingham                                                   name_error)) {
21003acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21013acdf385SJim Ingham                                          name_error.AsCString());
21023acdf385SJim Ingham         }
2103adcd0268SBenjamin Kramer         m_names.push_back(std::string(option_arg));
21043acdf385SJim Ingham         break;
21053acdf385SJim Ingham       }
2106e14dc268SJim Ingham       default:
210736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2108e14dc268SJim Ingham       }
2109e14dc268SJim Ingham 
2110e14dc268SJim Ingham       return error;
2111e14dc268SJim Ingham     }
2112e14dc268SJim Ingham 
2113e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2114e14dc268SJim Ingham       m_filename.clear();
21153acdf385SJim Ingham       m_names.clear();
2116e14dc268SJim Ingham     }
2117e14dc268SJim Ingham 
21181f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
211970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
21201f0f5b5bSZachary Turner     }
2121e14dc268SJim Ingham 
212222e63cbaSGongyu Deng     void HandleOptionArgumentCompletion(
212322e63cbaSGongyu Deng         CompletionRequest &request, OptionElementVector &opt_element_vector,
212422e63cbaSGongyu Deng         int opt_element_index, CommandInterpreter &interpreter) override {
212522e63cbaSGongyu Deng       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
212622e63cbaSGongyu Deng       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
212722e63cbaSGongyu Deng 
212822e63cbaSGongyu Deng       switch (GetDefinitions()[opt_defs_index].short_option) {
212922e63cbaSGongyu Deng       case 'f':
213022e63cbaSGongyu Deng         CommandCompletions::InvokeCommonCompletionCallbacks(
213122e63cbaSGongyu Deng             interpreter, CommandCompletions::eDiskFileCompletion, request,
213222e63cbaSGongyu Deng             nullptr);
213322e63cbaSGongyu Deng         break;
213422e63cbaSGongyu Deng 
213522e63cbaSGongyu Deng       case 'N':
213622e63cbaSGongyu Deng         llvm::Optional<FileSpec> file_spec;
213722e63cbaSGongyu Deng         const llvm::StringRef dash_f("-f");
213822e63cbaSGongyu Deng         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
213922e63cbaSGongyu Deng           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
214022e63cbaSGongyu Deng             file_spec.emplace(
214122e63cbaSGongyu Deng                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
214222e63cbaSGongyu Deng             break;
214322e63cbaSGongyu Deng           }
214422e63cbaSGongyu Deng         }
214522e63cbaSGongyu Deng         if (!file_spec)
214622e63cbaSGongyu Deng           return;
214722e63cbaSGongyu Deng 
214822e63cbaSGongyu Deng         FileSystem::Instance().Resolve(*file_spec);
214922e63cbaSGongyu Deng         Status error;
215022e63cbaSGongyu Deng         StructuredData::ObjectSP input_data_sp =
215122e63cbaSGongyu Deng             StructuredData::ParseJSONFromFile(*file_spec, error);
215222e63cbaSGongyu Deng         if (!error.Success())
215322e63cbaSGongyu Deng           return;
215422e63cbaSGongyu Deng 
215522e63cbaSGongyu Deng         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
215622e63cbaSGongyu Deng         if (!bkpt_array)
215722e63cbaSGongyu Deng           return;
215822e63cbaSGongyu Deng 
215922e63cbaSGongyu Deng         const size_t num_bkpts = bkpt_array->GetSize();
216022e63cbaSGongyu Deng         for (size_t i = 0; i < num_bkpts; i++) {
216122e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_object_sp =
216222e63cbaSGongyu Deng               bkpt_array->GetItemAtIndex(i);
216322e63cbaSGongyu Deng           if (!bkpt_object_sp)
216422e63cbaSGongyu Deng             return;
216522e63cbaSGongyu Deng 
216622e63cbaSGongyu Deng           StructuredData::Dictionary *bkpt_dict =
216722e63cbaSGongyu Deng               bkpt_object_sp->GetAsDictionary();
216822e63cbaSGongyu Deng           if (!bkpt_dict)
216922e63cbaSGongyu Deng             return;
217022e63cbaSGongyu Deng 
217122e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_data_sp =
217222e63cbaSGongyu Deng               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
217322e63cbaSGongyu Deng           if (!bkpt_data_sp)
217422e63cbaSGongyu Deng             return;
217522e63cbaSGongyu Deng 
217622e63cbaSGongyu Deng           bkpt_dict = bkpt_data_sp->GetAsDictionary();
217722e63cbaSGongyu Deng           if (!bkpt_dict)
217822e63cbaSGongyu Deng             return;
217922e63cbaSGongyu Deng 
218022e63cbaSGongyu Deng           StructuredData::Array *names_array;
218122e63cbaSGongyu Deng 
218222e63cbaSGongyu Deng           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
218322e63cbaSGongyu Deng             return;
218422e63cbaSGongyu Deng 
218522e63cbaSGongyu Deng           size_t num_names = names_array->GetSize();
218622e63cbaSGongyu Deng 
218722e63cbaSGongyu Deng           for (size_t i = 0; i < num_names; i++) {
218822e63cbaSGongyu Deng             llvm::StringRef name;
218922e63cbaSGongyu Deng             if (names_array->GetItemAtIndexAsString(i, name))
219022e63cbaSGongyu Deng               request.TryCompleteCurrentArg(name);
219122e63cbaSGongyu Deng           }
219222e63cbaSGongyu Deng         }
219322e63cbaSGongyu Deng       }
219422e63cbaSGongyu Deng     }
2195e14dc268SJim Ingham 
2196e14dc268SJim Ingham     std::string m_filename;
21973acdf385SJim Ingham     std::vector<std::string> m_names;
2198e14dc268SJim Ingham   };
2199e14dc268SJim Ingham 
2200e14dc268SJim Ingham protected:
2201e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2202cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2203e14dc268SJim Ingham 
22043acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2205cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
22063acdf385SJim Ingham 
22078f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
22088f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
220901f16664SJim Ingham     BreakpointIDList new_bps;
2210cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2211cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2212e14dc268SJim Ingham 
2213e14dc268SJim Ingham     if (!error.Success()) {
221401f16664SJim Ingham       result.AppendError(error.AsCString());
2215e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
221601f16664SJim Ingham       return false;
2217e14dc268SJim Ingham     }
22183acdf385SJim Ingham 
22193acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
22203acdf385SJim Ingham 
22213acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
22223acdf385SJim Ingham     if (num_breakpoints == 0) {
22233acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
22243acdf385SJim Ingham     } else {
22253acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
22263acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
22273acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
22283acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2229cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
22303acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
22313acdf385SJim Ingham                              .get();
22323acdf385SJim Ingham         if (bp)
22333acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22343acdf385SJim Ingham                              false);
22353acdf385SJim Ingham       }
22363acdf385SJim Ingham     }
2237e14dc268SJim Ingham     return result.Succeeded();
2238e14dc268SJim Ingham   }
2239e14dc268SJim Ingham 
2240e14dc268SJim Ingham private:
2241e14dc268SJim Ingham   CommandOptions m_options;
2242e14dc268SJim Ingham };
2243e14dc268SJim Ingham 
2244e14dc268SJim Ingham // CommandObjectBreakpointWrite
22451f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2246f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2247f94668e3SRaphael Isemann #include "CommandOptions.inc"
22481f0f5b5bSZachary Turner 
22491f0f5b5bSZachary Turner #pragma mark Write
2250e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2251e14dc268SJim Ingham public:
2252e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2253e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2254e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2255e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2256e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2257e14dc268SJim Ingham                             nullptr),
2258e14dc268SJim Ingham         m_options() {
2259e14dc268SJim Ingham     CommandArgumentEntry arg;
2260e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2261e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2262e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2263e14dc268SJim Ingham     // arguments vector.
2264e14dc268SJim Ingham     m_arguments.push_back(arg);
2265e14dc268SJim Ingham   }
2266e14dc268SJim Ingham 
2267e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2268e14dc268SJim Ingham 
2269e87362e6SGongyu Deng   void
2270e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
2271e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
2272e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
2273e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2274e87362e6SGongyu Deng         request, nullptr);
2275e87362e6SGongyu Deng   }
2276e87362e6SGongyu Deng 
2277e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2278e14dc268SJim Ingham 
2279e14dc268SJim Ingham   class CommandOptions : public Options {
2280e14dc268SJim Ingham   public:
2281e14dc268SJim Ingham     CommandOptions() : Options() {}
2282e14dc268SJim Ingham 
2283e14dc268SJim Ingham     ~CommandOptions() override = default;
2284e14dc268SJim Ingham 
228597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2286e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
228797206d57SZachary Turner       Status error;
2288e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2289e14dc268SJim Ingham 
2290e14dc268SJim Ingham       switch (short_option) {
2291e14dc268SJim Ingham       case 'f':
2292adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2293e14dc268SJim Ingham         break;
22942d3628e1SJim Ingham       case 'a':
22952d3628e1SJim Ingham         m_append = true;
22962d3628e1SJim Ingham         break;
2297e14dc268SJim Ingham       default:
229836162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2299e14dc268SJim Ingham       }
2300e14dc268SJim Ingham 
2301e14dc268SJim Ingham       return error;
2302e14dc268SJim Ingham     }
2303e14dc268SJim Ingham 
2304e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2305e14dc268SJim Ingham       m_filename.clear();
23062d3628e1SJim Ingham       m_append = false;
2307e14dc268SJim Ingham     }
2308e14dc268SJim Ingham 
23091f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
231070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
23111f0f5b5bSZachary Turner     }
2312e14dc268SJim Ingham 
2313e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2314e14dc268SJim Ingham 
2315e14dc268SJim Ingham     std::string m_filename;
23162d3628e1SJim Ingham     bool m_append = false;
2317e14dc268SJim Ingham   };
2318e14dc268SJim Ingham 
2319e14dc268SJim Ingham protected:
2320e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2321cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2322e14dc268SJim Ingham 
2323e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2324cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2325e14dc268SJim Ingham 
2326e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
232711eb9c64SZachary Turner     if (!command.empty()) {
2328e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2329cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2330b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2331e14dc268SJim Ingham 
233201f16664SJim Ingham       if (!result.Succeeded()) {
2333e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2334e14dc268SJim Ingham         return false;
2335e14dc268SJim Ingham       }
2336e14dc268SJim Ingham     }
23378f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
23388f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2339cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23408f3be7a3SJonas Devlieghere                                                      m_options.m_append);
234101f16664SJim Ingham     if (!error.Success()) {
234201f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
234301f16664SJim Ingham                                    error.AsCString());
234401f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2345e14dc268SJim Ingham     }
2346e14dc268SJim Ingham     return result.Succeeded();
2347e14dc268SJim Ingham   }
2348e14dc268SJim Ingham 
2349e14dc268SJim Ingham private:
2350e14dc268SJim Ingham   CommandOptions m_options;
2351e14dc268SJim Ingham };
2352e14dc268SJim Ingham 
235330fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2354ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
235530fdc8d8SChris Lattner 
2356b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2357b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2358b9c1b51eSKate Stone     : CommandObjectMultiword(
2359b9c1b51eSKate Stone           interpreter, "breakpoint",
23607428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2361b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2362b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2363b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2364b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2365b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2366b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2367b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2368b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2369b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2370b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2371b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2372b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2373b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2374b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2375b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2376b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2377b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2378b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2379b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2380e14dc268SJim Ingham   CommandObjectSP write_command_object(
2381e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2382e14dc268SJim Ingham   CommandObjectSP read_command_object(
2383e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
238430fdc8d8SChris Lattner 
2385b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
238630fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
238730fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2388b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2389b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2390ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2391b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2392b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
23935e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2394e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2395e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
239630fdc8d8SChris Lattner 
239723f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
239823f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
239923f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
240023f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
240123f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
240223f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
240323f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
240423f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
24055e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2406e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2407e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
240830fdc8d8SChris Lattner }
240930fdc8d8SChris Lattner 
24109e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
241130fdc8d8SChris Lattner 
2412a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2413a925974bSAdrian Prantl     Args &args, Target *target, bool allow_locations,
2414a925974bSAdrian Prantl     CommandReturnObject &result, BreakpointIDList *valid_ids,
2415a925974bSAdrian Prantl     BreakpointName::Permissions ::PermissionKinds purpose) {
241630fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2417b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2418b9c1b51eSKate Stone   //                                  canonical representation
2419b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2420b9c1b51eSKate Stone   //                                  representing a range (in which case there
2421b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2422b9c1b51eSKate Stone   //                                      after of one of the first two types.
24235e09c8c3SJim Ingham   //                                  4). A breakpoint name
2424b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2425b9c1b51eSKate Stone   // one.)
242630fdc8d8SChris Lattner 
242730fdc8d8SChris Lattner   Args temp_args;
242830fdc8d8SChris Lattner 
242911eb9c64SZachary Turner   if (args.empty()) {
2430b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2431b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2432b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
243336f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2434b9c1b51eSKate Stone     } else {
2435b9c1b51eSKate Stone       result.AppendError(
2436b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
243736f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
243836f3b369SJim Ingham     }
243936f3b369SJim Ingham     return;
244036f3b369SJim Ingham   }
244136f3b369SJim Ingham 
2442b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
244305097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
244405097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
244505097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
244605097246SAdrian Prantl   // into TEMP_ARGS.
244730fdc8d8SChris Lattner 
2448b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2449b842f2ecSJim Ingham                                            purpose, result, temp_args);
245030fdc8d8SChris Lattner 
2451b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2452b9c1b51eSKate Stone   // BreakpointIDList:
245330fdc8d8SChris Lattner 
245416662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
245530fdc8d8SChris Lattner 
245605097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
245705097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
245830fdc8d8SChris Lattner 
2459b9c1b51eSKate Stone   if (result.Succeeded()) {
2460b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
246105097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
246205097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
246330fdc8d8SChris Lattner 
2464c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2465b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
246630fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2467b9c1b51eSKate Stone       Breakpoint *breakpoint =
2468b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2469b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2470c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2471b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
247230fdc8d8SChris Lattner           StreamString id_str;
2473b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2474b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2475c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2476b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2477b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
247830fdc8d8SChris Lattner               id_str.GetData());
247930fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
248030fdc8d8SChris Lattner         }
2481b9c1b51eSKate Stone       } else {
2482c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2483b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2484b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
24857428a18cSKate Stone             cur_bp_id.GetBreakpointID());
248630fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
248730fdc8d8SChris Lattner       }
248830fdc8d8SChris Lattner     }
248930fdc8d8SChris Lattner   }
249030fdc8d8SChris Lattner }
2491