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:
52*abb0ed44SKazu Hirata   BreakpointOptionGroup() : 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') {
113f362b05dSJim Ingham         if (option_arg == "current") {
114f362b05dSJim Ingham           if (!execution_context) {
115f362b05dSJim Ingham             error.SetErrorStringWithFormat("No context to determine current "
116f362b05dSJim Ingham                                            "thread");
117f362b05dSJim Ingham           } else {
118f362b05dSJim Ingham             ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
119f362b05dSJim Ingham             if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
120f362b05dSJim Ingham               error.SetErrorStringWithFormat("No currently selected thread");
121f362b05dSJim Ingham             } else {
122f362b05dSJim Ingham               thread_id = ctx_thread_sp->GetID();
123f362b05dSJim Ingham             }
124f362b05dSJim Ingham           }
125f362b05dSJim Ingham         } else if (option_arg.getAsInteger(0, thread_id))
126b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
127b842f2ecSJim Ingham                                          option_arg.str().c_str());
128b842f2ecSJim Ingham       }
129b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
130a925974bSAdrian Prantl     } break;
131b842f2ecSJim Ingham     case 'T':
132b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
133b842f2ecSJim Ingham       break;
134b842f2ecSJim Ingham     case 'q':
135b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
136b842f2ecSJim Ingham       break;
137a925974bSAdrian Prantl     case 'x': {
138b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
139b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
140b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
141b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
142b842f2ecSJim Ingham                                          option_arg.str().c_str());
143b842f2ecSJim Ingham       }
144b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
145a925974bSAdrian Prantl     } break;
146b842f2ecSJim Ingham     default:
14736162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
148b842f2ecSJim Ingham     }
149b842f2ecSJim Ingham 
150b842f2ecSJim Ingham     return error;
151b842f2ecSJim Ingham   }
152b842f2ecSJim Ingham 
153b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
154b842f2ecSJim Ingham     m_bp_opts.Clear();
155b842f2ecSJim Ingham     m_commands.clear();
156b842f2ecSJim Ingham   }
157b842f2ecSJim Ingham 
158b842f2ecSJim Ingham   Status OptionParsingFinished(ExecutionContext *execution_context) override {
159a925974bSAdrian Prantl     if (!m_commands.empty()) {
160a8f3ae7cSJonas Devlieghere       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
161b842f2ecSJim Ingham 
162b842f2ecSJim Ingham       for (std::string &str : m_commands)
163b842f2ecSJim Ingham         cmd_data->user_source.AppendString(str);
164b842f2ecSJim Ingham 
165b842f2ecSJim Ingham       cmd_data->stop_on_error = true;
166b842f2ecSJim Ingham       m_bp_opts.SetCommandDataCallback(cmd_data);
167b842f2ecSJim Ingham     }
168b842f2ecSJim Ingham     return Status();
169b842f2ecSJim Ingham   }
170b842f2ecSJim Ingham 
171a925974bSAdrian Prantl   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
172b842f2ecSJim Ingham 
173b842f2ecSJim Ingham   std::vector<std::string> m_commands;
174b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
175b842f2ecSJim Ingham };
176bd68a052SRaphael Isemann 
177f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
178f94668e3SRaphael Isemann #include "CommandOptions.inc"
179b842f2ecSJim Ingham 
180a925974bSAdrian Prantl class BreakpointDummyOptionGroup : public OptionGroup {
181b842f2ecSJim Ingham public:
182*abb0ed44SKazu Hirata   BreakpointDummyOptionGroup() {}
183b842f2ecSJim Ingham 
184b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
185b842f2ecSJim Ingham 
186b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
187b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
188b842f2ecSJim Ingham   }
189b842f2ecSJim Ingham 
190b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
191b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
192b842f2ecSJim Ingham     Status error;
193a925974bSAdrian Prantl     const int short_option =
194f1539b9dSJim Ingham         g_breakpoint_dummy_options[option_idx].short_option;
195b842f2ecSJim Ingham 
196b842f2ecSJim Ingham     switch (short_option) {
197b842f2ecSJim Ingham     case 'D':
198b842f2ecSJim Ingham       m_use_dummy = true;
199b842f2ecSJim Ingham       break;
200b842f2ecSJim Ingham     default:
20136162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
202b842f2ecSJim Ingham     }
203b842f2ecSJim Ingham 
204b842f2ecSJim Ingham     return error;
205b842f2ecSJim Ingham   }
206b842f2ecSJim Ingham 
207b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
208b842f2ecSJim Ingham     m_use_dummy = false;
209b842f2ecSJim Ingham   }
210b842f2ecSJim Ingham 
211b842f2ecSJim Ingham   bool m_use_dummy;
212b842f2ecSJim Ingham };
213b842f2ecSJim Ingham 
214f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
215f94668e3SRaphael Isemann #include "CommandOptions.inc"
2161f0f5b5bSZachary Turner 
2175a988416SJim Ingham // CommandObjectBreakpointSet
21830fdc8d8SChris Lattner 
219b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2205a988416SJim Ingham public:
221efe8e7e3SFangrui Song   enum BreakpointSetType {
2225a988416SJim Ingham     eSetTypeInvalid,
2235a988416SJim Ingham     eSetTypeFileAndLine,
2245a988416SJim Ingham     eSetTypeAddress,
2255a988416SJim Ingham     eSetTypeFunctionName,
2265a988416SJim Ingham     eSetTypeFunctionRegexp,
2275a988416SJim Ingham     eSetTypeSourceRegexp,
2283815e702SJim Ingham     eSetTypeException,
2293815e702SJim Ingham     eSetTypeScripted,
230efe8e7e3SFangrui Song   };
2315a988416SJim Ingham 
232b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
233b9c1b51eSKate Stone       : CommandObjectParsed(
234b9c1b51eSKate Stone             interpreter, "breakpoint set",
2355a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2365a988416SJim Ingham             "breakpoint set <cmd-options>"),
237*abb0ed44SKazu Hirata         m_python_class_options("scripted breakpoint", true, 'P') {
238b842f2ecSJim Ingham     // We're picking up all the normal options, commands and disable.
239a925974bSAdrian Prantl     m_all_options.Append(&m_python_class_options,
240a925974bSAdrian Prantl                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
241b842f2ecSJim Ingham     m_all_options.Append(&m_bp_opts,
242b842f2ecSJim Ingham                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
243b842f2ecSJim Ingham                          LLDB_OPT_SET_ALL);
244f6a2086dSSam McCall     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
245b842f2ecSJim Ingham     m_all_options.Append(&m_options);
246b842f2ecSJim Ingham     m_all_options.Finalize();
247b842f2ecSJim Ingham   }
2485a988416SJim Ingham 
2499e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2505a988416SJim Ingham 
251b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2525a988416SJim Ingham 
253b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2545a988416SJim Ingham   public:
255*abb0ed44SKazu Hirata     CommandOptions() {}
25630fdc8d8SChris Lattner 
2579e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
25887df91b8SJim Ingham 
25997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
260b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
26197206d57SZachary Turner       Status error;
262a925974bSAdrian Prantl       const int short_option =
263a925974bSAdrian Prantl           g_breakpoint_set_options[option_idx].short_option;
26430fdc8d8SChris Lattner 
265b9c1b51eSKate Stone       switch (short_option) {
266b9c1b51eSKate Stone       case 'a': {
26747cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
268e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
269b9c1b51eSKate Stone       } break;
27030fdc8d8SChris Lattner 
271e732052fSJim Ingham       case 'A':
272e732052fSJim Ingham         m_all_files = true;
273e732052fSJim Ingham         break;
274e732052fSJim Ingham 
275ca36cd16SJim Ingham       case 'b':
276adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
277ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
278ca36cd16SJim Ingham         break;
279ca36cd16SJim Ingham 
2806672a4f5SJonas Devlieghere       case 'u':
281fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
282b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
283fe11483bSZachary Turner                                          option_arg.str().c_str());
28430fdc8d8SChris Lattner         break;
2859e85e5a8SEugene Zelenko 
286b9c1b51eSKate Stone       case 'E': {
287fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
288fab10e89SJim Ingham 
289b9c1b51eSKate Stone         switch (language) {
290fab10e89SJim Ingham         case eLanguageTypeC89:
291fab10e89SJim Ingham         case eLanguageTypeC:
292fab10e89SJim Ingham         case eLanguageTypeC99:
2931d0089faSBruce Mitchener         case eLanguageTypeC11:
294a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
295fab10e89SJim Ingham           break;
296fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
2971d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
2981d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
2992ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
300a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
301fab10e89SJim Ingham           break;
302fab10e89SJim Ingham         case eLanguageTypeObjC:
303a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
304fab10e89SJim Ingham           break;
305fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
306b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
307b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
308fab10e89SJim Ingham           break;
309fab10e89SJim Ingham         case eLanguageTypeUnknown:
310b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
311b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
312fe11483bSZachary Turner               option_arg.str().c_str());
313fab10e89SJim Ingham           break;
314fab10e89SJim Ingham         default:
315b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
316b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
317fe11483bSZachary Turner               option_arg.str().c_str());
318fab10e89SJim Ingham         }
319b9c1b51eSKate Stone       } break;
320ca36cd16SJim Ingham 
321ca36cd16SJim Ingham       case 'f':
3228f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
323fab10e89SJim Ingham         break;
324ca36cd16SJim Ingham 
325ca36cd16SJim Ingham       case 'F':
326adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
327ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
328ca36cd16SJim Ingham         break;
329ca36cd16SJim Ingham 
330b9c1b51eSKate Stone       case 'h': {
331fab10e89SJim Ingham         bool success;
33247cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
333fab10e89SJim Ingham         if (!success)
334b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
335fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
336fe11483bSZachary Turner               option_arg.str().c_str());
337b9c1b51eSKate Stone       } break;
338eb023e75SGreg Clayton 
339eb023e75SGreg Clayton       case 'H':
340eb023e75SGreg Clayton         m_hardware = true;
341eb023e75SGreg Clayton         break;
342eb023e75SGreg Clayton 
343b9c1b51eSKate Stone       case 'K': {
344a8558b62SJim Ingham         bool success;
345a8558b62SJim Ingham         bool value;
34647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
347a8558b62SJim Ingham         if (value)
348a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
349a8558b62SJim Ingham         else
350a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
351a8558b62SJim Ingham 
352a8558b62SJim Ingham         if (!success)
353b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
354b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
355fe11483bSZachary Turner               option_arg.str().c_str());
356b9c1b51eSKate Stone       } break;
357ca36cd16SJim Ingham 
358fe11483bSZachary Turner       case 'l':
359fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
360b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
361fe11483bSZachary Turner                                          option_arg.str().c_str());
362ca36cd16SJim Ingham         break;
363055ad9beSIlia K 
36423b1decbSDawn Perchik       case 'L':
365fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
36623b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
367b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
368fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
369fe11483bSZachary Turner               option_arg.str().c_str());
37023b1decbSDawn Perchik         break;
37123b1decbSDawn Perchik 
372b9c1b51eSKate Stone       case 'm': {
373055ad9beSIlia K         bool success;
374055ad9beSIlia K         bool value;
37547cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
376055ad9beSIlia K         if (value)
377055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
378055ad9beSIlia K         else
379055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
380055ad9beSIlia K 
381055ad9beSIlia K         if (!success)
382b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
383b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
384fe11483bSZachary Turner               option_arg.str().c_str());
385055ad9beSIlia K         break;
386055ad9beSIlia K       }
387055ad9beSIlia K 
388ca36cd16SJim Ingham       case 'M':
389adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
390ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
391ca36cd16SJim Ingham         break;
392ca36cd16SJim Ingham 
393ca36cd16SJim Ingham       case 'n':
394adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
395ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
396ca36cd16SJim Ingham         break;
397ca36cd16SJim Ingham 
3986fa7681bSZachary Turner       case 'N': {
399fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
400adcd0268SBenjamin Kramer           m_breakpoint_names.push_back(std::string(option_arg));
401ff9a91eaSJim Ingham         else
402ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
403fe11483bSZachary Turner                                          option_arg.str().c_str());
4045e09c8c3SJim Ingham         break;
4056fa7681bSZachary Turner       }
4065e09c8c3SJim Ingham 
407b9c1b51eSKate Stone       case 'R': {
4082411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
40947cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
41047cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4112411167fSJim Ingham         if (error.Success())
4122411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
413b9c1b51eSKate Stone       } break;
4142411167fSJim Ingham 
415a72b31c7SJim Ingham       case 'O':
416fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
417fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
418a72b31c7SJim Ingham         break;
419a72b31c7SJim Ingham 
420ca36cd16SJim Ingham       case 'p':
421adcd0268SBenjamin Kramer         m_source_text_regexp.assign(std::string(option_arg));
422ca36cd16SJim Ingham         break;
423ca36cd16SJim Ingham 
424ca36cd16SJim Ingham       case 'r':
425adcd0268SBenjamin Kramer         m_func_regexp.assign(std::string(option_arg));
426ca36cd16SJim Ingham         break;
427ca36cd16SJim Ingham 
428ca36cd16SJim Ingham       case 's':
4298f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
430ca36cd16SJim Ingham         break;
431ca36cd16SJim Ingham 
432ca36cd16SJim Ingham       case 'S':
433adcd0268SBenjamin Kramer         m_func_names.push_back(std::string(option_arg));
434ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
435ca36cd16SJim Ingham         break;
436ca36cd16SJim Ingham 
437b9c1b51eSKate Stone       case 'w': {
438ca36cd16SJim Ingham         bool success;
43947cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
440ca36cd16SJim Ingham         if (!success)
441b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
442fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
443fe11483bSZachary Turner               option_arg.str().c_str());
444b9c1b51eSKate Stone       } break;
445ca36cd16SJim Ingham 
44676bb8d67SJim Ingham       case 'X':
447adcd0268SBenjamin Kramer         m_source_regex_func_names.insert(std::string(option_arg));
44876bb8d67SJim Ingham         break;
44976bb8d67SJim Ingham 
450bc0a9a17SJim Ingham       case 'y':
451bc0a9a17SJim Ingham       {
452bc0a9a17SJim Ingham         OptionValueFileColonLine value;
453bc0a9a17SJim Ingham         Status fcl_err = value.SetValueFromString(option_arg);
454bc0a9a17SJim Ingham         if (!fcl_err.Success()) {
455bc0a9a17SJim Ingham           error.SetErrorStringWithFormat(
456bc0a9a17SJim Ingham               "Invalid value for file:line specifier: %s",
457bc0a9a17SJim Ingham               fcl_err.AsCString());
458bc0a9a17SJim Ingham         } else {
459bc0a9a17SJim Ingham           m_filenames.AppendIfUnique(value.GetFileSpec());
460bc0a9a17SJim Ingham           m_line_num = value.GetLineNumber();
461bc0a9a17SJim Ingham           m_column = value.GetColumnNumber();
462bc0a9a17SJim Ingham         }
463bc0a9a17SJim Ingham       } break;
464bc0a9a17SJim Ingham 
46530fdc8d8SChris Lattner       default:
46636162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
46730fdc8d8SChris Lattner       }
46830fdc8d8SChris Lattner 
46930fdc8d8SChris Lattner       return error;
47030fdc8d8SChris Lattner     }
4719e85e5a8SEugene Zelenko 
472b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
47387df91b8SJim Ingham       m_filenames.Clear();
47430fdc8d8SChris Lattner       m_line_num = 0;
47530fdc8d8SChris Lattner       m_column = 0;
476fab10e89SJim Ingham       m_func_names.clear();
4771f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
47830fdc8d8SChris Lattner       m_func_regexp.clear();
4791f746071SGreg Clayton       m_source_text_regexp.clear();
48087df91b8SJim Ingham       m_modules.Clear();
4811f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
4822411167fSJim Ingham       m_offset_addr = 0;
483fab10e89SJim Ingham       m_catch_bp = false;
484fab10e89SJim Ingham       m_throw_bp = true;
485eb023e75SGreg Clayton       m_hardware = false;
486a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
48723b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
488a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
4895e09c8c3SJim Ingham       m_breakpoint_names.clear();
490e732052fSJim Ingham       m_all_files = false;
491a72b31c7SJim Ingham       m_exception_extra_args.Clear();
492055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
49376bb8d67SJim Ingham       m_source_regex_func_names.clear();
4943815e702SJim Ingham       m_current_key.clear();
49530fdc8d8SChris Lattner     }
49630fdc8d8SChris Lattner 
4971f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
49870602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
4991f0f5b5bSZachary Turner     }
50030fdc8d8SChris Lattner 
5015a988416SJim Ingham     // Instance variables to hold the values for command options.
502969795f1SJim Ingham 
5035a988416SJim Ingham     std::string m_condition;
5045a988416SJim Ingham     FileSpecList m_filenames;
5059494c510SJonas Devlieghere     uint32_t m_line_num = 0;
5069494c510SJonas Devlieghere     uint32_t m_column = 0;
5075a988416SJim Ingham     std::vector<std::string> m_func_names;
5085e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
5099494c510SJonas Devlieghere     lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
5105a988416SJim Ingham     std::string m_func_regexp;
5115a988416SJim Ingham     std::string m_source_text_regexp;
5125a988416SJim Ingham     FileSpecList m_modules;
5139494c510SJonas Devlieghere     lldb::addr_t m_load_addr = 0;
5142411167fSJim Ingham     lldb::addr_t m_offset_addr;
5159494c510SJonas Devlieghere     bool m_catch_bp = false;
5169494c510SJonas Devlieghere     bool m_throw_bp = true;
5179494c510SJonas Devlieghere     bool m_hardware = false; // Request to use hardware breakpoints
5189494c510SJonas Devlieghere     lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
5199494c510SJonas Devlieghere     lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
5209494c510SJonas Devlieghere     LazyBool m_skip_prologue = eLazyBoolCalculate;
5219494c510SJonas Devlieghere     bool m_all_files = false;
522a72b31c7SJim Ingham     Args m_exception_extra_args;
5239494c510SJonas Devlieghere     LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
52476bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5253815e702SJim Ingham     std::string m_current_key;
5265a988416SJim Ingham   };
5275a988416SJim Ingham 
5285a988416SJim Ingham protected:
529b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
530cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
53130fdc8d8SChris Lattner 
53230fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
53330fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
53430fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
53530fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
536b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
537b9c1b51eSKate Stone     //   expression)
538b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
539b9c1b51eSKate Stone     //   to source text)
540b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
541b9c1b51eSKate Stone     //   given language.)
54230fdc8d8SChris Lattner 
54330fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
54430fdc8d8SChris Lattner 
545738af7a6SJim Ingham     if (!m_python_class_options.GetName().empty())
5463815e702SJim Ingham       break_type = eSetTypeScripted;
5473815e702SJim Ingham     else if (m_options.m_line_num != 0)
54830fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
54930fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
55030fdc8d8SChris Lattner       break_type = eSetTypeAddress;
551fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
55230fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
55330fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
55430fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
555969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
556969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
557a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
558fab10e89SJim Ingham       break_type = eSetTypeException;
55930fdc8d8SChris Lattner 
560b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
561274060b6SGreg Clayton     FileSpec module_spec;
562a8558b62SJim Ingham     const bool internal = false;
563a8558b62SJim Ingham 
564b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
565b9c1b51eSKate Stone     // that off.
566b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
567b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
5682411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
5692411167fSJim Ingham 
570b9c1b51eSKate Stone     switch (break_type) {
57130fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
57230fdc8d8SChris Lattner     {
57330fdc8d8SChris Lattner       FileSpec file;
574c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
575b9c1b51eSKate Stone       if (num_files == 0) {
576b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
57787df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
57887df91b8SJim Ingham           return false;
57987df91b8SJim Ingham         }
580b9c1b51eSKate Stone       } else if (num_files > 1) {
581b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
582b9c1b51eSKate Stone                            "line breakpoints.");
58387df91b8SJim Ingham         return false;
584b9c1b51eSKate Stone       } else
58587df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
58630fdc8d8SChris Lattner 
5871f746071SGreg Clayton       // Only check for inline functions if
5881f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
5891f746071SGreg Clayton 
590cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
591cb2380c9SRaphael Isemann           &(m_options.m_modules), file, m_options.m_line_num,
592cb2380c9SRaphael Isemann           m_options.m_column, m_options.m_offset_addr, check_inlines,
593cb2380c9SRaphael Isemann           m_options.m_skip_prologue, internal, m_options.m_hardware,
594b842f2ecSJim Ingham           m_options.m_move_to_nearest_code);
595b9c1b51eSKate Stone     } break;
5966eee5aa0SGreg Clayton 
59730fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
598055a08a4SJim Ingham     {
599b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
600b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
601b842f2ecSJim Ingham       //  will track the load location of the library.
602055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
603b9c1b51eSKate Stone       if (num_modules_specified == 1) {
604b9c1b51eSKate Stone         const FileSpec *file_spec =
605b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
606cb2380c9SRaphael Isemann         bp_sp = target.CreateAddressInModuleBreakpoint(
607cb2380c9SRaphael Isemann             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
608b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
609cb2380c9SRaphael Isemann         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
610b842f2ecSJim Ingham                                         m_options.m_hardware);
611b9c1b51eSKate Stone       } else {
612b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
613b9c1b51eSKate Stone                            "address breakpoints.");
614055a08a4SJim Ingham         return false;
615055a08a4SJim Ingham       }
61630fdc8d8SChris Lattner       break;
617055a08a4SJim Ingham     }
61830fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6190c5cd90dSGreg Clayton     {
620117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6210c5cd90dSGreg Clayton 
6220c5cd90dSGreg Clayton       if (name_type_mask == 0)
623e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6240c5cd90dSGreg Clayton 
625cb2380c9SRaphael Isemann       bp_sp = target.CreateBreakpoint(
626cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
627cb2380c9SRaphael Isemann           m_options.m_func_names, name_type_mask, m_options.m_language,
628cb2380c9SRaphael Isemann           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
629b842f2ecSJim Ingham           m_options.m_hardware);
630b9c1b51eSKate Stone     } break;
6310c5cd90dSGreg Clayton 
632b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
633b9c1b51eSKate Stone                                  // name
63430fdc8d8SChris Lattner     {
63595eae423SZachary Turner       RegularExpression regexp(m_options.m_func_regexp);
6363af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
637b9c1b51eSKate Stone         result.AppendErrorWithFormat(
638b58af8d2SRaphael Isemann             "Function name regular expression could not be compiled: %s",
6393af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
640aaf68cd9SRaphael Isemann         // Check if the incorrect regex looks like a globbing expression and
641aaf68cd9SRaphael Isemann         // warn the user about it.
642aaf68cd9SRaphael Isemann         if (!m_options.m_func_regexp.empty()) {
643aaf68cd9SRaphael Isemann           if (m_options.m_func_regexp[0] == '*' ||
644aaf68cd9SRaphael Isemann               m_options.m_func_regexp[0] == '?')
645aaf68cd9SRaphael Isemann             result.AppendWarning(
646aaf68cd9SRaphael Isemann                 "Function name regex does not accept glob patterns.");
647aaf68cd9SRaphael Isemann         }
648969795f1SJim Ingham         return false;
64930fdc8d8SChris Lattner       }
65087df91b8SJim Ingham 
651cb2380c9SRaphael Isemann       bp_sp = target.CreateFuncRegexBreakpoint(
6525aa1d819SJan Kratochvil           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
653cb2380c9SRaphael Isemann           m_options.m_language, m_options.m_skip_prologue, internal,
654b842f2ecSJim Ingham           m_options.m_hardware);
655a925974bSAdrian Prantl     } break;
656969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
657969795f1SJim Ingham     {
658c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
65987df91b8SJim Ingham 
660b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
661969795f1SJim Ingham         FileSpec file;
662b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
663b9c1b51eSKate Stone           result.AppendError(
664b9c1b51eSKate Stone               "No files provided and could not find default file.");
66587df91b8SJim Ingham           return false;
666b9c1b51eSKate Stone         } else {
66787df91b8SJim Ingham           m_options.m_filenames.Append(file);
66887df91b8SJim Ingham         }
66987df91b8SJim Ingham       }
6700c5cd90dSGreg Clayton 
67195eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
6723af3f1e8SJonas Devlieghere       if (llvm::Error err = regexp.GetError()) {
673b9c1b51eSKate Stone         result.AppendErrorWithFormat(
674b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
6753af3f1e8SJonas Devlieghere             llvm::toString(std::move(err)).c_str());
676969795f1SJim Ingham         return false;
677969795f1SJim Ingham       }
678cb2380c9SRaphael Isemann       bp_sp = target.CreateSourceRegexBreakpoint(
679cb2380c9SRaphael Isemann           &(m_options.m_modules), &(m_options.m_filenames),
6805aa1d819SJan Kratochvil           m_options.m_source_regex_func_names, std::move(regexp), internal,
681cb2380c9SRaphael Isemann           m_options.m_hardware, m_options.m_move_to_nearest_code);
682b9c1b51eSKate Stone     } break;
683b9c1b51eSKate Stone     case eSetTypeException: {
68497206d57SZachary Turner       Status precond_error;
685cb2380c9SRaphael Isemann       bp_sp = target.CreateExceptionBreakpoint(
686cb2380c9SRaphael Isemann           m_options.m_exception_language, m_options.m_catch_bp,
687cb2380c9SRaphael Isemann           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
688b842f2ecSJim Ingham           &precond_error);
689b9c1b51eSKate Stone       if (precond_error.Fail()) {
690b9c1b51eSKate Stone         result.AppendErrorWithFormat(
691b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
692a72b31c7SJim Ingham             precond_error.AsCString());
693cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
694a72b31c7SJim Ingham         return false;
695a72b31c7SJim Ingham       }
696b9c1b51eSKate Stone     } break;
6973815e702SJim Ingham     case eSetTypeScripted: {
6983815e702SJim Ingham 
6993815e702SJim Ingham       Status error;
700cb2380c9SRaphael Isemann       bp_sp = target.CreateScriptedBreakpoint(
701738af7a6SJim Ingham           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
702cb2380c9SRaphael Isemann           &(m_options.m_filenames), false, m_options.m_hardware,
703943a2481SJim Ingham           m_python_class_options.GetStructuredData(), &error);
7043815e702SJim Ingham       if (error.Fail()) {
7053815e702SJim Ingham         result.AppendErrorWithFormat(
706a925974bSAdrian Prantl             "Error setting extra exception arguments: %s", error.AsCString());
707cb2380c9SRaphael Isemann         target.RemoveBreakpointByID(bp_sp->GetID());
7083815e702SJim Ingham         return false;
7093815e702SJim Ingham       }
7103815e702SJim Ingham     } break;
71130fdc8d8SChris Lattner     default:
71230fdc8d8SChris Lattner       break;
71330fdc8d8SChris Lattner     }
71430fdc8d8SChris Lattner 
7151b54c88cSJim Ingham     // Now set the various options that were passed in:
716b842f2ecSJim Ingham     if (bp_sp) {
717cfb96d84SJim Ingham       bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
718ca36cd16SJim Ingham 
719b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
72097206d57SZachary Turner         Status name_error;
721ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
722cb2380c9SRaphael Isemann           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
723ff9a91eaSJim Ingham           if (name_error.Fail()) {
724ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
725ff9a91eaSJim Ingham                                          name.c_str());
726cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp_sp->GetID());
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     }
75430fdc8d8SChris Lattner 
75530fdc8d8SChris Lattner     return result.Succeeded();
75630fdc8d8SChris Lattner   }
75730fdc8d8SChris Lattner 
7585a988416SJim Ingham private:
759cb2380c9SRaphael Isemann   bool GetDefaultFile(Target &target, FileSpec &file,
760b9c1b51eSKate Stone                       CommandReturnObject &result) {
7615a988416SJim Ingham     uint32_t default_line;
76205097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
76305097246SAdrian Prantl     // frame's file.
764cb2380c9SRaphael Isemann     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
765b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
766b9c1b51eSKate Stone       if (cur_frame == nullptr) {
767b9c1b51eSKate Stone         result.AppendError(
768b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
7695a988416SJim Ingham         return false;
770b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
771b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
772b9c1b51eSKate Stone                            "file, it has no debug info.");
7735a988416SJim Ingham         return false;
774b9c1b51eSKate Stone       } else {
775b9c1b51eSKate Stone         const SymbolContext &sc =
776b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
777b9c1b51eSKate Stone         if (sc.line_entry.file) {
7785a988416SJim Ingham           file = sc.line_entry.file;
779b9c1b51eSKate Stone         } else {
780b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
781b9c1b51eSKate Stone                              "use as the default file.");
7825a988416SJim Ingham           return false;
7835a988416SJim Ingham         }
7845a988416SJim Ingham       }
7855a988416SJim Ingham     }
7865a988416SJim Ingham     return true;
7875a988416SJim Ingham   }
7885a988416SJim Ingham 
789b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
790b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
791943a2481SJim Ingham   OptionGroupPythonClassWithDict m_python_class_options;
7925a988416SJim Ingham   CommandOptions m_options;
793b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
7945a988416SJim Ingham };
7959e85e5a8SEugene Zelenko 
7965a988416SJim Ingham // CommandObjectBreakpointModify
7975a988416SJim Ingham #pragma mark Modify
7985a988416SJim Ingham 
799b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8005a988416SJim Ingham public:
801b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
802b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
803b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
804b9c1b51eSKate Stone                             "breakpoints in the executable.  "
805b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
806b9c1b51eSKate Stone                             "created breakpoint.  "
807b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
808b9c1b51eSKate Stone                             "empty argument clears the modification.",
809*abb0ed44SKazu Hirata                             nullptr) {
8105a988416SJim Ingham     CommandArgumentEntry arg;
811b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
812b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
813b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
814b9c1b51eSKate Stone     // arguments vector.
8155a988416SJim Ingham     m_arguments.push_back(arg);
816b842f2ecSJim Ingham 
817b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
818b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
819b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
820b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
821b842f2ecSJim Ingham     m_options.Finalize();
8225a988416SJim Ingham   }
8235a988416SJim Ingham 
8249e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
8255a988416SJim Ingham 
8260e50b9a4SGongyu Deng   void
8270e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
8280e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
8290e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
8300e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
8310e50b9a4SGongyu Deng         request, nullptr);
8320e50b9a4SGongyu Deng   }
8330e50b9a4SGongyu Deng 
834b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
8355a988416SJim Ingham 
8365a988416SJim Ingham protected:
837b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
838cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
8395a988416SJim Ingham 
840bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
841cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
8425a988416SJim Ingham 
8435a988416SJim Ingham     BreakpointIDList valid_bp_ids;
8445a988416SJim Ingham 
845b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
846cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
847b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
8485a988416SJim Ingham 
849b9c1b51eSKate Stone     if (result.Succeeded()) {
8505a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
851b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
8525a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
8535a988416SJim Ingham 
854b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
855b9c1b51eSKate Stone           Breakpoint *bp =
856cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
857b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
858b9c1b51eSKate Stone             BreakpointLocation *location =
859b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
860b842f2ecSJim Ingham             if (location)
861cfb96d84SJim Ingham               location->GetLocationOptions().CopyOverSetOptions(
862a925974bSAdrian Prantl                   m_bp_opts.GetBreakpointOptions());
863b9c1b51eSKate Stone           } else {
864cfb96d84SJim Ingham             bp->GetOptions().CopyOverSetOptions(
865a925974bSAdrian Prantl                 m_bp_opts.GetBreakpointOptions());
8665a988416SJim Ingham           }
8675a988416SJim Ingham         }
8685a988416SJim Ingham       }
8695a988416SJim Ingham     }
8705a988416SJim Ingham 
8715a988416SJim Ingham     return result.Succeeded();
8725a988416SJim Ingham   }
8735a988416SJim Ingham 
8745a988416SJim Ingham private:
875b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
876b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
877b842f2ecSJim Ingham   OptionGroupOptions m_options;
8785a988416SJim Ingham };
8795a988416SJim Ingham 
8805a988416SJim Ingham // CommandObjectBreakpointEnable
8815a988416SJim Ingham #pragma mark Enable
8825a988416SJim Ingham 
883b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
8845a988416SJim Ingham public:
885b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
886b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
887b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
888b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
889b9c1b51eSKate Stone                             nullptr) {
8905a988416SJim Ingham     CommandArgumentEntry arg;
891b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
892b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
893b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
894b9c1b51eSKate Stone     // arguments vector.
8955a988416SJim Ingham     m_arguments.push_back(arg);
8965a988416SJim Ingham   }
8975a988416SJim Ingham 
8989e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
8995a988416SJim Ingham 
9000e50b9a4SGongyu Deng   void
9010e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
9020e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
9030e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
9040e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
9050e50b9a4SGongyu Deng         request, nullptr);
9060e50b9a4SGongyu Deng   }
9070e50b9a4SGongyu Deng 
9085a988416SJim Ingham protected:
909b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
910cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
9115a988416SJim Ingham 
912bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
913cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
9145a988416SJim Ingham 
915cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
9165a988416SJim Ingham 
9175a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9185a988416SJim Ingham 
919b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9205a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9215a988416SJim Ingham       return false;
9225a988416SJim Ingham     }
9235a988416SJim Ingham 
92411eb9c64SZachary Turner     if (command.empty()) {
9255a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
926cb2380c9SRaphael Isemann       target.EnableAllowedBreakpoints();
927b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
928b9c1b51eSKate Stone                                      " breakpoints)\n",
929b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
9305a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
931b9c1b51eSKate Stone     } else {
9325a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
9335a988416SJim Ingham       BreakpointIDList valid_bp_ids;
934b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
935cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
936b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
9375a988416SJim Ingham 
938b9c1b51eSKate Stone       if (result.Succeeded()) {
9395a988416SJim Ingham         int enable_count = 0;
9405a988416SJim Ingham         int loc_count = 0;
9415a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
942b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
9435a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9445a988416SJim Ingham 
945b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
946b9c1b51eSKate Stone             Breakpoint *breakpoint =
947cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
948b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
949b9c1b51eSKate Stone               BreakpointLocation *location =
950b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
951b9c1b51eSKate Stone               if (location) {
9525a988416SJim Ingham                 location->SetEnabled(true);
9535a988416SJim Ingham                 ++loc_count;
9545a988416SJim Ingham               }
955b9c1b51eSKate Stone             } else {
9565a988416SJim Ingham               breakpoint->SetEnabled(true);
9575a988416SJim Ingham               ++enable_count;
9585a988416SJim Ingham             }
9595a988416SJim Ingham           }
9605a988416SJim Ingham         }
961b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
962b9c1b51eSKate Stone                                        enable_count + loc_count);
9635a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
9645a988416SJim Ingham       }
9655a988416SJim Ingham     }
9665a988416SJim Ingham 
9675a988416SJim Ingham     return result.Succeeded();
9685a988416SJim Ingham   }
9695a988416SJim Ingham };
9705a988416SJim Ingham 
9715a988416SJim Ingham // CommandObjectBreakpointDisable
9725a988416SJim Ingham #pragma mark Disable
9735a988416SJim Ingham 
974b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
9755a988416SJim Ingham public:
9767428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
977b9c1b51eSKate Stone       : CommandObjectParsed(
978b9c1b51eSKate Stone             interpreter, "breakpoint disable",
979b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
9807428a18cSKate Stone             "them.  If none are specified, disable all "
9817428a18cSKate Stone             "breakpoints.",
982b9c1b51eSKate Stone             nullptr) {
983b9c1b51eSKate Stone     SetHelpLong(
984b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
9857428a18cSKate Stone If none are specified, disable all breakpoints."
9867428a18cSKate Stone         R"(
987ea671fbdSKate Stone 
9887428a18cSKate Stone )"
9897428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
9907428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
9917428a18cSKate Stone         R"(
992ea671fbdSKate Stone 
993ea671fbdSKate Stone     (lldb) break disable 1
994ea671fbdSKate Stone     (lldb) break enable 1.1
995ea671fbdSKate Stone 
996ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
997ea671fbdSKate Stone 
998ea671fbdSKate Stone     (lldb) break disable 1.*
999ea671fbdSKate Stone     (lldb) break enable 1.1
1000ea671fbdSKate Stone 
10017428a18cSKate Stone )"
10027428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10037428a18cSKate Stone the second re-enables the first location.");
1004b0fac509SJim Ingham 
10055a988416SJim Ingham     CommandArgumentEntry arg;
1006b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1007b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1008b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1009b9c1b51eSKate Stone     // arguments vector.
10105a988416SJim Ingham     m_arguments.push_back(arg);
10115a988416SJim Ingham   }
10125a988416SJim Ingham 
10139e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10145a988416SJim Ingham 
10150e50b9a4SGongyu Deng   void
10160e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
10170e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
10180e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
10190e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
10200e50b9a4SGongyu Deng         request, nullptr);
10210e50b9a4SGongyu Deng   }
10220e50b9a4SGongyu Deng 
10235a988416SJim Ingham protected:
1024b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1025cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
1026bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1027cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
10285a988416SJim Ingham 
1029cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
10305a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10315a988416SJim Ingham 
1032b9c1b51eSKate Stone     if (num_breakpoints == 0) {
10335a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
10345a988416SJim Ingham       return false;
10355a988416SJim Ingham     }
10365a988416SJim Ingham 
103711eb9c64SZachary Turner     if (command.empty()) {
10385a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1039cb2380c9SRaphael Isemann       target.DisableAllowedBreakpoints();
1040b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1041b9c1b51eSKate Stone                                      " breakpoints)\n",
1042b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10435a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1044b9c1b51eSKate Stone     } else {
10455a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
10465a988416SJim Ingham       BreakpointIDList valid_bp_ids;
10475a988416SJim Ingham 
1048b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1049cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1050b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10515a988416SJim Ingham 
1052b9c1b51eSKate Stone       if (result.Succeeded()) {
10535a988416SJim Ingham         int disable_count = 0;
10545a988416SJim Ingham         int loc_count = 0;
10555a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1056b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10575a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10585a988416SJim Ingham 
1059b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1060b9c1b51eSKate Stone             Breakpoint *breakpoint =
1061cb2380c9SRaphael Isemann                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1062b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1063b9c1b51eSKate Stone               BreakpointLocation *location =
1064b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1065b9c1b51eSKate Stone               if (location) {
10665a988416SJim Ingham                 location->SetEnabled(false);
10675a988416SJim Ingham                 ++loc_count;
10685a988416SJim Ingham               }
1069b9c1b51eSKate Stone             } else {
10705a988416SJim Ingham               breakpoint->SetEnabled(false);
10715a988416SJim Ingham               ++disable_count;
10725a988416SJim Ingham             }
10735a988416SJim Ingham           }
10745a988416SJim Ingham         }
1075b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1076b9c1b51eSKate Stone                                        disable_count + loc_count);
10775a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10785a988416SJim Ingham       }
10795a988416SJim Ingham     }
10805a988416SJim Ingham 
10815a988416SJim Ingham     return result.Succeeded();
10825a988416SJim Ingham   }
10835a988416SJim Ingham };
10845a988416SJim Ingham 
10855a988416SJim Ingham // CommandObjectBreakpointList
10861f0f5b5bSZachary Turner 
10871f0f5b5bSZachary Turner #pragma mark List::CommandOptions
10886f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1089c5a2d747SRaphael Isemann #include "CommandOptions.inc"
10901f0f5b5bSZachary Turner 
10915a988416SJim Ingham #pragma mark List
10925a988416SJim Ingham 
1093b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
10945a988416SJim Ingham public:
1095b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1096b9c1b51eSKate Stone       : CommandObjectParsed(
1097b9c1b51eSKate Stone             interpreter, "breakpoint list",
10985a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
1099*abb0ed44SKazu Hirata             nullptr) {
11005a988416SJim Ingham     CommandArgumentEntry arg;
11015a988416SJim Ingham     CommandArgumentData bp_id_arg;
11025a988416SJim Ingham 
11035a988416SJim Ingham     // Define the first (and only) variant of this arg.
11045a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11055a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11065a988416SJim Ingham 
1107b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1108b9c1b51eSKate Stone     // argument entry.
11095a988416SJim Ingham     arg.push_back(bp_id_arg);
11105a988416SJim Ingham 
11115a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11125a988416SJim Ingham     m_arguments.push_back(arg);
11135a988416SJim Ingham   }
11145a988416SJim Ingham 
11159e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11165a988416SJim Ingham 
1117b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11185a988416SJim Ingham 
1119b9c1b51eSKate Stone   class CommandOptions : public Options {
11205a988416SJim Ingham   public:
1121*abb0ed44SKazu Hirata     CommandOptions() {}
11225a988416SJim Ingham 
11239e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11245a988416SJim Ingham 
112597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1126b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
112797206d57SZachary Turner       Status error;
11283bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
11295a988416SJim Ingham 
1130b9c1b51eSKate Stone       switch (short_option) {
11315a988416SJim Ingham       case 'b':
11325a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
11335a988416SJim Ingham         break;
113433df7cd3SJim Ingham       case 'D':
113533df7cd3SJim Ingham         m_use_dummy = true;
113633df7cd3SJim Ingham         break;
11375a988416SJim Ingham       case 'f':
11385a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
11395a988416SJim Ingham         break;
11405a988416SJim Ingham       case 'v':
11415a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
11425a988416SJim Ingham         break;
11435a988416SJim Ingham       case 'i':
11445a988416SJim Ingham         m_internal = true;
11455a988416SJim Ingham         break;
11465a988416SJim Ingham       default:
114736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
11485a988416SJim Ingham       }
11495a988416SJim Ingham 
11505a988416SJim Ingham       return error;
11515a988416SJim Ingham     }
11525a988416SJim Ingham 
1153b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
11545a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
11555a988416SJim Ingham       m_internal = false;
115633df7cd3SJim Ingham       m_use_dummy = false;
11575a988416SJim Ingham     }
11585a988416SJim Ingham 
11591f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
11611f0f5b5bSZachary Turner     }
11625a988416SJim Ingham 
11635a988416SJim Ingham     // Instance variables to hold the values for command options.
11645a988416SJim Ingham 
11659494c510SJonas Devlieghere     lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
11665a988416SJim Ingham 
11675a988416SJim Ingham     bool m_internal;
11689494c510SJonas Devlieghere     bool m_use_dummy = false;
11695a988416SJim Ingham   };
11705a988416SJim Ingham 
11715a988416SJim Ingham protected:
1172b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1173cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
11745a988416SJim Ingham 
1175b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1176cb2380c9SRaphael Isemann         target.GetBreakpointList(m_options.m_internal);
1177bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1178cb2380c9SRaphael Isemann     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
11795a988416SJim Ingham 
11805a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
11815a988416SJim Ingham 
1182b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11835a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
11845a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
11855a988416SJim Ingham       return true;
11865a988416SJim Ingham     }
11875a988416SJim Ingham 
11885a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
11895a988416SJim Ingham 
119011eb9c64SZachary Turner     if (command.empty()) {
11915a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
11925a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1193b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
11945a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1195b842f2ecSJim Ingham         if (breakpoint->AllowList())
1196b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1197b842f2ecSJim Ingham                                    m_options.m_level);
11985a988416SJim Ingham       }
11995a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1200b9c1b51eSKate Stone     } else {
12015a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12025a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1203b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1204cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1205b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12065a988416SJim Ingham 
1207b9c1b51eSKate Stone       if (result.Succeeded()) {
1208b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12095a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1210b9c1b51eSKate Stone           Breakpoint *breakpoint =
1211cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1212b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1213b9c1b51eSKate Stone                                    m_options.m_level);
12145a988416SJim Ingham         }
12155a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1216b9c1b51eSKate Stone       } else {
12177428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
12185a988416SJim Ingham       }
12195a988416SJim Ingham     }
12205a988416SJim Ingham 
12215a988416SJim Ingham     return result.Succeeded();
12225a988416SJim Ingham   }
12235a988416SJim Ingham 
12245a988416SJim Ingham private:
12255a988416SJim Ingham   CommandOptions m_options;
12265a988416SJim Ingham };
12275a988416SJim Ingham 
12285a988416SJim Ingham // CommandObjectBreakpointClear
12291f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
12301f0f5b5bSZachary Turner 
1231f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1232f94668e3SRaphael Isemann #include "CommandOptions.inc"
12331f0f5b5bSZachary Turner 
12345a988416SJim Ingham #pragma mark Clear
12355a988416SJim Ingham 
1236b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
12375a988416SJim Ingham public:
1238efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
12395a988416SJim Ingham 
12407428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
12417428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1242b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1243b9c1b51eSKate Stone                             "specified source file and line.",
1244*abb0ed44SKazu Hirata                             "breakpoint clear <cmd-options>") {}
12455a988416SJim Ingham 
12469e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
12475a988416SJim Ingham 
1248b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12495a988416SJim Ingham 
1250b9c1b51eSKate Stone   class CommandOptions : public Options {
12515a988416SJim Ingham   public:
1252*abb0ed44SKazu Hirata     CommandOptions() {}
12535a988416SJim Ingham 
12549e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
12555a988416SJim Ingham 
125697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1257b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
125897206d57SZachary Turner       Status error;
12593bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12605a988416SJim Ingham 
1261b9c1b51eSKate Stone       switch (short_option) {
12625a988416SJim Ingham       case 'f':
1263adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
12645a988416SJim Ingham         break;
12655a988416SJim Ingham 
12665a988416SJim Ingham       case 'l':
1267fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
12685a988416SJim Ingham         break;
12695a988416SJim Ingham 
12705a988416SJim Ingham       default:
127136162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12725a988416SJim Ingham       }
12735a988416SJim Ingham 
12745a988416SJim Ingham       return error;
12755a988416SJim Ingham     }
12765a988416SJim Ingham 
1277b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12785a988416SJim Ingham       m_filename.clear();
12795a988416SJim Ingham       m_line_num = 0;
12805a988416SJim Ingham     }
12815a988416SJim Ingham 
12821f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
128370602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
12841f0f5b5bSZachary Turner     }
12855a988416SJim Ingham 
12865a988416SJim Ingham     // Instance variables to hold the values for command options.
12875a988416SJim Ingham 
12885a988416SJim Ingham     std::string m_filename;
12899494c510SJonas Devlieghere     uint32_t m_line_num = 0;
12905a988416SJim Ingham   };
12915a988416SJim Ingham 
12925a988416SJim Ingham protected:
1293b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1294cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
12955a988416SJim Ingham 
129605097246SAdrian Prantl     // The following are the various types of breakpoints that could be
129705097246SAdrian Prantl     // cleared:
12985a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
12995a988416SJim Ingham 
13005a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13015a988416SJim Ingham 
13025a988416SJim Ingham     if (m_options.m_line_num != 0)
13035a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13045a988416SJim Ingham 
1305bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1306cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
13075a988416SJim Ingham 
1308cb2380c9SRaphael Isemann     BreakpointList &breakpoints = target.GetBreakpointList();
13095a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
13105a988416SJim Ingham 
13115a988416SJim Ingham     // Early return if there's no breakpoint at all.
1312b9c1b51eSKate Stone     if (num_breakpoints == 0) {
13135a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13145a988416SJim Ingham       return result.Succeeded();
13155a988416SJim Ingham     }
13165a988416SJim Ingham 
13175a988416SJim Ingham     // Find matching breakpoints and delete them.
13185a988416SJim Ingham 
13195a988416SJim Ingham     // First create a copy of all the IDs.
13205a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
13215a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
13229e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
13235a988416SJim Ingham 
13245a988416SJim Ingham     int num_cleared = 0;
13255a988416SJim Ingham     StreamString ss;
1326b9c1b51eSKate Stone     switch (break_type) {
13275a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
13285a988416SJim Ingham     {
13295a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
13305a988416SJim Ingham       BreakpointLocationCollection loc_coll;
13315a988416SJim Ingham 
1332b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
13335a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
13345a988416SJim Ingham 
1335b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1336b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1337b9c1b51eSKate Stone           // remove the breakpoint.
1338b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
13395a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
13405a988416SJim Ingham             ss.EOL();
1341cb2380c9SRaphael Isemann             target.RemoveBreakpointByID(bp->GetID());
13425a988416SJim Ingham             ++num_cleared;
13435a988416SJim Ingham           }
13445a988416SJim Ingham         }
13455a988416SJim Ingham       }
1346b9c1b51eSKate Stone     } break;
13475a988416SJim Ingham 
13485a988416SJim Ingham     default:
13495a988416SJim Ingham       break;
13505a988416SJim Ingham     }
13515a988416SJim Ingham 
1352b9c1b51eSKate Stone     if (num_cleared > 0) {
13535a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
13545a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1355c156427dSZachary Turner       output_stream << ss.GetString();
13565a988416SJim Ingham       output_stream.EOL();
13575a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1358b9c1b51eSKate Stone     } else {
13595a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
13605a988416SJim Ingham     }
13615a988416SJim Ingham 
13625a988416SJim Ingham     return result.Succeeded();
13635a988416SJim Ingham   }
13645a988416SJim Ingham 
13655a988416SJim Ingham private:
13665a988416SJim Ingham   CommandOptions m_options;
13675a988416SJim Ingham };
13685a988416SJim Ingham 
13695a988416SJim Ingham // CommandObjectBreakpointDelete
1370f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1371f94668e3SRaphael Isemann #include "CommandOptions.inc"
13721f0f5b5bSZachary Turner 
13735a988416SJim Ingham #pragma mark Delete
13745a988416SJim Ingham 
1375b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
13765a988416SJim Ingham public:
1377b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1378b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1379b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1380b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
1381*abb0ed44SKazu Hirata                             nullptr) {
13825a988416SJim Ingham     CommandArgumentEntry arg;
1383b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1384b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1385b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1386b9c1b51eSKate Stone     // arguments vector.
13875a988416SJim Ingham     m_arguments.push_back(arg);
13885a988416SJim Ingham   }
13895a988416SJim Ingham 
13909e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
13915a988416SJim Ingham 
13920e50b9a4SGongyu Deng   void
13930e50b9a4SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
13940e50b9a4SGongyu Deng                            OptionElementVector &opt_element_vector) override {
13950e50b9a4SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
13960e50b9a4SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
13970e50b9a4SGongyu Deng         request, nullptr);
13980e50b9a4SGongyu Deng   }
13990e50b9a4SGongyu Deng 
1400b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
140133df7cd3SJim Ingham 
1402b9c1b51eSKate Stone   class CommandOptions : public Options {
140333df7cd3SJim Ingham   public:
1404*abb0ed44SKazu Hirata     CommandOptions() {}
140533df7cd3SJim Ingham 
14069e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
140733df7cd3SJim Ingham 
140897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1409b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
141097206d57SZachary Turner       Status error;
141133df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
141233df7cd3SJim Ingham 
1413b9c1b51eSKate Stone       switch (short_option) {
141433df7cd3SJim Ingham       case 'f':
141533df7cd3SJim Ingham         m_force = true;
141633df7cd3SJim Ingham         break;
141733df7cd3SJim Ingham 
141833df7cd3SJim Ingham       case 'D':
141933df7cd3SJim Ingham         m_use_dummy = true;
142033df7cd3SJim Ingham         break;
142133df7cd3SJim Ingham 
14223726ac41SJim Ingham       case 'd':
14233726ac41SJim Ingham         m_delete_disabled = true;
14243726ac41SJim Ingham         break;
14253726ac41SJim Ingham 
142633df7cd3SJim Ingham       default:
142736162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
142833df7cd3SJim Ingham       }
142933df7cd3SJim Ingham 
143033df7cd3SJim Ingham       return error;
143133df7cd3SJim Ingham     }
143233df7cd3SJim Ingham 
1433b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
143433df7cd3SJim Ingham       m_use_dummy = false;
143533df7cd3SJim Ingham       m_force = false;
14363726ac41SJim Ingham       m_delete_disabled = false;
143733df7cd3SJim Ingham     }
143833df7cd3SJim Ingham 
14391f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
144070602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
14411f0f5b5bSZachary Turner     }
144233df7cd3SJim Ingham 
144333df7cd3SJim Ingham     // Instance variables to hold the values for command options.
14449494c510SJonas Devlieghere     bool m_use_dummy = false;
14459494c510SJonas Devlieghere     bool m_force = false;
14469494c510SJonas Devlieghere     bool m_delete_disabled = false;
144733df7cd3SJim Ingham   };
144833df7cd3SJim Ingham 
14495a988416SJim Ingham protected:
1450b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1451cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
14523726ac41SJim Ingham     result.Clear();
14535a988416SJim Ingham 
1454bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1455cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
14565a988416SJim Ingham 
14573726ac41SJim Ingham     BreakpointList &breakpoints = target.GetBreakpointList();
14585a988416SJim Ingham 
14595a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14605a988416SJim Ingham 
1461b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14625a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
14635a988416SJim Ingham       return false;
14645a988416SJim Ingham     }
14655a988416SJim Ingham 
14660018c712SJim Ingham     // Handle the delete all breakpoints case:
14673726ac41SJim Ingham     if (command.empty() && !m_options.m_delete_disabled) {
1468b9c1b51eSKate Stone       if (!m_options.m_force &&
1469b9c1b51eSKate Stone           !m_interpreter.Confirm(
1470b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1471b9c1b51eSKate Stone               true)) {
14725a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1473b9c1b51eSKate Stone       } else {
1474cb2380c9SRaphael Isemann         target.RemoveAllowedBreakpoints();
1475b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1476b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1477b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
14785a988416SJim Ingham       }
14795a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
14800018c712SJim Ingham       return result.Succeeded();
14810018c712SJim Ingham     }
14820018c712SJim Ingham 
14830018c712SJim Ingham     // Either we have some kind of breakpoint specification(s),
14840018c712SJim Ingham     // or we are handling "break disable --deleted".  Gather the list
14850018c712SJim Ingham     // of breakpoints to delete here, the we'll delete them below.
14865a988416SJim Ingham     BreakpointIDList valid_bp_ids;
14873726ac41SJim Ingham 
14883726ac41SJim Ingham     if (m_options.m_delete_disabled) {
14893726ac41SJim Ingham       BreakpointIDList excluded_bp_ids;
14903726ac41SJim Ingham 
14913726ac41SJim Ingham       if (!command.empty()) {
14923726ac41SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
14933726ac41SJim Ingham             command, &target, result, &excluded_bp_ids,
14943726ac41SJim Ingham             BreakpointName::Permissions::PermissionKinds::deletePerm);
14950018c712SJim Ingham         if (!result.Succeeded())
14960018c712SJim Ingham           return false;
14973726ac41SJim Ingham       }
14980018c712SJim Ingham 
14993726ac41SJim Ingham       for (auto breakpoint_sp : breakpoints.Breakpoints()) {
15003726ac41SJim Ingham         if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
15013726ac41SJim Ingham           BreakpointID bp_id(breakpoint_sp->GetID());
15023726ac41SJim Ingham           size_t pos = 0;
15033726ac41SJim Ingham           if (!excluded_bp_ids.FindBreakpointID(bp_id, &pos))
15043726ac41SJim Ingham             valid_bp_ids.AddBreakpointID(breakpoint_sp->GetID());
15053726ac41SJim Ingham         }
15063726ac41SJim Ingham       }
15073726ac41SJim Ingham       if (valid_bp_ids.GetSize() == 0) {
15083726ac41SJim Ingham         result.AppendError("No disabled breakpoints.");
15093726ac41SJim Ingham         return false;
15103726ac41SJim Ingham       }
15113726ac41SJim Ingham     } else {
1512b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1513cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
1514b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
15150018c712SJim Ingham       if (!result.Succeeded())
15160018c712SJim Ingham         return false;
15173726ac41SJim Ingham     }
15185a988416SJim Ingham 
15195a988416SJim Ingham     int delete_count = 0;
15205a988416SJim Ingham     int disable_count = 0;
15215a988416SJim Ingham     const size_t count = valid_bp_ids.GetSize();
1522b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
15235a988416SJim Ingham       BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15245a988416SJim Ingham 
1525b9c1b51eSKate Stone       if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1526b9c1b51eSKate Stone         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1527b9c1b51eSKate Stone           Breakpoint *breakpoint =
1528cb2380c9SRaphael Isemann               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1529b9c1b51eSKate Stone           BreakpointLocation *location =
1530b9c1b51eSKate Stone               breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1531b9c1b51eSKate Stone           // It makes no sense to try to delete individual locations, so we
1532b9c1b51eSKate Stone           // disable them instead.
1533b9c1b51eSKate Stone           if (location) {
15345a988416SJim Ingham             location->SetEnabled(false);
15355a988416SJim Ingham             ++disable_count;
15365a988416SJim Ingham           }
1537b9c1b51eSKate Stone         } else {
1538cb2380c9SRaphael Isemann           target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15395a988416SJim Ingham           ++delete_count;
15405a988416SJim Ingham         }
15415a988416SJim Ingham       }
15425a988416SJim Ingham     }
1543b9c1b51eSKate Stone     result.AppendMessageWithFormat(
1544b9c1b51eSKate Stone         "%d breakpoints deleted; %d breakpoint locations disabled.\n",
15455a988416SJim Ingham         delete_count, disable_count);
15465a988416SJim Ingham     result.SetStatus(eReturnStatusSuccessFinishNoResult);
15475a988416SJim Ingham     return result.Succeeded();
15485a988416SJim Ingham   }
15499e85e5a8SEugene Zelenko 
155033df7cd3SJim Ingham private:
155133df7cd3SJim Ingham   CommandOptions m_options;
155233df7cd3SJim Ingham };
155333df7cd3SJim Ingham 
15545e09c8c3SJim Ingham // CommandObjectBreakpointName
1555f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1556f94668e3SRaphael Isemann #include "CommandOptions.inc"
1557bd68a052SRaphael Isemann 
1558b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
15595e09c8c3SJim Ingham public:
1560b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1561*abb0ed44SKazu Hirata       : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
15625e09c8c3SJim Ingham 
15639e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
15645e09c8c3SJim Ingham 
15651f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
156670602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
15675e09c8c3SJim Ingham   }
15685e09c8c3SJim Ingham 
156997206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1570b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
157197206d57SZachary Turner     Status error;
15725e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
15735e09c8c3SJim Ingham 
1574b9c1b51eSKate Stone     switch (short_option) {
15755e09c8c3SJim Ingham     case 'N':
1576fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1577b9c1b51eSKate Stone           error.Success())
1578fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
15795e09c8c3SJim Ingham       break;
15805e09c8c3SJim Ingham     case 'B':
1581fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1582b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15838cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1584fe11483bSZachary Turner             option_arg.str().c_str());
15855e09c8c3SJim Ingham       break;
15865e09c8c3SJim Ingham     case 'D':
1587fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1588b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
15898cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1590fe11483bSZachary Turner             option_arg.str().c_str());
15915e09c8c3SJim Ingham       break;
1592e9632ebaSJim Ingham     case 'H':
1593e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1594e9632ebaSJim Ingham       break;
15955e09c8c3SJim Ingham 
15965e09c8c3SJim Ingham     default:
159736162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
15985e09c8c3SJim Ingham     }
15995e09c8c3SJim Ingham     return error;
16005e09c8c3SJim Ingham   }
16015e09c8c3SJim Ingham 
1602b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
16035e09c8c3SJim Ingham     m_name.Clear();
16045e09c8c3SJim Ingham     m_breakpoint.Clear();
16055e09c8c3SJim Ingham     m_use_dummy.Clear();
16065e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1607e9632ebaSJim Ingham     m_help_string.Clear();
16085e09c8c3SJim Ingham   }
16095e09c8c3SJim Ingham 
16105e09c8c3SJim Ingham   OptionValueString m_name;
16115e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
16125e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1613e9632ebaSJim Ingham   OptionValueString m_help_string;
16145e09c8c3SJim Ingham };
16155e09c8c3SJim Ingham 
1616f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1617f94668e3SRaphael Isemann #include "CommandOptions.inc"
1618b842f2ecSJim Ingham 
16198fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1620b842f2ecSJim Ingham public:
1621*abb0ed44SKazu Hirata   BreakpointAccessOptionGroup() {}
1622b842f2ecSJim Ingham 
1623b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1624b842f2ecSJim Ingham 
1625b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1626b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1627b842f2ecSJim Ingham   }
1628b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1629b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1630b842f2ecSJim Ingham     Status error;
1631a925974bSAdrian Prantl     const int short_option =
1632a925974bSAdrian Prantl         g_breakpoint_access_options[option_idx].short_option;
1633b842f2ecSJim Ingham 
1634b842f2ecSJim Ingham     switch (short_option) {
1635b842f2ecSJim Ingham     case 'L': {
1636b842f2ecSJim Ingham       bool value, success;
163747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1638b842f2ecSJim Ingham       if (success) {
1639b842f2ecSJim Ingham         m_permissions.SetAllowList(value);
1640b842f2ecSJim Ingham       } else
1641b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1642b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1643b842f2ecSJim Ingham             option_arg.str().c_str());
1644b842f2ecSJim Ingham     } break;
1645b842f2ecSJim Ingham     case 'A': {
1646b842f2ecSJim Ingham       bool value, success;
164747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1648b842f2ecSJim Ingham       if (success) {
1649b842f2ecSJim Ingham         m_permissions.SetAllowDisable(value);
1650b842f2ecSJim Ingham       } else
1651b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1652b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1653b842f2ecSJim Ingham             option_arg.str().c_str());
1654b842f2ecSJim Ingham     } break;
1655b842f2ecSJim Ingham     case 'D': {
1656b842f2ecSJim Ingham       bool value, success;
165747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1658b842f2ecSJim Ingham       if (success) {
1659b842f2ecSJim Ingham         m_permissions.SetAllowDelete(value);
1660b842f2ecSJim Ingham       } else
1661b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
1662b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -L option",
1663b842f2ecSJim Ingham             option_arg.str().c_str());
1664b842f2ecSJim Ingham     } break;
166536162014SRaphael Isemann     default:
166636162014SRaphael Isemann       llvm_unreachable("Unimplemented option");
1667b842f2ecSJim Ingham     }
1668b842f2ecSJim Ingham 
1669b842f2ecSJim Ingham     return error;
1670b842f2ecSJim Ingham   }
1671b842f2ecSJim Ingham 
1672a925974bSAdrian Prantl   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1673b842f2ecSJim Ingham 
1674a925974bSAdrian Prantl   const BreakpointName::Permissions &GetPermissions() const {
1675b842f2ecSJim Ingham     return m_permissions;
1676b842f2ecSJim Ingham   }
1677b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1678b842f2ecSJim Ingham };
1679b842f2ecSJim Ingham 
1680b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1681b842f2ecSJim Ingham public:
1682b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1683b842f2ecSJim Ingham       : CommandObjectParsed(
1684a925974bSAdrian Prantl             interpreter, "configure",
1685a925974bSAdrian Prantl             "Configure the options for the breakpoint"
1686b842f2ecSJim Ingham             " name provided.  "
1687b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1688b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1689b842f2ecSJim Ingham             "on the name.",
1690b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1691*abb0ed44SKazu Hirata             "<breakpoint-name-list>") {
1692b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1693b842f2ecSJim Ingham     // command.
1694b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1695b842f2ecSJim Ingham     CommandArgumentData id_arg;
1696b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1697b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1698b842f2ecSJim Ingham     arg1.push_back(id_arg);
1699b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1700b842f2ecSJim Ingham 
1701a925974bSAdrian Prantl     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1702a925974bSAdrian Prantl     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1703b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1704a925974bSAdrian Prantl     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1705e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1706b842f2ecSJim Ingham     m_option_group.Finalize();
1707b842f2ecSJim Ingham   }
1708b842f2ecSJim Ingham 
1709b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1710b842f2ecSJim Ingham 
1711b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1712b842f2ecSJim Ingham 
1713b842f2ecSJim Ingham protected:
1714b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1715b842f2ecSJim Ingham 
1716b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1717b842f2ecSJim Ingham     if (argc == 0) {
1718b842f2ecSJim Ingham       result.AppendError("No names provided.");
1719b842f2ecSJim Ingham       return false;
1720b842f2ecSJim Ingham     }
1721b842f2ecSJim Ingham 
1722cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget(false);
1723b842f2ecSJim Ingham 
1724b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1725cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
1726b842f2ecSJim Ingham 
1727b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1728b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1729b842f2ecSJim Ingham       Status error;
1730a925974bSAdrian Prantl       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1731b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1732b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1733b842f2ecSJim Ingham         return false;
1734b842f2ecSJim Ingham       }
1735b842f2ecSJim Ingham     }
173605097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
173705097246SAdrian Prantl     // check the error:
1738b842f2ecSJim Ingham     BreakpointSP bp_sp;
1739a925974bSAdrian Prantl     if (m_bp_id.m_breakpoint.OptionWasSet()) {
1740b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1741cb2380c9SRaphael Isemann       bp_sp = target.GetBreakpointByID(bp_id);
1742a925974bSAdrian Prantl       if (!bp_sp) {
1743b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1744b842f2ecSJim Ingham                                       bp_id);
1745b842f2ecSJim Ingham         return false;
1746b842f2ecSJim Ingham       }
1747b842f2ecSJim Ingham     }
1748b842f2ecSJim Ingham 
1749b842f2ecSJim Ingham     Status error;
1750b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1751b842f2ecSJim Ingham       ConstString name(entry.c_str());
1752cb2380c9SRaphael Isemann       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1753b842f2ecSJim Ingham       if (!bp_name)
1754b842f2ecSJim Ingham         continue;
1755e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1756e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1757e9632ebaSJim Ingham 
1758b842f2ecSJim Ingham       if (bp_sp)
1759cfb96d84SJim Ingham         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1760b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1761b842f2ecSJim Ingham       else
1762cb2380c9SRaphael Isemann         target.ConfigureBreakpointName(*bp_name,
1763b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1764b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1765b842f2ecSJim Ingham     }
1766b842f2ecSJim Ingham     return true;
1767b842f2ecSJim Ingham   }
1768b842f2ecSJim Ingham 
1769b842f2ecSJim Ingham private:
1770b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1771b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1772b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1773b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1774b842f2ecSJim Ingham };
1775b842f2ecSJim Ingham 
1776b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
17775e09c8c3SJim Ingham public:
1778b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1779b9c1b51eSKate Stone       : CommandObjectParsed(
1780b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
1781*abb0ed44SKazu Hirata             "breakpoint name add <command-options> <breakpoint-id-list>") {
1782b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1783b9c1b51eSKate Stone     // command.
17845e09c8c3SJim Ingham     CommandArgumentEntry arg1;
17855e09c8c3SJim Ingham     CommandArgumentData id_arg;
17865e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
17875e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
17885e09c8c3SJim Ingham     arg1.push_back(id_arg);
17895e09c8c3SJim Ingham     m_arguments.push_back(arg1);
17905e09c8c3SJim Ingham 
17915e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
17925e09c8c3SJim Ingham     m_option_group.Finalize();
17935e09c8c3SJim Ingham   }
17945e09c8c3SJim Ingham 
17959e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
17965e09c8c3SJim Ingham 
1797e87362e6SGongyu Deng   void
1798e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1799e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1800e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1801e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1802e87362e6SGongyu Deng         request, nullptr);
1803e87362e6SGongyu Deng   }
1804e87362e6SGongyu Deng 
1805b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18065e09c8c3SJim Ingham 
18075e09c8c3SJim Ingham protected:
1808b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1809b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18101b1c8e4aSDavid Spickett       result.AppendError("No name option provided.");
18115e09c8c3SJim Ingham       return false;
18125e09c8c3SJim Ingham     }
18135e09c8c3SJim Ingham 
1814cb2380c9SRaphael Isemann     Target &target =
1815b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18165e09c8c3SJim Ingham 
1817bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1818cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
18195e09c8c3SJim Ingham 
1820cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
18215e09c8c3SJim Ingham 
18225e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1823b9c1b51eSKate Stone     if (num_breakpoints == 0) {
18241b1c8e4aSDavid Spickett       result.AppendError("No breakpoints, cannot add names.");
18255e09c8c3SJim Ingham       return false;
18265e09c8c3SJim Ingham     }
18275e09c8c3SJim Ingham 
18285e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
18295e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1830b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1831cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1832b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
18335e09c8c3SJim Ingham 
1834b9c1b51eSKate Stone     if (result.Succeeded()) {
1835b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
18361b1c8e4aSDavid Spickett         result.AppendError("No breakpoints specified, cannot add names.");
18375e09c8c3SJim Ingham         return false;
18385e09c8c3SJim Ingham       }
18395e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1840b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1841b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1842b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1843b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1844b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1845b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
18465e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1847cb2380c9SRaphael Isemann         target.AddNameToBreakpoint(bp_sp, bp_name, error);
18485e09c8c3SJim Ingham       }
18495e09c8c3SJim Ingham     }
18505e09c8c3SJim Ingham 
18515e09c8c3SJim Ingham     return true;
18525e09c8c3SJim Ingham   }
18535e09c8c3SJim Ingham 
18545e09c8c3SJim Ingham private:
18555e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
18565e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
18575e09c8c3SJim Ingham };
18585e09c8c3SJim Ingham 
1859b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
18605e09c8c3SJim Ingham public:
1861b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1862b9c1b51eSKate Stone       : CommandObjectParsed(
1863b9c1b51eSKate Stone             interpreter, "delete",
18645e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
1865*abb0ed44SKazu Hirata             "breakpoint name delete <command-options> <breakpoint-id-list>") {
1866b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1867b9c1b51eSKate Stone     // command.
18685e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18695e09c8c3SJim Ingham     CommandArgumentData id_arg;
18705e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18715e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18725e09c8c3SJim Ingham     arg1.push_back(id_arg);
18735e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18745e09c8c3SJim Ingham 
18755e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18765e09c8c3SJim Ingham     m_option_group.Finalize();
18775e09c8c3SJim Ingham   }
18785e09c8c3SJim Ingham 
18799e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
18805e09c8c3SJim Ingham 
1881e87362e6SGongyu Deng   void
1882e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
1883e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
1884e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
1885e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
1886e87362e6SGongyu Deng         request, nullptr);
1887e87362e6SGongyu Deng   }
1888e87362e6SGongyu Deng 
1889b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18905e09c8c3SJim Ingham 
18915e09c8c3SJim Ingham protected:
1892b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1893b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18941b1c8e4aSDavid Spickett       result.AppendError("No name option provided.");
18955e09c8c3SJim Ingham       return false;
18965e09c8c3SJim Ingham     }
18975e09c8c3SJim Ingham 
1898cb2380c9SRaphael Isemann     Target &target =
1899b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19005e09c8c3SJim Ingham 
1901bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1902cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
19035e09c8c3SJim Ingham 
1904cb2380c9SRaphael Isemann     const BreakpointList &breakpoints = target.GetBreakpointList();
19055e09c8c3SJim Ingham 
19065e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1907b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19081b1c8e4aSDavid Spickett       result.AppendError("No breakpoints, cannot delete names.");
19095e09c8c3SJim Ingham       return false;
19105e09c8c3SJim Ingham     }
19115e09c8c3SJim Ingham 
19125e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19135e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1914b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1915cb2380c9SRaphael Isemann         command, &target, result, &valid_bp_ids,
1916b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
19175e09c8c3SJim Ingham 
1918b9c1b51eSKate Stone     if (result.Succeeded()) {
1919b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19201b1c8e4aSDavid Spickett         result.AppendError("No breakpoints specified, cannot delete names.");
19215e09c8c3SJim Ingham         return false;
19225e09c8c3SJim Ingham       }
1923b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
19245e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1925b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1926b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1927b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19285e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1929cb2380c9SRaphael Isemann         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
19305e09c8c3SJim Ingham       }
19315e09c8c3SJim Ingham     }
19325e09c8c3SJim Ingham 
19335e09c8c3SJim Ingham     return true;
19345e09c8c3SJim Ingham   }
19355e09c8c3SJim Ingham 
19365e09c8c3SJim Ingham private:
19375e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19385e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19395e09c8c3SJim Ingham };
19405e09c8c3SJim Ingham 
1941b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
19425e09c8c3SJim Ingham public:
1943b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1944b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
1945b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
1946b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
1947b842f2ecSJim Ingham                             "names",
1948*abb0ed44SKazu Hirata                             "breakpoint name list <command-options>") {
1949b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
19505e09c8c3SJim Ingham     m_option_group.Finalize();
19515e09c8c3SJim Ingham   }
19525e09c8c3SJim Ingham 
19539e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
19545e09c8c3SJim Ingham 
1955b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19565e09c8c3SJim Ingham 
19575e09c8c3SJim Ingham protected:
1958b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1959cb2380c9SRaphael Isemann     Target &target =
1960b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19615e09c8c3SJim Ingham 
1962b842f2ecSJim Ingham     std::vector<std::string> name_list;
1963b842f2ecSJim Ingham     if (command.empty()) {
1964cb2380c9SRaphael Isemann       target.GetBreakpointNames(name_list);
1965b842f2ecSJim Ingham     } else {
1966a925974bSAdrian Prantl       for (const Args::ArgEntry &arg : command) {
1967b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
1968b842f2ecSJim Ingham       }
1969b842f2ecSJim Ingham     }
1970b842f2ecSJim Ingham 
1971b842f2ecSJim Ingham     if (name_list.empty()) {
1972b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
1973b842f2ecSJim Ingham     } else {
1974b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
1975b842f2ecSJim Ingham         const char *name = name_str.c_str();
1976b842f2ecSJim Ingham         // First print out the options for the name:
1977b842f2ecSJim Ingham         Status error;
1978cb2380c9SRaphael Isemann         BreakpointName *bp_name =
1979cb2380c9SRaphael Isemann             target.FindBreakpointName(ConstString(name), false, error);
1980a925974bSAdrian Prantl         if (bp_name) {
1981b842f2ecSJim Ingham           StreamString s;
1982b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
1983a925974bSAdrian Prantl           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1984b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
1985b842f2ecSJim Ingham           }
1986b842f2ecSJim Ingham 
1987bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
1988cb2380c9SRaphael Isemann           target.GetBreakpointList().GetListMutex(lock);
19895e09c8c3SJim Ingham 
1990cb2380c9SRaphael Isemann           BreakpointList &breakpoints = target.GetBreakpointList();
1991b842f2ecSJim Ingham           bool any_set = false;
1992b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1993b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
19945e09c8c3SJim Ingham               StreamString s;
1995b842f2ecSJim Ingham               any_set = true;
19965e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
19975e09c8c3SJim Ingham               s.EOL();
1998c156427dSZachary Turner               result.AppendMessage(s.GetString());
19995e09c8c3SJim Ingham             }
20005e09c8c3SJim Ingham           }
2001b842f2ecSJim Ingham           if (!any_set)
2002b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
2003b9c1b51eSKate Stone         } else {
2004b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
20055e09c8c3SJim Ingham         }
2006b842f2ecSJim Ingham       }
20075e09c8c3SJim Ingham     }
20085e09c8c3SJim Ingham     return true;
20095e09c8c3SJim Ingham   }
20105e09c8c3SJim Ingham 
20115e09c8c3SJim Ingham private:
20125e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20135e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20145e09c8c3SJim Ingham };
20155e09c8c3SJim Ingham 
2016e14dc268SJim Ingham // CommandObjectBreakpointName
2017b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
20185e09c8c3SJim Ingham public:
20197428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2020b9c1b51eSKate Stone       : CommandObjectMultiword(
2021b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2022b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2023b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2024b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2025b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2026b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2027b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2028b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2029b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2030b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
20315e09c8c3SJim Ingham 
20325e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
20335e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
20345e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2035b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
20365e09c8c3SJim Ingham   }
20375e09c8c3SJim Ingham 
20389e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
20395e09c8c3SJim Ingham };
20405e09c8c3SJim Ingham 
2041e14dc268SJim Ingham // CommandObjectBreakpointRead
20423acdf385SJim Ingham #pragma mark Read::CommandOptions
2043f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2044f94668e3SRaphael Isemann #include "CommandOptions.inc"
20451f0f5b5bSZachary Turner 
20461f0f5b5bSZachary Turner #pragma mark Read
2047e14dc268SJim Ingham 
2048e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2049e14dc268SJim Ingham public:
2050e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2051e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2052e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2053e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2054*abb0ed44SKazu Hirata                             nullptr) {}
2055e14dc268SJim Ingham 
2056e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2057e14dc268SJim Ingham 
2058e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2059e14dc268SJim Ingham 
2060e14dc268SJim Ingham   class CommandOptions : public Options {
2061e14dc268SJim Ingham   public:
2062*abb0ed44SKazu Hirata     CommandOptions() {}
2063e14dc268SJim Ingham 
2064e14dc268SJim Ingham     ~CommandOptions() override = default;
2065e14dc268SJim Ingham 
206697206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2067e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
206897206d57SZachary Turner       Status error;
2069e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2070e14dc268SJim Ingham 
2071e14dc268SJim Ingham       switch (short_option) {
2072e14dc268SJim Ingham       case 'f':
2073adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2074e14dc268SJim Ingham         break;
20753acdf385SJim Ingham       case 'N': {
207697206d57SZachary Turner         Status name_error;
20773acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
20783acdf385SJim Ingham                                                   name_error)) {
20793acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
20803acdf385SJim Ingham                                          name_error.AsCString());
20813acdf385SJim Ingham         }
2082adcd0268SBenjamin Kramer         m_names.push_back(std::string(option_arg));
20833acdf385SJim Ingham         break;
20843acdf385SJim Ingham       }
2085e14dc268SJim Ingham       default:
208636162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2087e14dc268SJim Ingham       }
2088e14dc268SJim Ingham 
2089e14dc268SJim Ingham       return error;
2090e14dc268SJim Ingham     }
2091e14dc268SJim Ingham 
2092e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2093e14dc268SJim Ingham       m_filename.clear();
20943acdf385SJim Ingham       m_names.clear();
2095e14dc268SJim Ingham     }
2096e14dc268SJim Ingham 
20971f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
209870602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
20991f0f5b5bSZachary Turner     }
2100e14dc268SJim Ingham 
210122e63cbaSGongyu Deng     void HandleOptionArgumentCompletion(
210222e63cbaSGongyu Deng         CompletionRequest &request, OptionElementVector &opt_element_vector,
210322e63cbaSGongyu Deng         int opt_element_index, CommandInterpreter &interpreter) override {
210422e63cbaSGongyu Deng       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
210522e63cbaSGongyu Deng       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
210622e63cbaSGongyu Deng 
210722e63cbaSGongyu Deng       switch (GetDefinitions()[opt_defs_index].short_option) {
210822e63cbaSGongyu Deng       case 'f':
210922e63cbaSGongyu Deng         CommandCompletions::InvokeCommonCompletionCallbacks(
211022e63cbaSGongyu Deng             interpreter, CommandCompletions::eDiskFileCompletion, request,
211122e63cbaSGongyu Deng             nullptr);
211222e63cbaSGongyu Deng         break;
211322e63cbaSGongyu Deng 
211422e63cbaSGongyu Deng       case 'N':
211522e63cbaSGongyu Deng         llvm::Optional<FileSpec> file_spec;
211622e63cbaSGongyu Deng         const llvm::StringRef dash_f("-f");
211722e63cbaSGongyu Deng         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
211822e63cbaSGongyu Deng           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
211922e63cbaSGongyu Deng             file_spec.emplace(
212022e63cbaSGongyu Deng                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
212122e63cbaSGongyu Deng             break;
212222e63cbaSGongyu Deng           }
212322e63cbaSGongyu Deng         }
212422e63cbaSGongyu Deng         if (!file_spec)
212522e63cbaSGongyu Deng           return;
212622e63cbaSGongyu Deng 
212722e63cbaSGongyu Deng         FileSystem::Instance().Resolve(*file_spec);
212822e63cbaSGongyu Deng         Status error;
212922e63cbaSGongyu Deng         StructuredData::ObjectSP input_data_sp =
213022e63cbaSGongyu Deng             StructuredData::ParseJSONFromFile(*file_spec, error);
213122e63cbaSGongyu Deng         if (!error.Success())
213222e63cbaSGongyu Deng           return;
213322e63cbaSGongyu Deng 
213422e63cbaSGongyu Deng         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
213522e63cbaSGongyu Deng         if (!bkpt_array)
213622e63cbaSGongyu Deng           return;
213722e63cbaSGongyu Deng 
213822e63cbaSGongyu Deng         const size_t num_bkpts = bkpt_array->GetSize();
213922e63cbaSGongyu Deng         for (size_t i = 0; i < num_bkpts; i++) {
214022e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_object_sp =
214122e63cbaSGongyu Deng               bkpt_array->GetItemAtIndex(i);
214222e63cbaSGongyu Deng           if (!bkpt_object_sp)
214322e63cbaSGongyu Deng             return;
214422e63cbaSGongyu Deng 
214522e63cbaSGongyu Deng           StructuredData::Dictionary *bkpt_dict =
214622e63cbaSGongyu Deng               bkpt_object_sp->GetAsDictionary();
214722e63cbaSGongyu Deng           if (!bkpt_dict)
214822e63cbaSGongyu Deng             return;
214922e63cbaSGongyu Deng 
215022e63cbaSGongyu Deng           StructuredData::ObjectSP bkpt_data_sp =
215122e63cbaSGongyu Deng               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
215222e63cbaSGongyu Deng           if (!bkpt_data_sp)
215322e63cbaSGongyu Deng             return;
215422e63cbaSGongyu Deng 
215522e63cbaSGongyu Deng           bkpt_dict = bkpt_data_sp->GetAsDictionary();
215622e63cbaSGongyu Deng           if (!bkpt_dict)
215722e63cbaSGongyu Deng             return;
215822e63cbaSGongyu Deng 
215922e63cbaSGongyu Deng           StructuredData::Array *names_array;
216022e63cbaSGongyu Deng 
216122e63cbaSGongyu Deng           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
216222e63cbaSGongyu Deng             return;
216322e63cbaSGongyu Deng 
216422e63cbaSGongyu Deng           size_t num_names = names_array->GetSize();
216522e63cbaSGongyu Deng 
216622e63cbaSGongyu Deng           for (size_t i = 0; i < num_names; i++) {
216722e63cbaSGongyu Deng             llvm::StringRef name;
216822e63cbaSGongyu Deng             if (names_array->GetItemAtIndexAsString(i, name))
216922e63cbaSGongyu Deng               request.TryCompleteCurrentArg(name);
217022e63cbaSGongyu Deng           }
217122e63cbaSGongyu Deng         }
217222e63cbaSGongyu Deng       }
217322e63cbaSGongyu Deng     }
2174e14dc268SJim Ingham 
2175e14dc268SJim Ingham     std::string m_filename;
21763acdf385SJim Ingham     std::vector<std::string> m_names;
2177e14dc268SJim Ingham   };
2178e14dc268SJim Ingham 
2179e14dc268SJim Ingham protected:
2180e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2181cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2182e14dc268SJim Ingham 
21833acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2184cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
21853acdf385SJim Ingham 
21868f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
21878f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
218801f16664SJim Ingham     BreakpointIDList new_bps;
2189cb2380c9SRaphael Isemann     Status error = target.CreateBreakpointsFromFile(input_spec,
2190cb2380c9SRaphael Isemann                                                     m_options.m_names, new_bps);
2191e14dc268SJim Ingham 
2192e14dc268SJim Ingham     if (!error.Success()) {
219301f16664SJim Ingham       result.AppendError(error.AsCString());
219401f16664SJim Ingham       return false;
2195e14dc268SJim Ingham     }
21963acdf385SJim Ingham 
21973acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
21983acdf385SJim Ingham 
21993acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
22003acdf385SJim Ingham     if (num_breakpoints == 0) {
22013acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
22023acdf385SJim Ingham     } else {
22033acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
22043acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
22053acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
22063acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2207cb2380c9SRaphael Isemann         Breakpoint *bp = target.GetBreakpointList()
22083acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
22093acdf385SJim Ingham                              .get();
22103acdf385SJim Ingham         if (bp)
22113acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22123acdf385SJim Ingham                              false);
22133acdf385SJim Ingham       }
22143acdf385SJim Ingham     }
2215e14dc268SJim Ingham     return result.Succeeded();
2216e14dc268SJim Ingham   }
2217e14dc268SJim Ingham 
2218e14dc268SJim Ingham private:
2219e14dc268SJim Ingham   CommandOptions m_options;
2220e14dc268SJim Ingham };
2221e14dc268SJim Ingham 
2222e14dc268SJim Ingham // CommandObjectBreakpointWrite
22231f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
2224f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2225f94668e3SRaphael Isemann #include "CommandOptions.inc"
22261f0f5b5bSZachary Turner 
22271f0f5b5bSZachary Turner #pragma mark Write
2228e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2229e14dc268SJim Ingham public:
2230e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2231e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2232e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2233e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2234e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2235*abb0ed44SKazu Hirata                             nullptr) {
2236e14dc268SJim Ingham     CommandArgumentEntry arg;
2237e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2238e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2239e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2240e14dc268SJim Ingham     // arguments vector.
2241e14dc268SJim Ingham     m_arguments.push_back(arg);
2242e14dc268SJim Ingham   }
2243e14dc268SJim Ingham 
2244e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2245e14dc268SJim Ingham 
2246e87362e6SGongyu Deng   void
2247e87362e6SGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
2248e87362e6SGongyu Deng                            OptionElementVector &opt_element_vector) override {
2249e87362e6SGongyu Deng     CommandCompletions::InvokeCommonCompletionCallbacks(
2250e87362e6SGongyu Deng         GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
2251e87362e6SGongyu Deng         request, nullptr);
2252e87362e6SGongyu Deng   }
2253e87362e6SGongyu Deng 
2254e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2255e14dc268SJim Ingham 
2256e14dc268SJim Ingham   class CommandOptions : public Options {
2257e14dc268SJim Ingham   public:
2258*abb0ed44SKazu Hirata     CommandOptions() {}
2259e14dc268SJim Ingham 
2260e14dc268SJim Ingham     ~CommandOptions() override = default;
2261e14dc268SJim Ingham 
226297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2263e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
226497206d57SZachary Turner       Status error;
2265e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2266e14dc268SJim Ingham 
2267e14dc268SJim Ingham       switch (short_option) {
2268e14dc268SJim Ingham       case 'f':
2269adcd0268SBenjamin Kramer         m_filename.assign(std::string(option_arg));
2270e14dc268SJim Ingham         break;
22712d3628e1SJim Ingham       case 'a':
22722d3628e1SJim Ingham         m_append = true;
22732d3628e1SJim Ingham         break;
2274e14dc268SJim Ingham       default:
227536162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
2276e14dc268SJim Ingham       }
2277e14dc268SJim Ingham 
2278e14dc268SJim Ingham       return error;
2279e14dc268SJim Ingham     }
2280e14dc268SJim Ingham 
2281e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2282e14dc268SJim Ingham       m_filename.clear();
22832d3628e1SJim Ingham       m_append = false;
2284e14dc268SJim Ingham     }
2285e14dc268SJim Ingham 
22861f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
228770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
22881f0f5b5bSZachary Turner     }
2289e14dc268SJim Ingham 
2290e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2291e14dc268SJim Ingham 
2292e14dc268SJim Ingham     std::string m_filename;
22932d3628e1SJim Ingham     bool m_append = false;
2294e14dc268SJim Ingham   };
2295e14dc268SJim Ingham 
2296e14dc268SJim Ingham protected:
2297e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2298cb2380c9SRaphael Isemann     Target &target = GetSelectedOrDummyTarget();
2299e14dc268SJim Ingham 
2300e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2301cb2380c9SRaphael Isemann     target.GetBreakpointList().GetListMutex(lock);
2302e14dc268SJim Ingham 
2303e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
230411eb9c64SZachary Turner     if (!command.empty()) {
2305e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2306cb2380c9SRaphael Isemann           command, &target, result, &valid_bp_ids,
2307b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2308e14dc268SJim Ingham 
230901f16664SJim Ingham       if (!result.Succeeded()) {
2310e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2311e14dc268SJim Ingham         return false;
2312e14dc268SJim Ingham       }
2313e14dc268SJim Ingham     }
23148f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
23158f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
2316cb2380c9SRaphael Isemann     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23178f3be7a3SJonas Devlieghere                                                      m_options.m_append);
231801f16664SJim Ingham     if (!error.Success()) {
231901f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
232001f16664SJim Ingham                                    error.AsCString());
2321e14dc268SJim Ingham     }
2322e14dc268SJim Ingham     return result.Succeeded();
2323e14dc268SJim Ingham   }
2324e14dc268SJim Ingham 
2325e14dc268SJim Ingham private:
2326e14dc268SJim Ingham   CommandOptions m_options;
2327e14dc268SJim Ingham };
2328e14dc268SJim Ingham 
232930fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2330ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
233130fdc8d8SChris Lattner 
2332b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2333b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2334b9c1b51eSKate Stone     : CommandObjectMultiword(
2335b9c1b51eSKate Stone           interpreter, "breakpoint",
23367428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2337b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2338b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2339b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2340b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2341b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2342b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2343b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2344b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2345b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2346b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2347b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2348b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2349b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2350b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2351b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2352b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2353b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2354b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2355b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2356e14dc268SJim Ingham   CommandObjectSP write_command_object(
2357e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2358e14dc268SJim Ingham   CommandObjectSP read_command_object(
2359e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
236030fdc8d8SChris Lattner 
2361b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
236230fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
236330fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2364b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2365b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2366ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2367b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2368b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
23695e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2370e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2371e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
237230fdc8d8SChris Lattner 
237323f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
237423f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
237523f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
237623f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
237723f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
237823f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
237923f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
238023f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
23815e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2382e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2383e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
238430fdc8d8SChris Lattner }
238530fdc8d8SChris Lattner 
23869e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
238730fdc8d8SChris Lattner 
2388a925974bSAdrian Prantl void CommandObjectMultiwordBreakpoint::VerifyIDs(
2389a925974bSAdrian Prantl     Args &args, Target *target, bool allow_locations,
2390a925974bSAdrian Prantl     CommandReturnObject &result, BreakpointIDList *valid_ids,
2391a925974bSAdrian Prantl     BreakpointName::Permissions ::PermissionKinds purpose) {
239230fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2393b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2394b9c1b51eSKate Stone   //                                  canonical representation
2395b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2396b9c1b51eSKate Stone   //                                  representing a range (in which case there
2397b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2398b9c1b51eSKate Stone   //                                      after of one of the first two types.
23995e09c8c3SJim Ingham   //                                  4). A breakpoint name
2400b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2401b9c1b51eSKate Stone   // one.)
240230fdc8d8SChris Lattner 
240330fdc8d8SChris Lattner   Args temp_args;
240430fdc8d8SChris Lattner 
240511eb9c64SZachary Turner   if (args.empty()) {
2406b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2407b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2408b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
240936f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2410b9c1b51eSKate Stone     } else {
2411b9c1b51eSKate Stone       result.AppendError(
2412b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
241336f3b369SJim Ingham     }
241436f3b369SJim Ingham     return;
241536f3b369SJim Ingham   }
241636f3b369SJim Ingham 
2417b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
241805097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
241905097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
242005097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
242105097246SAdrian Prantl   // into TEMP_ARGS.
242230fdc8d8SChris Lattner 
2423b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2424b842f2ecSJim Ingham                                            purpose, result, temp_args);
242530fdc8d8SChris Lattner 
2426b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2427b9c1b51eSKate Stone   // BreakpointIDList:
242830fdc8d8SChris Lattner 
242916662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
243030fdc8d8SChris Lattner 
243105097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
243205097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
243330fdc8d8SChris Lattner 
2434b9c1b51eSKate Stone   if (result.Succeeded()) {
2435b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
243605097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
243705097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
243830fdc8d8SChris Lattner 
2439c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2440b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
244130fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2442b9c1b51eSKate Stone       Breakpoint *breakpoint =
2443b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2444b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2445c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2446b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
244730fdc8d8SChris Lattner           StreamString id_str;
2448b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2449b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2450c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2451b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2452b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
245330fdc8d8SChris Lattner               id_str.GetData());
245430fdc8d8SChris Lattner         }
2455b9c1b51eSKate Stone       } else {
2456c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2457b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2458b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
24597428a18cSKate Stone             cur_bp_id.GetBreakpointID());
246030fdc8d8SChris Lattner       }
246130fdc8d8SChris Lattner     }
246230fdc8d8SChris Lattner   }
246330fdc8d8SChris Lattner }
2464