130fdc8d8SChris Lattner //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
99e85e5a8SEugene Zelenko #include "CommandObjectBreakpoint.h"
109e85e5a8SEugene Zelenko #include "CommandObjectBreakpointCommand.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
1230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
1330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
15b9c1b51eSKate Stone #include "lldb/Interpreter/CommandCompletions.h"
16b9c1b51eSKate Stone #include "lldb/Interpreter/CommandInterpreter.h"
17b9c1b51eSKate Stone #include "lldb/Interpreter/CommandReturnObject.h"
1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
1932abc6edSZachary Turner #include "lldb/Interpreter/OptionValueBoolean.h"
205e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueString.h"
215e09c8c3SJim Ingham #include "lldb/Interpreter/OptionValueUInt64.h"
22b9c1b51eSKate Stone #include "lldb/Interpreter/Options.h"
230e0984eeSJim Ingham #include "lldb/Target/Language.h"
24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
25b9c1b51eSKate Stone #include "lldb/Target/Target.h"
261b54c88cSJim Ingham #include "lldb/Target/Thread.h"
271b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
28bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h"
29bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
3030fdc8d8SChris Lattner 
31796ac80bSJonas Devlieghere #include <memory>
32796ac80bSJonas Devlieghere #include <vector>
33796ac80bSJonas Devlieghere 
3430fdc8d8SChris Lattner using namespace lldb;
3530fdc8d8SChris Lattner using namespace lldb_private;
3630fdc8d8SChris Lattner 
37b9c1b51eSKate Stone static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38b9c1b51eSKate Stone                                      lldb::DescriptionLevel level) {
3930fdc8d8SChris Lattner   s->IndentMore();
4030fdc8d8SChris Lattner   bp->GetDescription(s, level, true);
4130fdc8d8SChris Lattner   s->IndentLess();
4230fdc8d8SChris Lattner   s->EOL();
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
45b842f2ecSJim Ingham // Modifiable Breakpoint Options
46b842f2ecSJim Ingham #pragma mark Modify::CommandOptions
478fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_modify_options[] = {
48*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_modify
49*f94668e3SRaphael Isemann #include "CommandOptions.inc"
50b842f2ecSJim Ingham };
51b842f2ecSJim Ingham class lldb_private::BreakpointOptionGroup : public OptionGroup
52b842f2ecSJim Ingham {
53b842f2ecSJim Ingham public:
54b842f2ecSJim Ingham   BreakpointOptionGroup() :
55b842f2ecSJim Ingham           OptionGroup(),
56b842f2ecSJim Ingham           m_bp_opts(false) {}
57b842f2ecSJim Ingham 
58b842f2ecSJim Ingham   ~BreakpointOptionGroup() override = default;
59b842f2ecSJim Ingham 
60b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
61b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_modify_options);
62b842f2ecSJim Ingham   }
63b842f2ecSJim Ingham 
64b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
65b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
66b842f2ecSJim Ingham     Status error;
67b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
68b842f2ecSJim Ingham 
69b842f2ecSJim Ingham     switch (short_option) {
70b842f2ecSJim Ingham     case 'c':
7105097246SAdrian Prantl       // Normally an empty breakpoint condition marks is as unset. But we need
7205097246SAdrian Prantl       // to say it was passed in.
73b842f2ecSJim Ingham       m_bp_opts.SetCondition(option_arg.str().c_str());
74b842f2ecSJim Ingham       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
75b842f2ecSJim Ingham       break;
76b842f2ecSJim Ingham     case 'C':
77b842f2ecSJim Ingham       m_commands.push_back(option_arg);
78b842f2ecSJim Ingham       break;
79b842f2ecSJim Ingham     case 'd':
80b842f2ecSJim Ingham       m_bp_opts.SetEnabled(false);
81b842f2ecSJim Ingham       break;
82b842f2ecSJim Ingham     case 'e':
83b842f2ecSJim Ingham       m_bp_opts.SetEnabled(true);
84b842f2ecSJim Ingham       break;
85b842f2ecSJim Ingham     case 'G': {
86b842f2ecSJim Ingham       bool value, success;
8747cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
88b842f2ecSJim Ingham       if (success) {
89b842f2ecSJim Ingham         m_bp_opts.SetAutoContinue(value);
90b842f2ecSJim Ingham       } else
91b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
92b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -G option",
93b842f2ecSJim Ingham             option_arg.str().c_str());
94b842f2ecSJim Ingham     }
95b842f2ecSJim Ingham     break;
96b842f2ecSJim Ingham     case 'i':
97b842f2ecSJim Ingham     {
98b842f2ecSJim Ingham       uint32_t ignore_count;
99b842f2ecSJim Ingham       if (option_arg.getAsInteger(0, ignore_count))
100b842f2ecSJim Ingham         error.SetErrorStringWithFormat("invalid ignore count '%s'",
101b842f2ecSJim Ingham                                        option_arg.str().c_str());
102b842f2ecSJim Ingham       else
103b842f2ecSJim Ingham         m_bp_opts.SetIgnoreCount(ignore_count);
104b842f2ecSJim Ingham     }
105b842f2ecSJim Ingham     break;
106b842f2ecSJim Ingham     case 'o': {
107b842f2ecSJim Ingham       bool value, success;
10847cbf4a0SPavel Labath       value = OptionArgParser::ToBoolean(option_arg, false, &success);
109b842f2ecSJim Ingham       if (success) {
110b842f2ecSJim Ingham         m_bp_opts.SetOneShot(value);
111b842f2ecSJim Ingham       } else
112b842f2ecSJim Ingham         error.SetErrorStringWithFormat(
113b842f2ecSJim Ingham             "invalid boolean value '%s' passed for -o option",
114b842f2ecSJim Ingham             option_arg.str().c_str());
115b842f2ecSJim Ingham     } break;
116b842f2ecSJim Ingham     case 't':
117b842f2ecSJim Ingham     {
118b842f2ecSJim Ingham       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
119b842f2ecSJim Ingham       if (option_arg[0] != '\0') {
120b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_id))
121b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread id string '%s'",
122b842f2ecSJim Ingham                                          option_arg.str().c_str());
123b842f2ecSJim Ingham       }
124b842f2ecSJim Ingham       m_bp_opts.SetThreadID(thread_id);
125b842f2ecSJim Ingham     }
126b842f2ecSJim Ingham     break;
127b842f2ecSJim Ingham     case 'T':
128b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
129b842f2ecSJim Ingham       break;
130b842f2ecSJim Ingham     case 'q':
131b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
132b842f2ecSJim Ingham       break;
133b842f2ecSJim Ingham     case 'x':
134b842f2ecSJim Ingham     {
135b842f2ecSJim Ingham       uint32_t thread_index = UINT32_MAX;
136b842f2ecSJim Ingham       if (option_arg[0] != '\n') {
137b842f2ecSJim Ingham         if (option_arg.getAsInteger(0, thread_index))
138b842f2ecSJim Ingham           error.SetErrorStringWithFormat("invalid thread index string '%s'",
139b842f2ecSJim Ingham                                          option_arg.str().c_str());
140b842f2ecSJim Ingham       }
141b842f2ecSJim Ingham       m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
142b842f2ecSJim Ingham     }
143b842f2ecSJim Ingham     break;
144b842f2ecSJim Ingham     default:
145b842f2ecSJim Ingham       error.SetErrorStringWithFormat("unrecognized option '%c'",
146b842f2ecSJim Ingham                                      short_option);
147b842f2ecSJim Ingham       break;
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 {
159b842f2ecSJim Ingham     if (!m_commands.empty())
160b842f2ecSJim Ingham     {
161b842f2ecSJim Ingham       if (!m_commands.empty())
162b842f2ecSJim Ingham       {
163b842f2ecSJim Ingham           auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
164b842f2ecSJim Ingham 
165b842f2ecSJim Ingham           for (std::string &str : m_commands)
166b842f2ecSJim Ingham             cmd_data->user_source.AppendString(str);
167b842f2ecSJim Ingham 
168b842f2ecSJim Ingham           cmd_data->stop_on_error = true;
169b842f2ecSJim Ingham           m_bp_opts.SetCommandDataCallback(cmd_data);
170b842f2ecSJim Ingham       }
171b842f2ecSJim Ingham     }
172b842f2ecSJim Ingham     return Status();
173b842f2ecSJim Ingham   }
174b842f2ecSJim Ingham 
175b842f2ecSJim Ingham   const BreakpointOptions &GetBreakpointOptions()
176b842f2ecSJim Ingham   {
177b842f2ecSJim Ingham     return m_bp_opts;
178b842f2ecSJim Ingham   }
179b842f2ecSJim Ingham 
180b842f2ecSJim Ingham   std::vector<std::string> m_commands;
181b842f2ecSJim Ingham   BreakpointOptions m_bp_opts;
182b842f2ecSJim Ingham 
183b842f2ecSJim Ingham };
1848fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
185*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_dummy
186*f94668e3SRaphael Isemann #include "CommandOptions.inc"
187b842f2ecSJim Ingham };
188b842f2ecSJim Ingham 
189b842f2ecSJim Ingham class BreakpointDummyOptionGroup : public OptionGroup
190b842f2ecSJim Ingham {
191b842f2ecSJim Ingham public:
192b842f2ecSJim Ingham   BreakpointDummyOptionGroup() :
193b842f2ecSJim Ingham           OptionGroup() {}
194b842f2ecSJim Ingham 
195b842f2ecSJim Ingham   ~BreakpointDummyOptionGroup() override = default;
196b842f2ecSJim Ingham 
197b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
198b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_dummy_options);
199b842f2ecSJim Ingham   }
200b842f2ecSJim Ingham 
201b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
202b842f2ecSJim Ingham                           ExecutionContext *execution_context) override {
203b842f2ecSJim Ingham     Status error;
204b842f2ecSJim Ingham     const int short_option = g_breakpoint_modify_options[option_idx].short_option;
205b842f2ecSJim Ingham 
206b842f2ecSJim Ingham     switch (short_option) {
207b842f2ecSJim Ingham       case 'D':
208b842f2ecSJim Ingham         m_use_dummy = true;
209b842f2ecSJim Ingham         break;
210b842f2ecSJim Ingham     default:
211b842f2ecSJim Ingham       error.SetErrorStringWithFormat("unrecognized option '%c'",
212b842f2ecSJim Ingham                                      short_option);
213b842f2ecSJim Ingham       break;
214b842f2ecSJim Ingham     }
215b842f2ecSJim Ingham 
216b842f2ecSJim Ingham     return error;
217b842f2ecSJim Ingham   }
218b842f2ecSJim Ingham 
219b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
220b842f2ecSJim Ingham     m_use_dummy = false;
221b842f2ecSJim Ingham   }
222b842f2ecSJim Ingham 
223b842f2ecSJim Ingham   bool m_use_dummy;
224b842f2ecSJim Ingham 
225b842f2ecSJim Ingham };
226b842f2ecSJim Ingham 
2278fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_set_options[] = {
228*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_set
229*f94668e3SRaphael Isemann #include "CommandOptions.inc"
2301f0f5b5bSZachary Turner };
2311f0f5b5bSZachary Turner 
2325a988416SJim Ingham // CommandObjectBreakpointSet
23330fdc8d8SChris Lattner 
234b9c1b51eSKate Stone class CommandObjectBreakpointSet : public CommandObjectParsed {
2355a988416SJim Ingham public:
236efe8e7e3SFangrui Song   enum BreakpointSetType {
2375a988416SJim Ingham     eSetTypeInvalid,
2385a988416SJim Ingham     eSetTypeFileAndLine,
2395a988416SJim Ingham     eSetTypeAddress,
2405a988416SJim Ingham     eSetTypeFunctionName,
2415a988416SJim Ingham     eSetTypeFunctionRegexp,
2425a988416SJim Ingham     eSetTypeSourceRegexp,
2433815e702SJim Ingham     eSetTypeException,
2443815e702SJim Ingham     eSetTypeScripted,
245efe8e7e3SFangrui Song   };
2465a988416SJim Ingham 
247b9c1b51eSKate Stone   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
248b9c1b51eSKate Stone       : CommandObjectParsed(
249b9c1b51eSKate Stone             interpreter, "breakpoint set",
2505a988416SJim Ingham             "Sets a breakpoint or set of breakpoints in the executable.",
2515a988416SJim Ingham             "breakpoint set <cmd-options>"),
252b842f2ecSJim Ingham         m_bp_opts(), m_options() {
253b842f2ecSJim Ingham           // We're picking up all the normal options, commands and disable.
254b842f2ecSJim Ingham           m_all_options.Append(&m_bp_opts,
255b842f2ecSJim Ingham                                LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
256b842f2ecSJim Ingham                                LLDB_OPT_SET_ALL);
257b842f2ecSJim Ingham           m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
258b842f2ecSJim Ingham           m_all_options.Append(&m_options);
259b842f2ecSJim Ingham           m_all_options.Finalize();
260b842f2ecSJim Ingham         }
2615a988416SJim Ingham 
2629e85e5a8SEugene Zelenko   ~CommandObjectBreakpointSet() override = default;
2635a988416SJim Ingham 
264b842f2ecSJim Ingham   Options *GetOptions() override { return &m_all_options; }
2655a988416SJim Ingham 
266b842f2ecSJim Ingham   class CommandOptions : public OptionGroup {
2675a988416SJim Ingham   public:
268b9c1b51eSKate Stone     CommandOptions()
269b842f2ecSJim Ingham         : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
270b9c1b51eSKate Stone           m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
271b9c1b51eSKate Stone           m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
272b9c1b51eSKate Stone           m_catch_bp(false), m_throw_bp(true), m_hardware(false),
273a72b31c7SJim Ingham           m_exception_language(eLanguageTypeUnknown),
27423b1decbSDawn Perchik           m_language(lldb::eLanguageTypeUnknown),
275b842f2ecSJim Ingham           m_skip_prologue(eLazyBoolCalculate),
276b9c1b51eSKate Stone           m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
27730fdc8d8SChris Lattner 
2789e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
27987df91b8SJim Ingham 
28097206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
281b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
28297206d57SZachary Turner       Status error;
283b842f2ecSJim Ingham       const int short_option = g_breakpoint_set_options[option_idx].short_option;
28430fdc8d8SChris Lattner 
285b9c1b51eSKate Stone       switch (short_option) {
286b9c1b51eSKate Stone       case 'a': {
28747cbf4a0SPavel Labath         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
288e1cfbc79STodd Fiala                                                  LLDB_INVALID_ADDRESS, &error);
289b9c1b51eSKate Stone       } break;
29030fdc8d8SChris Lattner 
291e732052fSJim Ingham       case 'A':
292e732052fSJim Ingham         m_all_files = true;
293e732052fSJim Ingham         break;
294e732052fSJim Ingham 
295ca36cd16SJim Ingham       case 'b':
296ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
297ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeBase;
298ca36cd16SJim Ingham         break;
299ca36cd16SJim Ingham 
300fe11483bSZachary Turner       case 'C':
301fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_column))
302b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid column number: %s",
303fe11483bSZachary Turner                                          option_arg.str().c_str());
30430fdc8d8SChris Lattner         break;
3059e85e5a8SEugene Zelenko 
306b9c1b51eSKate Stone       case 'E': {
307fe11483bSZachary Turner         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
308fab10e89SJim Ingham 
309b9c1b51eSKate Stone         switch (language) {
310fab10e89SJim Ingham         case eLanguageTypeC89:
311fab10e89SJim Ingham         case eLanguageTypeC:
312fab10e89SJim Ingham         case eLanguageTypeC99:
3131d0089faSBruce Mitchener         case eLanguageTypeC11:
314a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC;
315fab10e89SJim Ingham           break;
316fab10e89SJim Ingham         case eLanguageTypeC_plus_plus:
3171d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_03:
3181d0089faSBruce Mitchener         case eLanguageTypeC_plus_plus_11:
3192ba84a6aSBruce Mitchener         case eLanguageTypeC_plus_plus_14:
320a72b31c7SJim Ingham           m_exception_language = eLanguageTypeC_plus_plus;
321fab10e89SJim Ingham           break;
322fab10e89SJim Ingham         case eLanguageTypeObjC:
323a72b31c7SJim Ingham           m_exception_language = eLanguageTypeObjC;
324fab10e89SJim Ingham           break;
325fab10e89SJim Ingham         case eLanguageTypeObjC_plus_plus:
326b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
327b9c1b51eSKate Stone               "Set exception breakpoints separately for c++ and objective-c");
328fab10e89SJim Ingham           break;
329fab10e89SJim Ingham         case eLanguageTypeUnknown:
330b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
331b9c1b51eSKate Stone               "Unknown language type: '%s' for exception breakpoint",
332fe11483bSZachary Turner               option_arg.str().c_str());
333fab10e89SJim Ingham           break;
334fab10e89SJim Ingham         default:
335b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
336b9c1b51eSKate Stone               "Unsupported language type: '%s' for exception breakpoint",
337fe11483bSZachary Turner               option_arg.str().c_str());
338fab10e89SJim Ingham         }
339b9c1b51eSKate Stone       } break;
340ca36cd16SJim Ingham 
341ca36cd16SJim Ingham       case 'f':
3428f3be7a3SJonas Devlieghere         m_filenames.AppendIfUnique(FileSpec(option_arg));
343fab10e89SJim Ingham         break;
344ca36cd16SJim Ingham 
345ca36cd16SJim Ingham       case 'F':
346ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
347ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeFull;
348ca36cd16SJim Ingham         break;
349ca36cd16SJim Ingham 
350b9c1b51eSKate Stone       case 'h': {
351fab10e89SJim Ingham         bool success;
35247cbf4a0SPavel Labath         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
353fab10e89SJim Ingham         if (!success)
354b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
355fe11483bSZachary Turner               "Invalid boolean value for on-catch option: '%s'",
356fe11483bSZachary Turner               option_arg.str().c_str());
357b9c1b51eSKate Stone       } break;
358eb023e75SGreg Clayton 
359eb023e75SGreg Clayton       case 'H':
360eb023e75SGreg Clayton         m_hardware = true;
361eb023e75SGreg Clayton         break;
362eb023e75SGreg Clayton 
3633815e702SJim Ingham       case 'k': {
3643815e702SJim Ingham           if (m_current_key.empty())
3653815e702SJim Ingham             m_current_key.assign(option_arg);
3663815e702SJim Ingham           else
3673815e702SJim Ingham             error.SetErrorStringWithFormat("Key: %s missing value.",
3683815e702SJim Ingham                                             m_current_key.c_str());
3693815e702SJim Ingham 
3703815e702SJim Ingham       } break;
371b9c1b51eSKate Stone       case 'K': {
372a8558b62SJim Ingham         bool success;
373a8558b62SJim Ingham         bool value;
37447cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
375a8558b62SJim Ingham         if (value)
376a8558b62SJim Ingham           m_skip_prologue = eLazyBoolYes;
377a8558b62SJim Ingham         else
378a8558b62SJim Ingham           m_skip_prologue = eLazyBoolNo;
379a8558b62SJim Ingham 
380a8558b62SJim Ingham         if (!success)
381b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
382b9c1b51eSKate Stone               "Invalid boolean value for skip prologue option: '%s'",
383fe11483bSZachary Turner               option_arg.str().c_str());
384b9c1b51eSKate Stone       } break;
385ca36cd16SJim Ingham 
386fe11483bSZachary Turner       case 'l':
387fe11483bSZachary Turner         if (option_arg.getAsInteger(0, m_line_num))
388b9c1b51eSKate Stone           error.SetErrorStringWithFormat("invalid line number: %s.",
389fe11483bSZachary Turner                                          option_arg.str().c_str());
390ca36cd16SJim Ingham         break;
391055ad9beSIlia K 
39223b1decbSDawn Perchik       case 'L':
393fe11483bSZachary Turner         m_language = Language::GetLanguageTypeFromString(option_arg);
39423b1decbSDawn Perchik         if (m_language == eLanguageTypeUnknown)
395b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
396fe11483bSZachary Turner               "Unknown language type: '%s' for breakpoint",
397fe11483bSZachary Turner               option_arg.str().c_str());
39823b1decbSDawn Perchik         break;
39923b1decbSDawn Perchik 
400b9c1b51eSKate Stone       case 'm': {
401055ad9beSIlia K         bool success;
402055ad9beSIlia K         bool value;
40347cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, true, &success);
404055ad9beSIlia K         if (value)
405055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolYes;
406055ad9beSIlia K         else
407055ad9beSIlia K           m_move_to_nearest_code = eLazyBoolNo;
408055ad9beSIlia K 
409055ad9beSIlia K         if (!success)
410b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
411b9c1b51eSKate Stone               "Invalid boolean value for move-to-nearest-code option: '%s'",
412fe11483bSZachary Turner               option_arg.str().c_str());
413055ad9beSIlia K         break;
414055ad9beSIlia K       }
415055ad9beSIlia K 
416ca36cd16SJim Ingham       case 'M':
417ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
418ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeMethod;
419ca36cd16SJim Ingham         break;
420ca36cd16SJim Ingham 
421ca36cd16SJim Ingham       case 'n':
422ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
423ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeAuto;
424ca36cd16SJim Ingham         break;
425ca36cd16SJim Ingham 
4266fa7681bSZachary Turner       case 'N': {
427fe11483bSZachary Turner         if (BreakpointID::StringIsBreakpointName(option_arg, error))
4285e09c8c3SJim Ingham           m_breakpoint_names.push_back(option_arg);
429ff9a91eaSJim Ingham         else
430ff9a91eaSJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
431fe11483bSZachary Turner                                          option_arg.str().c_str());
4325e09c8c3SJim Ingham         break;
4336fa7681bSZachary Turner       }
4345e09c8c3SJim Ingham 
435b9c1b51eSKate Stone       case 'R': {
4362411167fSJim Ingham         lldb::addr_t tmp_offset_addr;
43747cbf4a0SPavel Labath         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
43847cbf4a0SPavel Labath                                                      option_arg, 0, &error);
4392411167fSJim Ingham         if (error.Success())
4402411167fSJim Ingham           m_offset_addr = tmp_offset_addr;
441b9c1b51eSKate Stone       } break;
4422411167fSJim Ingham 
443a72b31c7SJim Ingham       case 'O':
444fe11483bSZachary Turner         m_exception_extra_args.AppendArgument("-O");
445fe11483bSZachary Turner         m_exception_extra_args.AppendArgument(option_arg);
446a72b31c7SJim Ingham         break;
447a72b31c7SJim Ingham 
448ca36cd16SJim Ingham       case 'p':
449ca36cd16SJim Ingham         m_source_text_regexp.assign(option_arg);
450ca36cd16SJim Ingham         break;
451ca36cd16SJim Ingham 
4523815e702SJim Ingham       case 'P':
4533815e702SJim Ingham         m_python_class.assign(option_arg);
4543815e702SJim Ingham         break;
4553815e702SJim Ingham 
456ca36cd16SJim Ingham       case 'r':
457ca36cd16SJim Ingham         m_func_regexp.assign(option_arg);
458ca36cd16SJim Ingham         break;
459ca36cd16SJim Ingham 
460ca36cd16SJim Ingham       case 's':
4618f3be7a3SJonas Devlieghere         m_modules.AppendIfUnique(FileSpec(option_arg));
462ca36cd16SJim Ingham         break;
463ca36cd16SJim Ingham 
464ca36cd16SJim Ingham       case 'S':
465ca36cd16SJim Ingham         m_func_names.push_back(option_arg);
466ca36cd16SJim Ingham         m_func_name_type_mask |= eFunctionNameTypeSelector;
467ca36cd16SJim Ingham         break;
468ca36cd16SJim Ingham 
4693815e702SJim Ingham       case 'v': {
4703815e702SJim Ingham           if (!m_current_key.empty()) {
4713815e702SJim Ingham               m_extra_args_sp->AddStringItem(m_current_key, option_arg);
4723815e702SJim Ingham               m_current_key.clear();
4733815e702SJim Ingham           }
4743815e702SJim Ingham           else
4753815e702SJim Ingham             error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
4763815e702SJim Ingham                                            option_arg.str().c_str());
4773815e702SJim Ingham       } break;
4783815e702SJim Ingham 
479b9c1b51eSKate Stone       case 'w': {
480ca36cd16SJim Ingham         bool success;
48147cbf4a0SPavel Labath         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
482ca36cd16SJim Ingham         if (!success)
483b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
484fe11483bSZachary Turner               "Invalid boolean value for on-throw option: '%s'",
485fe11483bSZachary Turner               option_arg.str().c_str());
486b9c1b51eSKate Stone       } break;
487ca36cd16SJim Ingham 
48876bb8d67SJim Ingham       case 'X':
48976bb8d67SJim Ingham         m_source_regex_func_names.insert(option_arg);
49076bb8d67SJim Ingham         break;
49176bb8d67SJim Ingham 
49230fdc8d8SChris Lattner       default:
493b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
494b9c1b51eSKate Stone                                        short_option);
49530fdc8d8SChris Lattner         break;
49630fdc8d8SChris Lattner       }
49730fdc8d8SChris Lattner 
49830fdc8d8SChris Lattner       return error;
49930fdc8d8SChris Lattner     }
5009e85e5a8SEugene Zelenko 
501b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
50287df91b8SJim Ingham       m_filenames.Clear();
50330fdc8d8SChris Lattner       m_line_num = 0;
50430fdc8d8SChris Lattner       m_column = 0;
505fab10e89SJim Ingham       m_func_names.clear();
5061f746071SGreg Clayton       m_func_name_type_mask = eFunctionNameTypeNone;
50730fdc8d8SChris Lattner       m_func_regexp.clear();
5081f746071SGreg Clayton       m_source_text_regexp.clear();
50987df91b8SJim Ingham       m_modules.Clear();
5101f746071SGreg Clayton       m_load_addr = LLDB_INVALID_ADDRESS;
5112411167fSJim Ingham       m_offset_addr = 0;
512fab10e89SJim Ingham       m_catch_bp = false;
513fab10e89SJim Ingham       m_throw_bp = true;
514eb023e75SGreg Clayton       m_hardware = false;
515a72b31c7SJim Ingham       m_exception_language = eLanguageTypeUnknown;
51623b1decbSDawn Perchik       m_language = lldb::eLanguageTypeUnknown;
517a8558b62SJim Ingham       m_skip_prologue = eLazyBoolCalculate;
5185e09c8c3SJim Ingham       m_breakpoint_names.clear();
519e732052fSJim Ingham       m_all_files = false;
520a72b31c7SJim Ingham       m_exception_extra_args.Clear();
521055ad9beSIlia K       m_move_to_nearest_code = eLazyBoolCalculate;
52276bb8d67SJim Ingham       m_source_regex_func_names.clear();
5233815e702SJim Ingham       m_python_class.clear();
524796ac80bSJonas Devlieghere       m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
5253815e702SJim Ingham       m_current_key.clear();
52630fdc8d8SChris Lattner     }
52730fdc8d8SChris Lattner 
5281f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
52970602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_set_options);
5301f0f5b5bSZachary Turner     }
53130fdc8d8SChris Lattner 
5325a988416SJim Ingham     // Instance variables to hold the values for command options.
533969795f1SJim Ingham 
5345a988416SJim Ingham     std::string m_condition;
5355a988416SJim Ingham     FileSpecList m_filenames;
5365a988416SJim Ingham     uint32_t m_line_num;
5375a988416SJim Ingham     uint32_t m_column;
5385a988416SJim Ingham     std::vector<std::string> m_func_names;
5395e09c8c3SJim Ingham     std::vector<std::string> m_breakpoint_names;
540117b1fa1SZachary Turner     lldb::FunctionNameType m_func_name_type_mask;
5415a988416SJim Ingham     std::string m_func_regexp;
5425a988416SJim Ingham     std::string m_source_text_regexp;
5435a988416SJim Ingham     FileSpecList m_modules;
5445a988416SJim Ingham     lldb::addr_t m_load_addr;
5452411167fSJim Ingham     lldb::addr_t m_offset_addr;
5465a988416SJim Ingham     bool m_catch_bp;
5475a988416SJim Ingham     bool m_throw_bp;
548eb023e75SGreg Clayton     bool m_hardware; // Request to use hardware breakpoints
549a72b31c7SJim Ingham     lldb::LanguageType m_exception_language;
55023b1decbSDawn Perchik     lldb::LanguageType m_language;
5515a988416SJim Ingham     LazyBool m_skip_prologue;
552e732052fSJim Ingham     bool m_all_files;
553a72b31c7SJim Ingham     Args m_exception_extra_args;
554055ad9beSIlia K     LazyBool m_move_to_nearest_code;
55576bb8d67SJim Ingham     std::unordered_set<std::string> m_source_regex_func_names;
5563815e702SJim Ingham     std::string m_python_class;
5573815e702SJim Ingham     StructuredData::DictionarySP m_extra_args_sp;
5583815e702SJim Ingham     std::string m_current_key;
5595a988416SJim Ingham   };
5605a988416SJim Ingham 
5615a988416SJim Ingham protected:
562b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
563b842f2ecSJim Ingham     Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
56433df7cd3SJim Ingham 
565b9c1b51eSKate Stone     if (target == nullptr) {
566b9c1b51eSKate Stone       result.AppendError("Invalid target.  Must set target before setting "
567b9c1b51eSKate Stone                          "breakpoints (see 'target create' command).");
56830fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
56930fdc8d8SChris Lattner       return false;
57030fdc8d8SChris Lattner     }
57130fdc8d8SChris Lattner 
57230fdc8d8SChris Lattner     // The following are the various types of breakpoints that could be set:
57330fdc8d8SChris Lattner     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
57430fdc8d8SChris Lattner     //   2).  -a  [-s -g]         (setting breakpoint by address)
57530fdc8d8SChris Lattner     //   3).  -n  [-s -g]         (setting breakpoint by function name)
576b9c1b51eSKate Stone     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
577b9c1b51eSKate Stone     //   expression)
578b9c1b51eSKate Stone     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
579b9c1b51eSKate Stone     //   to source text)
580b9c1b51eSKate Stone     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
581b9c1b51eSKate Stone     //   given language.)
58230fdc8d8SChris Lattner 
58330fdc8d8SChris Lattner     BreakpointSetType break_type = eSetTypeInvalid;
58430fdc8d8SChris Lattner 
5853815e702SJim Ingham     if (!m_options.m_python_class.empty())
5863815e702SJim Ingham       break_type = eSetTypeScripted;
5873815e702SJim Ingham     else if (m_options.m_line_num != 0)
58830fdc8d8SChris Lattner       break_type = eSetTypeFileAndLine;
58930fdc8d8SChris Lattner     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
59030fdc8d8SChris Lattner       break_type = eSetTypeAddress;
591fab10e89SJim Ingham     else if (!m_options.m_func_names.empty())
59230fdc8d8SChris Lattner       break_type = eSetTypeFunctionName;
59330fdc8d8SChris Lattner     else if (!m_options.m_func_regexp.empty())
59430fdc8d8SChris Lattner       break_type = eSetTypeFunctionRegexp;
595969795f1SJim Ingham     else if (!m_options.m_source_text_regexp.empty())
596969795f1SJim Ingham       break_type = eSetTypeSourceRegexp;
597a72b31c7SJim Ingham     else if (m_options.m_exception_language != eLanguageTypeUnknown)
598fab10e89SJim Ingham       break_type = eSetTypeException;
59930fdc8d8SChris Lattner 
600b842f2ecSJim Ingham     BreakpointSP bp_sp = nullptr;
601274060b6SGreg Clayton     FileSpec module_spec;
602a8558b62SJim Ingham     const bool internal = false;
603a8558b62SJim Ingham 
604b9c1b51eSKate Stone     // If the user didn't specify skip-prologue, having an offset should turn
605b9c1b51eSKate Stone     // that off.
606b9c1b51eSKate Stone     if (m_options.m_offset_addr != 0 &&
607b9c1b51eSKate Stone         m_options.m_skip_prologue == eLazyBoolCalculate)
6082411167fSJim Ingham       m_options.m_skip_prologue = eLazyBoolNo;
6092411167fSJim Ingham 
610b9c1b51eSKate Stone     switch (break_type) {
61130fdc8d8SChris Lattner     case eSetTypeFileAndLine: // Breakpoint by source position
61230fdc8d8SChris Lattner     {
61330fdc8d8SChris Lattner       FileSpec file;
614c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
615b9c1b51eSKate Stone       if (num_files == 0) {
616b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
61787df91b8SJim Ingham           result.AppendError("No file supplied and no default file available.");
61887df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
61987df91b8SJim Ingham           return false;
62087df91b8SJim Ingham         }
621b9c1b51eSKate Stone       } else if (num_files > 1) {
622b9c1b51eSKate Stone         result.AppendError("Only one file at a time is allowed for file and "
623b9c1b51eSKate Stone                            "line breakpoints.");
62487df91b8SJim Ingham         result.SetStatus(eReturnStatusFailed);
62587df91b8SJim Ingham         return false;
626b9c1b51eSKate Stone       } else
62787df91b8SJim Ingham         file = m_options.m_filenames.GetFileSpecAtIndex(0);
62830fdc8d8SChris Lattner 
6291f746071SGreg Clayton       // Only check for inline functions if
6301f746071SGreg Clayton       LazyBool check_inlines = eLazyBoolCalculate;
6311f746071SGreg Clayton 
632b842f2ecSJim Ingham       bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
633b842f2ecSJim Ingham                                        file,
634b842f2ecSJim Ingham                                        m_options.m_line_num,
635431b1584SAdrian Prantl                                        m_options.m_column,
636b842f2ecSJim Ingham                                        m_options.m_offset_addr,
637b842f2ecSJim Ingham                                        check_inlines,
638b842f2ecSJim Ingham                                        m_options.m_skip_prologue,
639b842f2ecSJim Ingham                                        internal,
640b842f2ecSJim Ingham                                        m_options.m_hardware,
641b842f2ecSJim Ingham                                        m_options.m_move_to_nearest_code);
642b9c1b51eSKate Stone     } break;
6436eee5aa0SGreg Clayton 
64430fdc8d8SChris Lattner     case eSetTypeAddress: // Breakpoint by address
645055a08a4SJim Ingham     {
646b9c1b51eSKate Stone       // If a shared library has been specified, make an lldb_private::Address
647b842f2ecSJim Ingham       // with the library, and use that.  That way the address breakpoint
648b842f2ecSJim Ingham       //  will track the load location of the library.
649055a08a4SJim Ingham       size_t num_modules_specified = m_options.m_modules.GetSize();
650b9c1b51eSKate Stone       if (num_modules_specified == 1) {
651b9c1b51eSKate Stone         const FileSpec *file_spec =
652b9c1b51eSKate Stone             m_options.m_modules.GetFileSpecPointerAtIndex(0);
653b842f2ecSJim Ingham         bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
654b9c1b51eSKate Stone                                                         internal, file_spec,
655b842f2ecSJim Ingham                                                         m_options.m_hardware);
656b9c1b51eSKate Stone       } else if (num_modules_specified == 0) {
657b842f2ecSJim Ingham         bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
658b842f2ecSJim Ingham                                          m_options.m_hardware);
659b9c1b51eSKate Stone       } else {
660b9c1b51eSKate Stone         result.AppendError("Only one shared library can be specified for "
661b9c1b51eSKate Stone                            "address breakpoints.");
662055a08a4SJim Ingham         result.SetStatus(eReturnStatusFailed);
663055a08a4SJim Ingham         return false;
664055a08a4SJim Ingham       }
66530fdc8d8SChris Lattner       break;
666055a08a4SJim Ingham     }
66730fdc8d8SChris Lattner     case eSetTypeFunctionName: // Breakpoint by function name
6680c5cd90dSGreg Clayton     {
669117b1fa1SZachary Turner       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
6700c5cd90dSGreg Clayton 
6710c5cd90dSGreg Clayton       if (name_type_mask == 0)
672e02b8504SGreg Clayton         name_type_mask = eFunctionNameTypeAuto;
6730c5cd90dSGreg Clayton 
674b842f2ecSJim Ingham       bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
675b842f2ecSJim Ingham                                        &(m_options.m_filenames),
676b842f2ecSJim Ingham                                        m_options.m_func_names,
677b842f2ecSJim Ingham                                        name_type_mask,
678b842f2ecSJim Ingham                                        m_options.m_language,
679b842f2ecSJim Ingham                                        m_options.m_offset_addr,
680b842f2ecSJim Ingham                                        m_options.m_skip_prologue,
681b842f2ecSJim Ingham                                        internal,
682b842f2ecSJim Ingham                                        m_options.m_hardware);
683b9c1b51eSKate Stone     } break;
6840c5cd90dSGreg Clayton 
685b9c1b51eSKate Stone     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
686b9c1b51eSKate Stone                                  // name
68730fdc8d8SChris Lattner       {
68895eae423SZachary Turner         RegularExpression regexp(m_options.m_func_regexp);
689b9c1b51eSKate Stone         if (!regexp.IsValid()) {
690969795f1SJim Ingham           char err_str[1024];
691969795f1SJim Ingham           regexp.GetErrorAsCString(err_str, sizeof(err_str));
692b9c1b51eSKate Stone           result.AppendErrorWithFormat(
693b9c1b51eSKate Stone               "Function name regular expression could not be compiled: \"%s\"",
694969795f1SJim Ingham               err_str);
69530fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
696969795f1SJim Ingham           return false;
69730fdc8d8SChris Lattner         }
69887df91b8SJim Ingham 
699b842f2ecSJim Ingham         bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
700b842f2ecSJim Ingham                                                   &(m_options.m_filenames),
701b842f2ecSJim Ingham                                                   regexp,
702b842f2ecSJim Ingham                                                   m_options.m_language,
703b842f2ecSJim Ingham                                                   m_options.m_skip_prologue,
704b842f2ecSJim Ingham                                                   internal,
705b842f2ecSJim Ingham                                                   m_options.m_hardware);
706e14dc268SJim Ingham       }
707e14dc268SJim Ingham       break;
708969795f1SJim Ingham     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
709969795f1SJim Ingham     {
710c7bece56SGreg Clayton       const size_t num_files = m_options.m_filenames.GetSize();
71187df91b8SJim Ingham 
712b9c1b51eSKate Stone       if (num_files == 0 && !m_options.m_all_files) {
713969795f1SJim Ingham         FileSpec file;
714b9c1b51eSKate Stone         if (!GetDefaultFile(target, file, result)) {
715b9c1b51eSKate Stone           result.AppendError(
716b9c1b51eSKate Stone               "No files provided and could not find default file.");
71787df91b8SJim Ingham           result.SetStatus(eReturnStatusFailed);
71887df91b8SJim Ingham           return false;
719b9c1b51eSKate Stone         } else {
72087df91b8SJim Ingham           m_options.m_filenames.Append(file);
72187df91b8SJim Ingham         }
72287df91b8SJim Ingham       }
7230c5cd90dSGreg Clayton 
72495eae423SZachary Turner       RegularExpression regexp(m_options.m_source_text_regexp);
725b9c1b51eSKate Stone       if (!regexp.IsValid()) {
726969795f1SJim Ingham         char err_str[1024];
727969795f1SJim Ingham         regexp.GetErrorAsCString(err_str, sizeof(err_str));
728b9c1b51eSKate Stone         result.AppendErrorWithFormat(
729b9c1b51eSKate Stone             "Source text regular expression could not be compiled: \"%s\"",
730969795f1SJim Ingham             err_str);
731969795f1SJim Ingham         result.SetStatus(eReturnStatusFailed);
732969795f1SJim Ingham         return false;
733969795f1SJim Ingham       }
734b842f2ecSJim Ingham       bp_sp =
735b842f2ecSJim Ingham           target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
736b842f2ecSJim Ingham                                               &(m_options.m_filenames),
737b842f2ecSJim Ingham                                               m_options
738b842f2ecSJim Ingham                                                   .m_source_regex_func_names,
739b842f2ecSJim Ingham                                               regexp,
740b842f2ecSJim Ingham                                               internal,
741b842f2ecSJim Ingham                                               m_options.m_hardware,
742b842f2ecSJim Ingham                                               m_options.m_move_to_nearest_code);
743b9c1b51eSKate Stone     } break;
744b9c1b51eSKate Stone     case eSetTypeException: {
74597206d57SZachary Turner       Status precond_error;
746b842f2ecSJim Ingham       bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
747b842f2ecSJim Ingham                                                 m_options.m_catch_bp,
748b842f2ecSJim Ingham                                                 m_options.m_throw_bp,
749b842f2ecSJim Ingham                                                 internal,
750b842f2ecSJim Ingham                                                 &m_options
751b842f2ecSJim Ingham                                                     .m_exception_extra_args,
752b842f2ecSJim Ingham                                                 &precond_error);
753b9c1b51eSKate Stone       if (precond_error.Fail()) {
754b9c1b51eSKate Stone         result.AppendErrorWithFormat(
755b9c1b51eSKate Stone             "Error setting extra exception arguments: %s",
756a72b31c7SJim Ingham             precond_error.AsCString());
757b842f2ecSJim Ingham         target->RemoveBreakpointByID(bp_sp->GetID());
758a72b31c7SJim Ingham         result.SetStatus(eReturnStatusFailed);
759a72b31c7SJim Ingham         return false;
760a72b31c7SJim Ingham       }
761b9c1b51eSKate Stone     } break;
7623815e702SJim Ingham     case eSetTypeScripted: {
7633815e702SJim Ingham 
7643815e702SJim Ingham       Status error;
7653815e702SJim Ingham       bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
7663815e702SJim Ingham                                                &(m_options.m_modules),
7673815e702SJim Ingham                                                &(m_options.m_filenames),
7683815e702SJim Ingham                                                false,
7693815e702SJim Ingham                                                m_options.m_hardware,
7703815e702SJim Ingham                                                m_options.m_extra_args_sp,
7713815e702SJim Ingham                                                &error);
7723815e702SJim Ingham       if (error.Fail()) {
7733815e702SJim Ingham         result.AppendErrorWithFormat(
7743815e702SJim Ingham             "Error setting extra exception arguments: %s",
7753815e702SJim Ingham             error.AsCString());
7763815e702SJim Ingham         target->RemoveBreakpointByID(bp_sp->GetID());
7773815e702SJim Ingham         result.SetStatus(eReturnStatusFailed);
7783815e702SJim Ingham         return false;
7793815e702SJim Ingham       }
7803815e702SJim Ingham     } break;
78130fdc8d8SChris Lattner     default:
78230fdc8d8SChris Lattner       break;
78330fdc8d8SChris Lattner     }
78430fdc8d8SChris Lattner 
7851b54c88cSJim Ingham     // Now set the various options that were passed in:
786b842f2ecSJim Ingham     if (bp_sp) {
787b842f2ecSJim Ingham       bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
788ca36cd16SJim Ingham 
789b9c1b51eSKate Stone       if (!m_options.m_breakpoint_names.empty()) {
79097206d57SZachary Turner         Status name_error;
791ff9a91eaSJim Ingham         for (auto name : m_options.m_breakpoint_names) {
792b842f2ecSJim Ingham           target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
793ff9a91eaSJim Ingham           if (name_error.Fail()) {
794ff9a91eaSJim Ingham             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
795ff9a91eaSJim Ingham                                          name.c_str());
796b842f2ecSJim Ingham             target->RemoveBreakpointByID(bp_sp->GetID());
797ff9a91eaSJim Ingham             result.SetStatus(eReturnStatusFailed);
798ff9a91eaSJim Ingham             return false;
799ff9a91eaSJim Ingham           }
800ff9a91eaSJim Ingham         }
8015e09c8c3SJim Ingham       }
8021b54c88cSJim Ingham     }
8031b54c88cSJim Ingham 
804b842f2ecSJim Ingham     if (bp_sp) {
80585e8b814SJim Ingham       Stream &output_stream = result.GetOutputStream();
8061391cc7dSJim Ingham       const bool show_locations = false;
807b842f2ecSJim Ingham       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
808b9c1b51eSKate Stone                          show_locations);
80957179860SJonas Devlieghere       if (target == GetDebugger().GetDummyTarget())
810b9c1b51eSKate Stone         output_stream.Printf("Breakpoint set in dummy target, will get copied "
811b9c1b51eSKate Stone                              "into future targets.\n");
812b9c1b51eSKate Stone       else {
81305097246SAdrian Prantl         // Don't print out this warning for exception breakpoints.  They can
81405097246SAdrian Prantl         // get set before the target is set, but we won't know how to actually
81505097246SAdrian Prantl         // set the breakpoint till we run.
816b842f2ecSJim Ingham         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
817b9c1b51eSKate Stone           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
818b9c1b51eSKate Stone                                "actual locations.\n");
8194aeb1989SJim Ingham         }
8204aeb1989SJim Ingham       }
82130fdc8d8SChris Lattner       result.SetStatus(eReturnStatusSuccessFinishResult);
822b842f2ecSJim Ingham     } else if (!bp_sp) {
82330fdc8d8SChris Lattner       result.AppendError("Breakpoint creation failed: No breakpoint created.");
82430fdc8d8SChris Lattner       result.SetStatus(eReturnStatusFailed);
82530fdc8d8SChris Lattner     }
82630fdc8d8SChris Lattner 
82730fdc8d8SChris Lattner     return result.Succeeded();
82830fdc8d8SChris Lattner   }
82930fdc8d8SChris Lattner 
8305a988416SJim Ingham private:
831b9c1b51eSKate Stone   bool GetDefaultFile(Target *target, FileSpec &file,
832b9c1b51eSKate Stone                       CommandReturnObject &result) {
8335a988416SJim Ingham     uint32_t default_line;
83405097246SAdrian Prantl     // First use the Source Manager's default file. Then use the current stack
83505097246SAdrian Prantl     // frame's file.
836b9c1b51eSKate Stone     if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
837b57e4a1bSJason Molenda       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
838b9c1b51eSKate Stone       if (cur_frame == nullptr) {
839b9c1b51eSKate Stone         result.AppendError(
840b9c1b51eSKate Stone             "No selected frame to use to find the default file.");
8415a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
8425a988416SJim Ingham         return false;
843b9c1b51eSKate Stone       } else if (!cur_frame->HasDebugInformation()) {
844b9c1b51eSKate Stone         result.AppendError("Cannot use the selected frame to find the default "
845b9c1b51eSKate Stone                            "file, it has no debug info.");
8465a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
8475a988416SJim Ingham         return false;
848b9c1b51eSKate Stone       } else {
849b9c1b51eSKate Stone         const SymbolContext &sc =
850b9c1b51eSKate Stone             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
851b9c1b51eSKate Stone         if (sc.line_entry.file) {
8525a988416SJim Ingham           file = sc.line_entry.file;
853b9c1b51eSKate Stone         } else {
854b9c1b51eSKate Stone           result.AppendError("Can't find the file for the selected frame to "
855b9c1b51eSKate Stone                              "use as the default file.");
8565a988416SJim Ingham           result.SetStatus(eReturnStatusFailed);
8575a988416SJim Ingham           return false;
8585a988416SJim Ingham         }
8595a988416SJim Ingham       }
8605a988416SJim Ingham     }
8615a988416SJim Ingham     return true;
8625a988416SJim Ingham   }
8635a988416SJim Ingham 
864b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
865b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_options;
8665a988416SJim Ingham   CommandOptions m_options;
867b842f2ecSJim Ingham   OptionGroupOptions m_all_options;
8685a988416SJim Ingham };
8699e85e5a8SEugene Zelenko 
8705a988416SJim Ingham // CommandObjectBreakpointModify
8715a988416SJim Ingham #pragma mark Modify
8725a988416SJim Ingham 
873b9c1b51eSKate Stone class CommandObjectBreakpointModify : public CommandObjectParsed {
8745a988416SJim Ingham public:
875b9c1b51eSKate Stone   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
876b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint modify",
877b9c1b51eSKate Stone                             "Modify the options on a breakpoint or set of "
878b9c1b51eSKate Stone                             "breakpoints in the executable.  "
879b9c1b51eSKate Stone                             "If no breakpoint is specified, acts on the last "
880b9c1b51eSKate Stone                             "created breakpoint.  "
881b9c1b51eSKate Stone                             "With the exception of -e, -d and -i, passing an "
882b9c1b51eSKate Stone                             "empty argument clears the modification.",
8839e85e5a8SEugene Zelenko                             nullptr),
884b9c1b51eSKate Stone         m_options() {
8855a988416SJim Ingham     CommandArgumentEntry arg;
886b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
887b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
888b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
889b9c1b51eSKate Stone     // arguments vector.
8905a988416SJim Ingham     m_arguments.push_back(arg);
891b842f2ecSJim Ingham 
892b842f2ecSJim Ingham     m_options.Append(&m_bp_opts,
893b842f2ecSJim Ingham                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
894b842f2ecSJim Ingham                      LLDB_OPT_SET_ALL);
895b842f2ecSJim Ingham     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
896b842f2ecSJim Ingham     m_options.Finalize();
8975a988416SJim Ingham   }
8985a988416SJim Ingham 
8999e85e5a8SEugene Zelenko   ~CommandObjectBreakpointModify() override = default;
9005a988416SJim Ingham 
901b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
9025a988416SJim Ingham 
9035a988416SJim Ingham protected:
904b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
905b842f2ecSJim Ingham     Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
906b9c1b51eSKate Stone     if (target == nullptr) {
9075a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
9085a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9095a988416SJim Ingham       return false;
9105a988416SJim Ingham     }
9115a988416SJim Ingham 
912bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
913bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
9145a988416SJim Ingham 
9155a988416SJim Ingham     BreakpointIDList valid_bp_ids;
9165a988416SJim Ingham 
917b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
918b842f2ecSJim Ingham         command, target, result, &valid_bp_ids,
919b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::disablePerm);
9205a988416SJim Ingham 
921b9c1b51eSKate Stone     if (result.Succeeded()) {
9225a988416SJim Ingham       const size_t count = valid_bp_ids.GetSize();
923b9c1b51eSKate Stone       for (size_t i = 0; i < count; ++i) {
9245a988416SJim Ingham         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
9255a988416SJim Ingham 
926b9c1b51eSKate Stone         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
927b9c1b51eSKate Stone           Breakpoint *bp =
928b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
929b9c1b51eSKate Stone           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
930b9c1b51eSKate Stone             BreakpointLocation *location =
931b9c1b51eSKate Stone                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
932b842f2ecSJim Ingham             if (location)
933b842f2ecSJim Ingham               location->GetLocationOptions()
934b842f2ecSJim Ingham                   ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
935b9c1b51eSKate Stone           } else {
936b842f2ecSJim Ingham             bp->GetOptions()
937b842f2ecSJim Ingham                 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
9385a988416SJim Ingham           }
9395a988416SJim Ingham         }
9405a988416SJim Ingham       }
9415a988416SJim Ingham     }
9425a988416SJim Ingham 
9435a988416SJim Ingham     return result.Succeeded();
9445a988416SJim Ingham   }
9455a988416SJim Ingham 
9465a988416SJim Ingham private:
947b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
948b842f2ecSJim Ingham   BreakpointDummyOptionGroup m_dummy_opts;
949b842f2ecSJim Ingham   OptionGroupOptions m_options;
9505a988416SJim Ingham };
9515a988416SJim Ingham 
9525a988416SJim Ingham // CommandObjectBreakpointEnable
9535a988416SJim Ingham #pragma mark Enable
9545a988416SJim Ingham 
955b9c1b51eSKate Stone class CommandObjectBreakpointEnable : public CommandObjectParsed {
9565a988416SJim Ingham public:
957b9c1b51eSKate Stone   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
958b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "enable",
959b9c1b51eSKate Stone                             "Enable the specified disabled breakpoint(s). If "
960b9c1b51eSKate Stone                             "no breakpoints are specified, enable all of them.",
961b9c1b51eSKate Stone                             nullptr) {
9625a988416SJim Ingham     CommandArgumentEntry arg;
963b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
964b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
965b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
966b9c1b51eSKate Stone     // arguments vector.
9675a988416SJim Ingham     m_arguments.push_back(arg);
9685a988416SJim Ingham   }
9695a988416SJim Ingham 
9709e85e5a8SEugene Zelenko   ~CommandObjectBreakpointEnable() override = default;
9715a988416SJim Ingham 
9725a988416SJim Ingham protected:
973b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
974893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
975b9c1b51eSKate Stone     if (target == nullptr) {
9765a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
9775a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9785a988416SJim Ingham       return false;
9795a988416SJim Ingham     }
9805a988416SJim Ingham 
981bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
982bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
9835a988416SJim Ingham 
9845a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
9855a988416SJim Ingham 
9865a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
9875a988416SJim Ingham 
988b9c1b51eSKate Stone     if (num_breakpoints == 0) {
9895a988416SJim Ingham       result.AppendError("No breakpoints exist to be enabled.");
9905a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
9915a988416SJim Ingham       return false;
9925a988416SJim Ingham     }
9935a988416SJim Ingham 
99411eb9c64SZachary Turner     if (command.empty()) {
9955a988416SJim Ingham       // No breakpoint selected; enable all currently set breakpoints.
996b842f2ecSJim Ingham       target->EnableAllowedBreakpoints();
997b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
998b9c1b51eSKate Stone                                      " breakpoints)\n",
999b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
10005a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1001b9c1b51eSKate Stone     } else {
10025a988416SJim Ingham       // Particular breakpoint selected; enable that breakpoint.
10035a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1004b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1005b842f2ecSJim Ingham           command, target, result, &valid_bp_ids,
1006b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
10075a988416SJim Ingham 
1008b9c1b51eSKate Stone       if (result.Succeeded()) {
10095a988416SJim Ingham         int enable_count = 0;
10105a988416SJim Ingham         int loc_count = 0;
10115a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1012b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
10135a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
10145a988416SJim Ingham 
1015b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1016b9c1b51eSKate Stone             Breakpoint *breakpoint =
1017b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1018b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1019b9c1b51eSKate Stone               BreakpointLocation *location =
1020b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1021b9c1b51eSKate Stone               if (location) {
10225a988416SJim Ingham                 location->SetEnabled(true);
10235a988416SJim Ingham                 ++loc_count;
10245a988416SJim Ingham               }
1025b9c1b51eSKate Stone             } else {
10265a988416SJim Ingham               breakpoint->SetEnabled(true);
10275a988416SJim Ingham               ++enable_count;
10285a988416SJim Ingham             }
10295a988416SJim Ingham           }
10305a988416SJim Ingham         }
1031b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1032b9c1b51eSKate Stone                                        enable_count + loc_count);
10335a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10345a988416SJim Ingham       }
10355a988416SJim Ingham     }
10365a988416SJim Ingham 
10375a988416SJim Ingham     return result.Succeeded();
10385a988416SJim Ingham   }
10395a988416SJim Ingham };
10405a988416SJim Ingham 
10415a988416SJim Ingham // CommandObjectBreakpointDisable
10425a988416SJim Ingham #pragma mark Disable
10435a988416SJim Ingham 
1044b9c1b51eSKate Stone class CommandObjectBreakpointDisable : public CommandObjectParsed {
10455a988416SJim Ingham public:
10467428a18cSKate Stone   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1047b9c1b51eSKate Stone       : CommandObjectParsed(
1048b9c1b51eSKate Stone             interpreter, "breakpoint disable",
1049b9c1b51eSKate Stone             "Disable the specified breakpoint(s) without deleting "
10507428a18cSKate Stone             "them.  If none are specified, disable all "
10517428a18cSKate Stone             "breakpoints.",
1052b9c1b51eSKate Stone             nullptr) {
1053b9c1b51eSKate Stone     SetHelpLong(
1054b9c1b51eSKate Stone         "Disable the specified breakpoint(s) without deleting them.  \
10557428a18cSKate Stone If none are specified, disable all breakpoints."
10567428a18cSKate Stone         R"(
1057ea671fbdSKate Stone 
10587428a18cSKate Stone )"
10597428a18cSKate Stone         "Note: disabling a breakpoint will cause none of its locations to be hit \
10607428a18cSKate Stone regardless of whether individual locations are enabled or disabled.  After the sequence:"
10617428a18cSKate Stone         R"(
1062ea671fbdSKate Stone 
1063ea671fbdSKate Stone     (lldb) break disable 1
1064ea671fbdSKate Stone     (lldb) break enable 1.1
1065ea671fbdSKate Stone 
1066ea671fbdSKate Stone execution will NOT stop at location 1.1.  To achieve that, type:
1067ea671fbdSKate Stone 
1068ea671fbdSKate Stone     (lldb) break disable 1.*
1069ea671fbdSKate Stone     (lldb) break enable 1.1
1070ea671fbdSKate Stone 
10717428a18cSKate Stone )"
10727428a18cSKate Stone         "The first command disables all locations for breakpoint 1, \
10737428a18cSKate Stone the second re-enables the first location.");
1074b0fac509SJim Ingham 
10755a988416SJim Ingham     CommandArgumentEntry arg;
1076b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1077b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1078b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1079b9c1b51eSKate Stone     // arguments vector.
10805a988416SJim Ingham     m_arguments.push_back(arg);
10815a988416SJim Ingham   }
10825a988416SJim Ingham 
10839e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDisable() override = default;
10845a988416SJim Ingham 
10855a988416SJim Ingham protected:
1086b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1087893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1088b9c1b51eSKate Stone     if (target == nullptr) {
10895a988416SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
10905a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
10915a988416SJim Ingham       return false;
10925a988416SJim Ingham     }
10935a988416SJim Ingham 
1094bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1095bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
10965a988416SJim Ingham 
10975a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
10985a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
10995a988416SJim Ingham 
1100b9c1b51eSKate Stone     if (num_breakpoints == 0) {
11015a988416SJim Ingham       result.AppendError("No breakpoints exist to be disabled.");
11025a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
11035a988416SJim Ingham       return false;
11045a988416SJim Ingham     }
11055a988416SJim Ingham 
110611eb9c64SZachary Turner     if (command.empty()) {
11075a988416SJim Ingham       // No breakpoint selected; disable all currently set breakpoints.
1108b842f2ecSJim Ingham       target->DisableAllowedBreakpoints();
1109b9c1b51eSKate Stone       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1110b9c1b51eSKate Stone                                      " breakpoints)\n",
1111b9c1b51eSKate Stone                                      (uint64_t)num_breakpoints);
11125a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1113b9c1b51eSKate Stone     } else {
11145a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
11155a988416SJim Ingham       BreakpointIDList valid_bp_ids;
11165a988416SJim Ingham 
1117b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1118b842f2ecSJim Ingham           command, target, result, &valid_bp_ids,
1119b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::disablePerm);
11205a988416SJim Ingham 
1121b9c1b51eSKate Stone       if (result.Succeeded()) {
11225a988416SJim Ingham         int disable_count = 0;
11235a988416SJim Ingham         int loc_count = 0;
11245a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1125b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
11265a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
11275a988416SJim Ingham 
1128b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1129b9c1b51eSKate Stone             Breakpoint *breakpoint =
1130b9c1b51eSKate Stone                 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1131b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1132b9c1b51eSKate Stone               BreakpointLocation *location =
1133b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1134b9c1b51eSKate Stone               if (location) {
11355a988416SJim Ingham                 location->SetEnabled(false);
11365a988416SJim Ingham                 ++loc_count;
11375a988416SJim Ingham               }
1138b9c1b51eSKate Stone             } else {
11395a988416SJim Ingham               breakpoint->SetEnabled(false);
11405a988416SJim Ingham               ++disable_count;
11415a988416SJim Ingham             }
11425a988416SJim Ingham           }
11435a988416SJim Ingham         }
1144b9c1b51eSKate Stone         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1145b9c1b51eSKate Stone                                        disable_count + loc_count);
11465a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
11475a988416SJim Ingham       }
11485a988416SJim Ingham     }
11495a988416SJim Ingham 
11505a988416SJim Ingham     return result.Succeeded();
11515a988416SJim Ingham   }
11525a988416SJim Ingham };
11535a988416SJim Ingham 
11545a988416SJim Ingham // CommandObjectBreakpointList
11551f0f5b5bSZachary Turner 
11561f0f5b5bSZachary Turner #pragma mark List::CommandOptions
11578fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_list_options[] = {
11586f4fb4e7SRaphael Isemann #define LLDB_OPTIONS_breakpoint_list
1159c5a2d747SRaphael Isemann #include "CommandOptions.inc"
11601f0f5b5bSZachary Turner };
11611f0f5b5bSZachary Turner 
11625a988416SJim Ingham #pragma mark List
11635a988416SJim Ingham 
1164b9c1b51eSKate Stone class CommandObjectBreakpointList : public CommandObjectParsed {
11655a988416SJim Ingham public:
1166b9c1b51eSKate Stone   CommandObjectBreakpointList(CommandInterpreter &interpreter)
1167b9c1b51eSKate Stone       : CommandObjectParsed(
1168b9c1b51eSKate Stone             interpreter, "breakpoint list",
11695a988416SJim Ingham             "List some or all breakpoints at configurable levels of detail.",
11709e85e5a8SEugene Zelenko             nullptr),
1171b9c1b51eSKate Stone         m_options() {
11725a988416SJim Ingham     CommandArgumentEntry arg;
11735a988416SJim Ingham     CommandArgumentData bp_id_arg;
11745a988416SJim Ingham 
11755a988416SJim Ingham     // Define the first (and only) variant of this arg.
11765a988416SJim Ingham     bp_id_arg.arg_type = eArgTypeBreakpointID;
11775a988416SJim Ingham     bp_id_arg.arg_repetition = eArgRepeatOptional;
11785a988416SJim Ingham 
1179b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1180b9c1b51eSKate Stone     // argument entry.
11815a988416SJim Ingham     arg.push_back(bp_id_arg);
11825a988416SJim Ingham 
11835a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
11845a988416SJim Ingham     m_arguments.push_back(arg);
11855a988416SJim Ingham   }
11865a988416SJim Ingham 
11879e85e5a8SEugene Zelenko   ~CommandObjectBreakpointList() override = default;
11885a988416SJim Ingham 
1189b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
11905a988416SJim Ingham 
1191b9c1b51eSKate Stone   class CommandOptions : public Options {
11925a988416SJim Ingham   public:
1193b9c1b51eSKate Stone     CommandOptions()
1194b9c1b51eSKate Stone         : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
11955a988416SJim Ingham     }
11965a988416SJim Ingham 
11979e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
11985a988416SJim Ingham 
119997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1200b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
120197206d57SZachary Turner       Status error;
12023bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12035a988416SJim Ingham 
1204b9c1b51eSKate Stone       switch (short_option) {
12055a988416SJim Ingham       case 'b':
12065a988416SJim Ingham         m_level = lldb::eDescriptionLevelBrief;
12075a988416SJim Ingham         break;
120833df7cd3SJim Ingham       case 'D':
120933df7cd3SJim Ingham         m_use_dummy = true;
121033df7cd3SJim Ingham         break;
12115a988416SJim Ingham       case 'f':
12125a988416SJim Ingham         m_level = lldb::eDescriptionLevelFull;
12135a988416SJim Ingham         break;
12145a988416SJim Ingham       case 'v':
12155a988416SJim Ingham         m_level = lldb::eDescriptionLevelVerbose;
12165a988416SJim Ingham         break;
12175a988416SJim Ingham       case 'i':
12185a988416SJim Ingham         m_internal = true;
12195a988416SJim Ingham         break;
12205a988416SJim Ingham       default:
1221b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1222b9c1b51eSKate Stone                                        short_option);
12235a988416SJim Ingham         break;
12245a988416SJim Ingham       }
12255a988416SJim Ingham 
12265a988416SJim Ingham       return error;
12275a988416SJim Ingham     }
12285a988416SJim Ingham 
1229b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
12305a988416SJim Ingham       m_level = lldb::eDescriptionLevelFull;
12315a988416SJim Ingham       m_internal = false;
123233df7cd3SJim Ingham       m_use_dummy = false;
12335a988416SJim Ingham     }
12345a988416SJim Ingham 
12351f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
123670602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_list_options);
12371f0f5b5bSZachary Turner     }
12385a988416SJim Ingham 
12395a988416SJim Ingham     // Instance variables to hold the values for command options.
12405a988416SJim Ingham 
12415a988416SJim Ingham     lldb::DescriptionLevel m_level;
12425a988416SJim Ingham 
12435a988416SJim Ingham     bool m_internal;
124433df7cd3SJim Ingham     bool m_use_dummy;
12455a988416SJim Ingham   };
12465a988416SJim Ingham 
12475a988416SJim Ingham protected:
1248b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
124933df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
125033df7cd3SJim Ingham 
1251b9c1b51eSKate Stone     if (target == nullptr) {
12525a988416SJim Ingham       result.AppendError("Invalid target. No current target or breakpoints.");
12535a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
12545a988416SJim Ingham       return true;
12555a988416SJim Ingham     }
12565a988416SJim Ingham 
1257b9c1b51eSKate Stone     const BreakpointList &breakpoints =
1258b9c1b51eSKate Stone         target->GetBreakpointList(m_options.m_internal);
1259bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1260bb19a13cSSaleem Abdulrasool     target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
12615a988416SJim Ingham 
12625a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
12635a988416SJim Ingham 
1264b9c1b51eSKate Stone     if (num_breakpoints == 0) {
12655a988416SJim Ingham       result.AppendMessage("No breakpoints currently set.");
12665a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
12675a988416SJim Ingham       return true;
12685a988416SJim Ingham     }
12695a988416SJim Ingham 
12705a988416SJim Ingham     Stream &output_stream = result.GetOutputStream();
12715a988416SJim Ingham 
127211eb9c64SZachary Turner     if (command.empty()) {
12735a988416SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
12745a988416SJim Ingham       result.AppendMessage("Current breakpoints:");
1275b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
12765a988416SJim Ingham         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1277b842f2ecSJim Ingham         if (breakpoint->AllowList())
1278b842f2ecSJim Ingham           AddBreakpointDescription(&output_stream, breakpoint,
1279b842f2ecSJim Ingham                                    m_options.m_level);
12805a988416SJim Ingham       }
12815a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1282b9c1b51eSKate Stone     } else {
12835a988416SJim Ingham       // Particular breakpoints selected; show info about that breakpoint.
12845a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1285b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1286b842f2ecSJim Ingham           command, target, result, &valid_bp_ids,
1287b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
12885a988416SJim Ingham 
1289b9c1b51eSKate Stone       if (result.Succeeded()) {
1290b9c1b51eSKate Stone         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
12915a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1292b9c1b51eSKate Stone           Breakpoint *breakpoint =
1293b9c1b51eSKate Stone               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1294b9c1b51eSKate Stone           AddBreakpointDescription(&output_stream, breakpoint,
1295b9c1b51eSKate Stone                                    m_options.m_level);
12965a988416SJim Ingham         }
12975a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1298b9c1b51eSKate Stone       } else {
12997428a18cSKate Stone         result.AppendError("Invalid breakpoint ID.");
13005a988416SJim Ingham         result.SetStatus(eReturnStatusFailed);
13015a988416SJim Ingham       }
13025a988416SJim Ingham     }
13035a988416SJim Ingham 
13045a988416SJim Ingham     return result.Succeeded();
13055a988416SJim Ingham   }
13065a988416SJim Ingham 
13075a988416SJim Ingham private:
13085a988416SJim Ingham   CommandOptions m_options;
13095a988416SJim Ingham };
13105a988416SJim Ingham 
13115a988416SJim Ingham // CommandObjectBreakpointClear
13121f0f5b5bSZachary Turner #pragma mark Clear::CommandOptions
13131f0f5b5bSZachary Turner 
13148fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_clear_options[] = {
1315*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_clear
1316*f94668e3SRaphael Isemann #include "CommandOptions.inc"
13171f0f5b5bSZachary Turner };
13181f0f5b5bSZachary Turner 
13195a988416SJim Ingham #pragma mark Clear
13205a988416SJim Ingham 
1321b9c1b51eSKate Stone class CommandObjectBreakpointClear : public CommandObjectParsed {
13225a988416SJim Ingham public:
1323efe8e7e3SFangrui Song   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
13245a988416SJim Ingham 
13257428a18cSKate Stone   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
13267428a18cSKate Stone       : CommandObjectParsed(interpreter, "breakpoint clear",
1327b9c1b51eSKate Stone                             "Delete or disable breakpoints matching the "
1328b9c1b51eSKate Stone                             "specified source file and line.",
13295a988416SJim Ingham                             "breakpoint clear <cmd-options>"),
1330b9c1b51eSKate Stone         m_options() {}
13315a988416SJim Ingham 
13329e85e5a8SEugene Zelenko   ~CommandObjectBreakpointClear() override = default;
13335a988416SJim Ingham 
1334b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
13355a988416SJim Ingham 
1336b9c1b51eSKate Stone   class CommandOptions : public Options {
13375a988416SJim Ingham   public:
1338b9c1b51eSKate Stone     CommandOptions() : Options(), m_filename(), m_line_num(0) {}
13395a988416SJim Ingham 
13409e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
13415a988416SJim Ingham 
134297206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1343b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
134497206d57SZachary Turner       Status error;
13453bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
13465a988416SJim Ingham 
1347b9c1b51eSKate Stone       switch (short_option) {
13485a988416SJim Ingham       case 'f':
13495a988416SJim Ingham         m_filename.assign(option_arg);
13505a988416SJim Ingham         break;
13515a988416SJim Ingham 
13525a988416SJim Ingham       case 'l':
1353fe11483bSZachary Turner         option_arg.getAsInteger(0, m_line_num);
13545a988416SJim Ingham         break;
13555a988416SJim Ingham 
13565a988416SJim Ingham       default:
1357b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1358b9c1b51eSKate Stone                                        short_option);
13595a988416SJim Ingham         break;
13605a988416SJim Ingham       }
13615a988416SJim Ingham 
13625a988416SJim Ingham       return error;
13635a988416SJim Ingham     }
13645a988416SJim Ingham 
1365b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
13665a988416SJim Ingham       m_filename.clear();
13675a988416SJim Ingham       m_line_num = 0;
13685a988416SJim Ingham     }
13695a988416SJim Ingham 
13701f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
137170602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_clear_options);
13721f0f5b5bSZachary Turner     }
13735a988416SJim Ingham 
13745a988416SJim Ingham     // Instance variables to hold the values for command options.
13755a988416SJim Ingham 
13765a988416SJim Ingham     std::string m_filename;
13775a988416SJim Ingham     uint32_t m_line_num;
13785a988416SJim Ingham   };
13795a988416SJim Ingham 
13805a988416SJim Ingham protected:
1381b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1382893c932aSJim Ingham     Target *target = GetSelectedOrDummyTarget();
1383b9c1b51eSKate Stone     if (target == nullptr) {
13845a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
13855a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
13865a988416SJim Ingham       return false;
13875a988416SJim Ingham     }
13885a988416SJim Ingham 
138905097246SAdrian Prantl     // The following are the various types of breakpoints that could be
139005097246SAdrian Prantl     // cleared:
13915a988416SJim Ingham     //   1). -f -l (clearing breakpoint by source location)
13925a988416SJim Ingham 
13935a988416SJim Ingham     BreakpointClearType break_type = eClearTypeInvalid;
13945a988416SJim Ingham 
13955a988416SJim Ingham     if (m_options.m_line_num != 0)
13965a988416SJim Ingham       break_type = eClearTypeFileAndLine;
13975a988416SJim Ingham 
1398bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1399bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
14005a988416SJim Ingham 
14015a988416SJim Ingham     BreakpointList &breakpoints = target->GetBreakpointList();
14025a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
14035a988416SJim Ingham 
14045a988416SJim Ingham     // Early return if there's no breakpoint at all.
1405b9c1b51eSKate Stone     if (num_breakpoints == 0) {
14065a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
14075a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14085a988416SJim Ingham       return result.Succeeded();
14095a988416SJim Ingham     }
14105a988416SJim Ingham 
14115a988416SJim Ingham     // Find matching breakpoints and delete them.
14125a988416SJim Ingham 
14135a988416SJim Ingham     // First create a copy of all the IDs.
14145a988416SJim Ingham     std::vector<break_id_t> BreakIDs;
14155a988416SJim Ingham     for (size_t i = 0; i < num_breakpoints; ++i)
14169e85e5a8SEugene Zelenko       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
14175a988416SJim Ingham 
14185a988416SJim Ingham     int num_cleared = 0;
14195a988416SJim Ingham     StreamString ss;
1420b9c1b51eSKate Stone     switch (break_type) {
14215a988416SJim Ingham     case eClearTypeFileAndLine: // Breakpoint by source position
14225a988416SJim Ingham     {
14235a988416SJim Ingham       const ConstString filename(m_options.m_filename.c_str());
14245a988416SJim Ingham       BreakpointLocationCollection loc_coll;
14255a988416SJim Ingham 
1426b9c1b51eSKate Stone       for (size_t i = 0; i < num_breakpoints; ++i) {
14275a988416SJim Ingham         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
14285a988416SJim Ingham 
1429b9c1b51eSKate Stone         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1430b9c1b51eSKate Stone           // If the collection size is 0, it's a full match and we can just
1431b9c1b51eSKate Stone           // remove the breakpoint.
1432b9c1b51eSKate Stone           if (loc_coll.GetSize() == 0) {
14335a988416SJim Ingham             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
14345a988416SJim Ingham             ss.EOL();
14355a988416SJim Ingham             target->RemoveBreakpointByID(bp->GetID());
14365a988416SJim Ingham             ++num_cleared;
14375a988416SJim Ingham           }
14385a988416SJim Ingham         }
14395a988416SJim Ingham       }
1440b9c1b51eSKate Stone     } break;
14415a988416SJim Ingham 
14425a988416SJim Ingham     default:
14435a988416SJim Ingham       break;
14445a988416SJim Ingham     }
14455a988416SJim Ingham 
1446b9c1b51eSKate Stone     if (num_cleared > 0) {
14475a988416SJim Ingham       Stream &output_stream = result.GetOutputStream();
14485a988416SJim Ingham       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1449c156427dSZachary Turner       output_stream << ss.GetString();
14505a988416SJim Ingham       output_stream.EOL();
14515a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1452b9c1b51eSKate Stone     } else {
14535a988416SJim Ingham       result.AppendError("Breakpoint clear: No breakpoint cleared.");
14545a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
14555a988416SJim Ingham     }
14565a988416SJim Ingham 
14575a988416SJim Ingham     return result.Succeeded();
14585a988416SJim Ingham   }
14595a988416SJim Ingham 
14605a988416SJim Ingham private:
14615a988416SJim Ingham   CommandOptions m_options;
14625a988416SJim Ingham };
14635a988416SJim Ingham 
14645a988416SJim Ingham // CommandObjectBreakpointDelete
14658fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_delete_options[] = {
1466*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_delete
1467*f94668e3SRaphael Isemann #include "CommandOptions.inc"
14681f0f5b5bSZachary Turner };
14691f0f5b5bSZachary Turner 
14705a988416SJim Ingham #pragma mark Delete
14715a988416SJim Ingham 
1472b9c1b51eSKate Stone class CommandObjectBreakpointDelete : public CommandObjectParsed {
14735a988416SJim Ingham public:
1474b9c1b51eSKate Stone   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1475b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "breakpoint delete",
1476b9c1b51eSKate Stone                             "Delete the specified breakpoint(s).  If no "
1477b9c1b51eSKate Stone                             "breakpoints are specified, delete them all.",
14789e85e5a8SEugene Zelenko                             nullptr),
1479b9c1b51eSKate Stone         m_options() {
14805a988416SJim Ingham     CommandArgumentEntry arg;
1481b9c1b51eSKate Stone     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1482b9c1b51eSKate Stone                                       eArgTypeBreakpointIDRange);
1483b9c1b51eSKate Stone     // Add the entry for the first argument for this command to the object's
1484b9c1b51eSKate Stone     // arguments vector.
14855a988416SJim Ingham     m_arguments.push_back(arg);
14865a988416SJim Ingham   }
14875a988416SJim Ingham 
14889e85e5a8SEugene Zelenko   ~CommandObjectBreakpointDelete() override = default;
14895a988416SJim Ingham 
1490b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
149133df7cd3SJim Ingham 
1492b9c1b51eSKate Stone   class CommandOptions : public Options {
149333df7cd3SJim Ingham   public:
1494b9c1b51eSKate Stone     CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
149533df7cd3SJim Ingham 
14969e85e5a8SEugene Zelenko     ~CommandOptions() override = default;
149733df7cd3SJim Ingham 
149897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1499b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
150097206d57SZachary Turner       Status error;
150133df7cd3SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
150233df7cd3SJim Ingham 
1503b9c1b51eSKate Stone       switch (short_option) {
150433df7cd3SJim Ingham       case 'f':
150533df7cd3SJim Ingham         m_force = true;
150633df7cd3SJim Ingham         break;
150733df7cd3SJim Ingham 
150833df7cd3SJim Ingham       case 'D':
150933df7cd3SJim Ingham         m_use_dummy = true;
151033df7cd3SJim Ingham         break;
151133df7cd3SJim Ingham 
151233df7cd3SJim Ingham       default:
1513b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1514b9c1b51eSKate Stone                                        short_option);
151533df7cd3SJim Ingham         break;
151633df7cd3SJim Ingham       }
151733df7cd3SJim Ingham 
151833df7cd3SJim Ingham       return error;
151933df7cd3SJim Ingham     }
152033df7cd3SJim Ingham 
1521b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
152233df7cd3SJim Ingham       m_use_dummy = false;
152333df7cd3SJim Ingham       m_force = false;
152433df7cd3SJim Ingham     }
152533df7cd3SJim Ingham 
15261f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
152770602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_delete_options);
15281f0f5b5bSZachary Turner     }
152933df7cd3SJim Ingham 
153033df7cd3SJim Ingham     // Instance variables to hold the values for command options.
153133df7cd3SJim Ingham     bool m_use_dummy;
153233df7cd3SJim Ingham     bool m_force;
153333df7cd3SJim Ingham   };
153433df7cd3SJim Ingham 
15355a988416SJim Ingham protected:
1536b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
153733df7cd3SJim Ingham     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
153833df7cd3SJim Ingham 
1539b9c1b51eSKate Stone     if (target == nullptr) {
15405a988416SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
15415a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15425a988416SJim Ingham       return false;
15435a988416SJim Ingham     }
15445a988416SJim Ingham 
1545bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1546bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
15475a988416SJim Ingham 
15485a988416SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
15495a988416SJim Ingham 
15505a988416SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
15515a988416SJim Ingham 
1552b9c1b51eSKate Stone     if (num_breakpoints == 0) {
15535a988416SJim Ingham       result.AppendError("No breakpoints exist to be deleted.");
15545a988416SJim Ingham       result.SetStatus(eReturnStatusFailed);
15555a988416SJim Ingham       return false;
15565a988416SJim Ingham     }
15575a988416SJim Ingham 
155811eb9c64SZachary Turner     if (command.empty()) {
1559b9c1b51eSKate Stone       if (!m_options.m_force &&
1560b9c1b51eSKate Stone           !m_interpreter.Confirm(
1561b9c1b51eSKate Stone               "About to delete all breakpoints, do you want to do that?",
1562b9c1b51eSKate Stone               true)) {
15635a988416SJim Ingham         result.AppendMessage("Operation cancelled...");
1564b9c1b51eSKate Stone       } else {
1565b842f2ecSJim Ingham         target->RemoveAllowedBreakpoints();
1566b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1567b9c1b51eSKate Stone             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1568b9c1b51eSKate Stone             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
15695a988416SJim Ingham       }
15705a988416SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1571b9c1b51eSKate Stone     } else {
15725a988416SJim Ingham       // Particular breakpoint selected; disable that breakpoint.
15735a988416SJim Ingham       BreakpointIDList valid_bp_ids;
1574b9c1b51eSKate Stone       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1575b842f2ecSJim Ingham           command, target, result, &valid_bp_ids,
1576b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::deletePerm);
15775a988416SJim Ingham 
1578b9c1b51eSKate Stone       if (result.Succeeded()) {
15795a988416SJim Ingham         int delete_count = 0;
15805a988416SJim Ingham         int disable_count = 0;
15815a988416SJim Ingham         const size_t count = valid_bp_ids.GetSize();
1582b9c1b51eSKate Stone         for (size_t i = 0; i < count; ++i) {
15835a988416SJim Ingham           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
15845a988416SJim Ingham 
1585b9c1b51eSKate Stone           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1586b9c1b51eSKate Stone             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1587b9c1b51eSKate Stone               Breakpoint *breakpoint =
1588b9c1b51eSKate Stone                   target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1589b9c1b51eSKate Stone               BreakpointLocation *location =
1590b9c1b51eSKate Stone                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1591b9c1b51eSKate Stone               // It makes no sense to try to delete individual locations, so we
1592b9c1b51eSKate Stone               // disable them instead.
1593b9c1b51eSKate Stone               if (location) {
15945a988416SJim Ingham                 location->SetEnabled(false);
15955a988416SJim Ingham                 ++disable_count;
15965a988416SJim Ingham               }
1597b9c1b51eSKate Stone             } else {
15985a988416SJim Ingham               target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
15995a988416SJim Ingham               ++delete_count;
16005a988416SJim Ingham             }
16015a988416SJim Ingham           }
16025a988416SJim Ingham         }
1603b9c1b51eSKate Stone         result.AppendMessageWithFormat(
1604b9c1b51eSKate Stone             "%d breakpoints deleted; %d breakpoint locations disabled.\n",
16055a988416SJim Ingham             delete_count, disable_count);
16065a988416SJim Ingham         result.SetStatus(eReturnStatusSuccessFinishNoResult);
16075a988416SJim Ingham       }
16085a988416SJim Ingham     }
16095a988416SJim Ingham     return result.Succeeded();
16105a988416SJim Ingham   }
16119e85e5a8SEugene Zelenko 
161233df7cd3SJim Ingham private:
161333df7cd3SJim Ingham   CommandOptions m_options;
161433df7cd3SJim Ingham };
161533df7cd3SJim Ingham 
16165e09c8c3SJim Ingham // CommandObjectBreakpointName
16175e09c8c3SJim Ingham 
16188fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_name_options[] = {
1619*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_name
1620*f94668e3SRaphael Isemann #include "CommandOptions.inc"
16215e09c8c3SJim Ingham };
1622b9c1b51eSKate Stone class BreakpointNameOptionGroup : public OptionGroup {
16235e09c8c3SJim Ingham public:
1624b9c1b51eSKate Stone   BreakpointNameOptionGroup()
1625b9c1b51eSKate Stone       : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
16265e09c8c3SJim Ingham   }
16275e09c8c3SJim Ingham 
16289e85e5a8SEugene Zelenko   ~BreakpointNameOptionGroup() override = default;
16295e09c8c3SJim Ingham 
16301f0f5b5bSZachary Turner   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
163170602439SZachary Turner     return llvm::makeArrayRef(g_breakpoint_name_options);
16325e09c8c3SJim Ingham   }
16335e09c8c3SJim Ingham 
163497206d57SZachary Turner   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1635b9c1b51eSKate Stone                         ExecutionContext *execution_context) override {
163697206d57SZachary Turner     Status error;
16375e09c8c3SJim Ingham     const int short_option = g_breakpoint_name_options[option_idx].short_option;
16385e09c8c3SJim Ingham 
1639b9c1b51eSKate Stone     switch (short_option) {
16405e09c8c3SJim Ingham     case 'N':
1641fe11483bSZachary Turner       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1642b9c1b51eSKate Stone           error.Success())
1643fe11483bSZachary Turner         m_name.SetValueFromString(option_arg);
16445e09c8c3SJim Ingham       break;
16455e09c8c3SJim Ingham     case 'B':
1646fe11483bSZachary Turner       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1647b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
16488cef4b0bSZachary Turner             "unrecognized value \"%s\" for breakpoint",
1649fe11483bSZachary Turner             option_arg.str().c_str());
16505e09c8c3SJim Ingham       break;
16515e09c8c3SJim Ingham     case 'D':
1652fe11483bSZachary Turner       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1653b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
16548cef4b0bSZachary Turner             "unrecognized value \"%s\" for use-dummy",
1655fe11483bSZachary Turner             option_arg.str().c_str());
16565e09c8c3SJim Ingham       break;
1657e9632ebaSJim Ingham     case 'H':
1658e9632ebaSJim Ingham       m_help_string.SetValueFromString(option_arg);
1659e9632ebaSJim Ingham       break;
16605e09c8c3SJim Ingham 
16615e09c8c3SJim Ingham     default:
1662b9c1b51eSKate Stone       error.SetErrorStringWithFormat("unrecognized short option '%c'",
1663b9c1b51eSKate Stone                                      short_option);
16645e09c8c3SJim Ingham       break;
16655e09c8c3SJim Ingham     }
16665e09c8c3SJim Ingham     return error;
16675e09c8c3SJim Ingham   }
16685e09c8c3SJim Ingham 
1669b9c1b51eSKate Stone   void OptionParsingStarting(ExecutionContext *execution_context) override {
16705e09c8c3SJim Ingham     m_name.Clear();
16715e09c8c3SJim Ingham     m_breakpoint.Clear();
16725e09c8c3SJim Ingham     m_use_dummy.Clear();
16735e09c8c3SJim Ingham     m_use_dummy.SetDefaultValue(false);
1674e9632ebaSJim Ingham     m_help_string.Clear();
16755e09c8c3SJim Ingham   }
16765e09c8c3SJim Ingham 
16775e09c8c3SJim Ingham   OptionValueString m_name;
16785e09c8c3SJim Ingham   OptionValueUInt64 m_breakpoint;
16795e09c8c3SJim Ingham   OptionValueBoolean m_use_dummy;
1680e9632ebaSJim Ingham   OptionValueString m_help_string;
16815e09c8c3SJim Ingham };
16825e09c8c3SJim Ingham 
16838fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_access_options[] = {
1684*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_access
1685*f94668e3SRaphael Isemann #include "CommandOptions.inc"
1686b842f2ecSJim Ingham };
1687b842f2ecSJim Ingham 
16888fe53c49STatyana Krasnukha class BreakpointAccessOptionGroup : public OptionGroup {
1689b842f2ecSJim Ingham public:
16908fe53c49STatyana Krasnukha   BreakpointAccessOptionGroup() : OptionGroup() {}
1691b842f2ecSJim Ingham 
1692b842f2ecSJim Ingham   ~BreakpointAccessOptionGroup() override = default;
1693b842f2ecSJim Ingham 
1694b842f2ecSJim Ingham   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1695b842f2ecSJim Ingham     return llvm::makeArrayRef(g_breakpoint_access_options);
1696b842f2ecSJim Ingham   }
1697b842f2ecSJim Ingham   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1698b842f2ecSJim Ingham                         ExecutionContext *execution_context) override {
1699b842f2ecSJim Ingham     Status error;
1700b842f2ecSJim Ingham     const int short_option
1701b842f2ecSJim Ingham         = g_breakpoint_access_options[option_idx].short_option;
1702b842f2ecSJim Ingham 
1703b842f2ecSJim Ingham     switch (short_option) {
1704b842f2ecSJim Ingham       case 'L': {
1705b842f2ecSJim Ingham         bool value, success;
170647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1707b842f2ecSJim Ingham         if (success) {
1708b842f2ecSJim Ingham           m_permissions.SetAllowList(value);
1709b842f2ecSJim Ingham         } else
1710b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1711b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1712b842f2ecSJim Ingham               option_arg.str().c_str());
1713b842f2ecSJim Ingham       } break;
1714b842f2ecSJim Ingham       case 'A': {
1715b842f2ecSJim Ingham         bool value, success;
171647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1717b842f2ecSJim Ingham         if (success) {
1718b842f2ecSJim Ingham           m_permissions.SetAllowDisable(value);
1719b842f2ecSJim Ingham         } else
1720b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1721b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1722b842f2ecSJim Ingham               option_arg.str().c_str());
1723b842f2ecSJim Ingham       } break;
1724b842f2ecSJim Ingham       case 'D': {
1725b842f2ecSJim Ingham         bool value, success;
172647cbf4a0SPavel Labath         value = OptionArgParser::ToBoolean(option_arg, false, &success);
1727b842f2ecSJim Ingham         if (success) {
1728b842f2ecSJim Ingham           m_permissions.SetAllowDelete(value);
1729b842f2ecSJim Ingham         } else
1730b842f2ecSJim Ingham           error.SetErrorStringWithFormat(
1731b842f2ecSJim Ingham               "invalid boolean value '%s' passed for -L option",
1732b842f2ecSJim Ingham               option_arg.str().c_str());
1733b842f2ecSJim Ingham       } break;
1734b842f2ecSJim Ingham 
1735b842f2ecSJim Ingham     }
1736b842f2ecSJim Ingham 
1737b842f2ecSJim Ingham     return error;
1738b842f2ecSJim Ingham   }
1739b842f2ecSJim Ingham 
1740b842f2ecSJim Ingham   void OptionParsingStarting(ExecutionContext *execution_context) override {
1741b842f2ecSJim Ingham   }
1742b842f2ecSJim Ingham 
1743b842f2ecSJim Ingham   const BreakpointName::Permissions &GetPermissions() const
1744b842f2ecSJim Ingham   {
1745b842f2ecSJim Ingham     return m_permissions;
1746b842f2ecSJim Ingham   }
1747b842f2ecSJim Ingham   BreakpointName::Permissions m_permissions;
1748b842f2ecSJim Ingham };
1749b842f2ecSJim Ingham 
1750b842f2ecSJim Ingham class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1751b842f2ecSJim Ingham public:
1752b842f2ecSJim Ingham   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1753b842f2ecSJim Ingham       : CommandObjectParsed(
1754b842f2ecSJim Ingham             interpreter, "configure", "Configure the options for the breakpoint"
1755b842f2ecSJim Ingham             " name provided.  "
1756b842f2ecSJim Ingham             "If you provide a breakpoint id, the options will be copied from "
1757b842f2ecSJim Ingham             "the breakpoint, otherwise only the options specified will be set "
1758b842f2ecSJim Ingham             "on the name.",
1759b842f2ecSJim Ingham             "breakpoint name configure <command-options> "
1760b842f2ecSJim Ingham             "<breakpoint-name-list>"),
1761b842f2ecSJim Ingham         m_bp_opts(), m_option_group() {
1762b842f2ecSJim Ingham     // Create the first variant for the first (and only) argument for this
1763b842f2ecSJim Ingham     // command.
1764b842f2ecSJim Ingham     CommandArgumentEntry arg1;
1765b842f2ecSJim Ingham     CommandArgumentData id_arg;
1766b842f2ecSJim Ingham     id_arg.arg_type = eArgTypeBreakpointName;
1767b842f2ecSJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
1768b842f2ecSJim Ingham     arg1.push_back(id_arg);
1769b842f2ecSJim Ingham     m_arguments.push_back(arg1);
1770b842f2ecSJim Ingham 
1771b842f2ecSJim Ingham     m_option_group.Append(&m_bp_opts,
1772b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1773b842f2ecSJim Ingham                           LLDB_OPT_SET_1);
1774b842f2ecSJim Ingham     m_option_group.Append(&m_access_options,
1775b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL,
1776b842f2ecSJim Ingham                           LLDB_OPT_SET_ALL);
1777e9632ebaSJim Ingham     m_option_group.Append(&m_bp_id,
1778e9632ebaSJim Ingham                           LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1779e9632ebaSJim Ingham                           LLDB_OPT_SET_ALL);
1780b842f2ecSJim Ingham     m_option_group.Finalize();
1781b842f2ecSJim Ingham   }
1782b842f2ecSJim Ingham 
1783b842f2ecSJim Ingham   ~CommandObjectBreakpointNameConfigure() override = default;
1784b842f2ecSJim Ingham 
1785b842f2ecSJim Ingham   Options *GetOptions() override { return &m_option_group; }
1786b842f2ecSJim Ingham 
1787b842f2ecSJim Ingham protected:
1788b842f2ecSJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
1789b842f2ecSJim Ingham 
1790b842f2ecSJim Ingham     const size_t argc = command.GetArgumentCount();
1791b842f2ecSJim Ingham     if (argc == 0) {
1792b842f2ecSJim Ingham       result.AppendError("No names provided.");
1793b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1794b842f2ecSJim Ingham       return false;
1795b842f2ecSJim Ingham     }
1796b842f2ecSJim Ingham 
1797b842f2ecSJim Ingham     Target *target =
1798b842f2ecSJim Ingham         GetSelectedOrDummyTarget(false);
1799b842f2ecSJim Ingham 
1800b842f2ecSJim Ingham     if (target == nullptr) {
1801b842f2ecSJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
1802b842f2ecSJim Ingham       result.SetStatus(eReturnStatusFailed);
1803b842f2ecSJim Ingham       return false;
1804b842f2ecSJim Ingham     }
1805b842f2ecSJim Ingham 
1806b842f2ecSJim Ingham     std::unique_lock<std::recursive_mutex> lock;
1807b842f2ecSJim Ingham     target->GetBreakpointList().GetListMutex(lock);
1808b842f2ecSJim Ingham 
1809b842f2ecSJim Ingham     // Make a pass through first to see that all the names are legal.
1810b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1811b842f2ecSJim Ingham       Status error;
1812b842f2ecSJim Ingham       if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1813b842f2ecSJim Ingham       {
1814b842f2ecSJim Ingham         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1815b842f2ecSJim Ingham                                      entry.c_str(), error.AsCString());
1816b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1817b842f2ecSJim Ingham         return false;
1818b842f2ecSJim Ingham       }
1819b842f2ecSJim Ingham     }
182005097246SAdrian Prantl     // Now configure them, we already pre-checked the names so we don't need to
182105097246SAdrian Prantl     // check the error:
1822b842f2ecSJim Ingham     BreakpointSP bp_sp;
1823b842f2ecSJim Ingham     if (m_bp_id.m_breakpoint.OptionWasSet())
1824b842f2ecSJim Ingham     {
1825b842f2ecSJim Ingham       lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1826b842f2ecSJim Ingham       bp_sp = target->GetBreakpointByID(bp_id);
1827b842f2ecSJim Ingham       if (!bp_sp)
1828b842f2ecSJim Ingham       {
1829b842f2ecSJim Ingham         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1830b842f2ecSJim Ingham                            bp_id);
1831b842f2ecSJim Ingham         result.SetStatus(eReturnStatusFailed);
1832b842f2ecSJim Ingham         return false;
1833b842f2ecSJim Ingham       }
1834b842f2ecSJim Ingham     }
1835b842f2ecSJim Ingham 
1836b842f2ecSJim Ingham     Status error;
1837b842f2ecSJim Ingham     for (auto &entry : command.entries()) {
1838b842f2ecSJim Ingham       ConstString name(entry.c_str());
1839b842f2ecSJim Ingham       BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1840b842f2ecSJim Ingham       if (!bp_name)
1841b842f2ecSJim Ingham         continue;
1842e9632ebaSJim Ingham       if (m_bp_id.m_help_string.OptionWasSet())
1843e9632ebaSJim Ingham         bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1844e9632ebaSJim Ingham 
1845b842f2ecSJim Ingham       if (bp_sp)
1846b842f2ecSJim Ingham         target->ConfigureBreakpointName(*bp_name,
1847b842f2ecSJim Ingham                                        *bp_sp->GetOptions(),
1848b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1849b842f2ecSJim Ingham       else
1850b842f2ecSJim Ingham         target->ConfigureBreakpointName(*bp_name,
1851b842f2ecSJim Ingham                                        m_bp_opts.GetBreakpointOptions(),
1852b842f2ecSJim Ingham                                        m_access_options.GetPermissions());
1853b842f2ecSJim Ingham     }
1854b842f2ecSJim Ingham     return true;
1855b842f2ecSJim Ingham   }
1856b842f2ecSJim Ingham 
1857b842f2ecSJim Ingham private:
1858b842f2ecSJim Ingham   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1859b842f2ecSJim Ingham   BreakpointOptionGroup m_bp_opts;
1860b842f2ecSJim Ingham   BreakpointAccessOptionGroup m_access_options;
1861b842f2ecSJim Ingham   OptionGroupOptions m_option_group;
1862b842f2ecSJim Ingham };
1863b842f2ecSJim Ingham 
1864b9c1b51eSKate Stone class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
18655e09c8c3SJim Ingham public:
1866b9c1b51eSKate Stone   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1867b9c1b51eSKate Stone       : CommandObjectParsed(
1868b9c1b51eSKate Stone             interpreter, "add", "Add a name to the breakpoints provided.",
18695e09c8c3SJim Ingham             "breakpoint name add <command-options> <breakpoint-id-list>"),
1870b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1871b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1872b9c1b51eSKate Stone     // command.
18735e09c8c3SJim Ingham     CommandArgumentEntry arg1;
18745e09c8c3SJim Ingham     CommandArgumentData id_arg;
18755e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
18765e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
18775e09c8c3SJim Ingham     arg1.push_back(id_arg);
18785e09c8c3SJim Ingham     m_arguments.push_back(arg1);
18795e09c8c3SJim Ingham 
18805e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
18815e09c8c3SJim Ingham     m_option_group.Finalize();
18825e09c8c3SJim Ingham   }
18835e09c8c3SJim Ingham 
18849e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameAdd() override = default;
18855e09c8c3SJim Ingham 
1886b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
18875e09c8c3SJim Ingham 
18885e09c8c3SJim Ingham protected:
1889b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1890b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
18915e09c8c3SJim Ingham       result.SetError("No name option provided.");
18925e09c8c3SJim Ingham       return false;
18935e09c8c3SJim Ingham     }
18945e09c8c3SJim Ingham 
1895b9c1b51eSKate Stone     Target *target =
1896b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
18975e09c8c3SJim Ingham 
1898b9c1b51eSKate Stone     if (target == nullptr) {
18995e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
19005e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19015e09c8c3SJim Ingham       return false;
19025e09c8c3SJim Ingham     }
19035e09c8c3SJim Ingham 
1904bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1905bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
19065e09c8c3SJim Ingham 
19075e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
19085e09c8c3SJim Ingham 
19095e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1910b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19115e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot add names.");
19125e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19135e09c8c3SJim Ingham       return false;
19145e09c8c3SJim Ingham     }
19155e09c8c3SJim Ingham 
19165e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
19175e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
1918b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1919b842f2ecSJim Ingham         command, target, result, &valid_bp_ids,
1920b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::listPerm);
19215e09c8c3SJim Ingham 
1922b9c1b51eSKate Stone     if (result.Succeeded()) {
1923b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
19245e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot add names.");
19255e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
19265e09c8c3SJim Ingham         return false;
19275e09c8c3SJim Ingham       }
19285e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
1929b842f2ecSJim Ingham       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1930b842f2ecSJim Ingham       Status error; // This error reports illegal names, but we've already
1931b842f2ecSJim Ingham                     // checked that, so we don't need to check it again here.
1932b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
1933b9c1b51eSKate Stone         lldb::break_id_t bp_id =
1934b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
19355e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1936b842f2ecSJim Ingham         target->AddNameToBreakpoint(bp_sp, bp_name, error);
19375e09c8c3SJim Ingham       }
19385e09c8c3SJim Ingham     }
19395e09c8c3SJim Ingham 
19405e09c8c3SJim Ingham     return true;
19415e09c8c3SJim Ingham   }
19425e09c8c3SJim Ingham 
19435e09c8c3SJim Ingham private:
19445e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
19455e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
19465e09c8c3SJim Ingham };
19475e09c8c3SJim Ingham 
1948b9c1b51eSKate Stone class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
19495e09c8c3SJim Ingham public:
1950b9c1b51eSKate Stone   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1951b9c1b51eSKate Stone       : CommandObjectParsed(
1952b9c1b51eSKate Stone             interpreter, "delete",
19535e09c8c3SJim Ingham             "Delete a name from the breakpoints provided.",
19545e09c8c3SJim Ingham             "breakpoint name delete <command-options> <breakpoint-id-list>"),
1955b9c1b51eSKate Stone         m_name_options(), m_option_group() {
1956b9c1b51eSKate Stone     // Create the first variant for the first (and only) argument for this
1957b9c1b51eSKate Stone     // command.
19585e09c8c3SJim Ingham     CommandArgumentEntry arg1;
19595e09c8c3SJim Ingham     CommandArgumentData id_arg;
19605e09c8c3SJim Ingham     id_arg.arg_type = eArgTypeBreakpointID;
19615e09c8c3SJim Ingham     id_arg.arg_repetition = eArgRepeatOptional;
19625e09c8c3SJim Ingham     arg1.push_back(id_arg);
19635e09c8c3SJim Ingham     m_arguments.push_back(arg1);
19645e09c8c3SJim Ingham 
19655e09c8c3SJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
19665e09c8c3SJim Ingham     m_option_group.Finalize();
19675e09c8c3SJim Ingham   }
19685e09c8c3SJim Ingham 
19699e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameDelete() override = default;
19705e09c8c3SJim Ingham 
1971b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
19725e09c8c3SJim Ingham 
19735e09c8c3SJim Ingham protected:
1974b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1975b9c1b51eSKate Stone     if (!m_name_options.m_name.OptionWasSet()) {
19765e09c8c3SJim Ingham       result.SetError("No name option provided.");
19775e09c8c3SJim Ingham       return false;
19785e09c8c3SJim Ingham     }
19795e09c8c3SJim Ingham 
1980b9c1b51eSKate Stone     Target *target =
1981b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
19825e09c8c3SJim Ingham 
1983b9c1b51eSKate Stone     if (target == nullptr) {
19845e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
19855e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19865e09c8c3SJim Ingham       return false;
19875e09c8c3SJim Ingham     }
19885e09c8c3SJim Ingham 
1989bb19a13cSSaleem Abdulrasool     std::unique_lock<std::recursive_mutex> lock;
1990bb19a13cSSaleem Abdulrasool     target->GetBreakpointList().GetListMutex(lock);
19915e09c8c3SJim Ingham 
19925e09c8c3SJim Ingham     const BreakpointList &breakpoints = target->GetBreakpointList();
19935e09c8c3SJim Ingham 
19945e09c8c3SJim Ingham     size_t num_breakpoints = breakpoints.GetSize();
1995b9c1b51eSKate Stone     if (num_breakpoints == 0) {
19965e09c8c3SJim Ingham       result.SetError("No breakpoints, cannot delete names.");
19975e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
19985e09c8c3SJim Ingham       return false;
19995e09c8c3SJim Ingham     }
20005e09c8c3SJim Ingham 
20015e09c8c3SJim Ingham     // Particular breakpoint selected; disable that breakpoint.
20025e09c8c3SJim Ingham     BreakpointIDList valid_bp_ids;
2003b9c1b51eSKate Stone     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2004b842f2ecSJim Ingham         command, target, result, &valid_bp_ids,
2005b842f2ecSJim Ingham         BreakpointName::Permissions::PermissionKinds::deletePerm);
20065e09c8c3SJim Ingham 
2007b9c1b51eSKate Stone     if (result.Succeeded()) {
2008b9c1b51eSKate Stone       if (valid_bp_ids.GetSize() == 0) {
20095e09c8c3SJim Ingham         result.SetError("No breakpoints specified, cannot delete names.");
20105e09c8c3SJim Ingham         result.SetStatus(eReturnStatusFailed);
20115e09c8c3SJim Ingham         return false;
20125e09c8c3SJim Ingham       }
2013b842f2ecSJim Ingham       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
20145e09c8c3SJim Ingham       size_t num_valid_ids = valid_bp_ids.GetSize();
2015b9c1b51eSKate Stone       for (size_t index = 0; index < num_valid_ids; index++) {
2016b9c1b51eSKate Stone         lldb::break_id_t bp_id =
2017b9c1b51eSKate Stone             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
20185e09c8c3SJim Ingham         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2019b842f2ecSJim Ingham         target->RemoveNameFromBreakpoint(bp_sp, bp_name);
20205e09c8c3SJim Ingham       }
20215e09c8c3SJim Ingham     }
20225e09c8c3SJim Ingham 
20235e09c8c3SJim Ingham     return true;
20245e09c8c3SJim Ingham   }
20255e09c8c3SJim Ingham 
20265e09c8c3SJim Ingham private:
20275e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
20285e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
20295e09c8c3SJim Ingham };
20305e09c8c3SJim Ingham 
2031b9c1b51eSKate Stone class CommandObjectBreakpointNameList : public CommandObjectParsed {
20325e09c8c3SJim Ingham public:
2033b9c1b51eSKate Stone   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2034b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "list",
2035b842f2ecSJim Ingham                             "List either the names for a breakpoint or info "
2036b842f2ecSJim Ingham                             "about a given name.  With no arguments, lists all "
2037b842f2ecSJim Ingham                             "names",
20385e09c8c3SJim Ingham                             "breakpoint name list <command-options>"),
2039b9c1b51eSKate Stone         m_name_options(), m_option_group() {
2040b842f2ecSJim Ingham     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
20415e09c8c3SJim Ingham     m_option_group.Finalize();
20425e09c8c3SJim Ingham   }
20435e09c8c3SJim Ingham 
20449e85e5a8SEugene Zelenko   ~CommandObjectBreakpointNameList() override = default;
20455e09c8c3SJim Ingham 
2046b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
20475e09c8c3SJim Ingham 
20485e09c8c3SJim Ingham protected:
2049b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
2050b9c1b51eSKate Stone     Target *target =
2051b9c1b51eSKate Stone         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
20525e09c8c3SJim Ingham 
2053b9c1b51eSKate Stone     if (target == nullptr) {
20545e09c8c3SJim Ingham       result.AppendError("Invalid target. No existing target or breakpoints.");
20555e09c8c3SJim Ingham       result.SetStatus(eReturnStatusFailed);
20565e09c8c3SJim Ingham       return false;
20575e09c8c3SJim Ingham     }
20585e09c8c3SJim Ingham 
2059b842f2ecSJim Ingham 
2060b842f2ecSJim Ingham     std::vector<std::string> name_list;
2061b842f2ecSJim Ingham     if (command.empty()) {
2062b842f2ecSJim Ingham       target->GetBreakpointNames(name_list);
2063b842f2ecSJim Ingham     } else {
2064b842f2ecSJim Ingham       for (const Args::ArgEntry &arg : command)
2065b842f2ecSJim Ingham       {
2066b842f2ecSJim Ingham         name_list.push_back(arg.c_str());
2067b842f2ecSJim Ingham       }
2068b842f2ecSJim Ingham     }
2069b842f2ecSJim Ingham 
2070b842f2ecSJim Ingham     if (name_list.empty()) {
2071b842f2ecSJim Ingham       result.AppendMessage("No breakpoint names found.");
2072b842f2ecSJim Ingham     } else {
2073b842f2ecSJim Ingham       for (const std::string &name_str : name_list) {
2074b842f2ecSJim Ingham         const char *name = name_str.c_str();
2075b842f2ecSJim Ingham         // First print out the options for the name:
2076b842f2ecSJim Ingham         Status error;
2077b842f2ecSJim Ingham         BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2078b842f2ecSJim Ingham                                                              false,
2079b842f2ecSJim Ingham                                                              error);
2080b842f2ecSJim Ingham         if (bp_name)
2081b842f2ecSJim Ingham         {
2082b842f2ecSJim Ingham           StreamString s;
2083b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s\n", name);
2084b842f2ecSJim Ingham           if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2085b842f2ecSJim Ingham           {
2086b842f2ecSJim Ingham             result.AppendMessage(s.GetString());
2087b842f2ecSJim Ingham           }
2088b842f2ecSJim Ingham 
2089bb19a13cSSaleem Abdulrasool           std::unique_lock<std::recursive_mutex> lock;
2090bb19a13cSSaleem Abdulrasool           target->GetBreakpointList().GetListMutex(lock);
20915e09c8c3SJim Ingham 
20925e09c8c3SJim Ingham           BreakpointList &breakpoints = target->GetBreakpointList();
2093b842f2ecSJim Ingham           bool any_set = false;
2094b9c1b51eSKate Stone           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2095b9c1b51eSKate Stone             if (bp_sp->MatchesName(name)) {
20965e09c8c3SJim Ingham               StreamString s;
2097b842f2ecSJim Ingham               any_set = true;
20985e09c8c3SJim Ingham               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
20995e09c8c3SJim Ingham               s.EOL();
2100c156427dSZachary Turner               result.AppendMessage(s.GetString());
21015e09c8c3SJim Ingham             }
21025e09c8c3SJim Ingham           }
2103b842f2ecSJim Ingham           if (!any_set)
2104b842f2ecSJim Ingham             result.AppendMessage("No breakpoints using this name.");
2105b9c1b51eSKate Stone         } else {
2106b842f2ecSJim Ingham           result.AppendMessageWithFormat("Name: %s not found.\n", name);
21075e09c8c3SJim Ingham         }
2108b842f2ecSJim Ingham       }
21095e09c8c3SJim Ingham     }
21105e09c8c3SJim Ingham     return true;
21115e09c8c3SJim Ingham   }
21125e09c8c3SJim Ingham 
21135e09c8c3SJim Ingham private:
21145e09c8c3SJim Ingham   BreakpointNameOptionGroup m_name_options;
21155e09c8c3SJim Ingham   OptionGroupOptions m_option_group;
21165e09c8c3SJim Ingham };
21175e09c8c3SJim Ingham 
2118e14dc268SJim Ingham // CommandObjectBreakpointName
2119b9c1b51eSKate Stone class CommandObjectBreakpointName : public CommandObjectMultiword {
21205e09c8c3SJim Ingham public:
21217428a18cSKate Stone   CommandObjectBreakpointName(CommandInterpreter &interpreter)
2122b9c1b51eSKate Stone       : CommandObjectMultiword(
2123b9c1b51eSKate Stone             interpreter, "name", "Commands to manage name tags for breakpoints",
2124b9c1b51eSKate Stone             "breakpoint name <subcommand> [<command-options>]") {
2125b9c1b51eSKate Stone     CommandObjectSP add_command_object(
2126b9c1b51eSKate Stone         new CommandObjectBreakpointNameAdd(interpreter));
2127b9c1b51eSKate Stone     CommandObjectSP delete_command_object(
2128b9c1b51eSKate Stone         new CommandObjectBreakpointNameDelete(interpreter));
2129b9c1b51eSKate Stone     CommandObjectSP list_command_object(
2130b9c1b51eSKate Stone         new CommandObjectBreakpointNameList(interpreter));
2131b842f2ecSJim Ingham     CommandObjectSP configure_command_object(
2132b842f2ecSJim Ingham         new CommandObjectBreakpointNameConfigure(interpreter));
21335e09c8c3SJim Ingham 
21345e09c8c3SJim Ingham     LoadSubCommand("add", add_command_object);
21355e09c8c3SJim Ingham     LoadSubCommand("delete", delete_command_object);
21365e09c8c3SJim Ingham     LoadSubCommand("list", list_command_object);
2137b842f2ecSJim Ingham     LoadSubCommand("configure", configure_command_object);
21385e09c8c3SJim Ingham   }
21395e09c8c3SJim Ingham 
21409e85e5a8SEugene Zelenko   ~CommandObjectBreakpointName() override = default;
21415e09c8c3SJim Ingham };
21425e09c8c3SJim Ingham 
2143e14dc268SJim Ingham // CommandObjectBreakpointRead
21443acdf385SJim Ingham #pragma mark Read::CommandOptions
21458fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_read_options[] = {
2146*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_read
2147*f94668e3SRaphael Isemann #include "CommandOptions.inc"
21481f0f5b5bSZachary Turner };
21491f0f5b5bSZachary Turner 
21501f0f5b5bSZachary Turner #pragma mark Read
2151e14dc268SJim Ingham 
2152e14dc268SJim Ingham class CommandObjectBreakpointRead : public CommandObjectParsed {
2153e14dc268SJim Ingham public:
2154e14dc268SJim Ingham   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2155e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint read",
2156e14dc268SJim Ingham                             "Read and set the breakpoints previously saved to "
2157e14dc268SJim Ingham                             "a file with \"breakpoint write\".  ",
2158e14dc268SJim Ingham                             nullptr),
2159e14dc268SJim Ingham         m_options() {
2160e14dc268SJim Ingham     CommandArgumentEntry arg;
2161e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2162e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2163e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2164e14dc268SJim Ingham     // arguments vector.
2165e14dc268SJim Ingham     m_arguments.push_back(arg);
2166e14dc268SJim Ingham   }
2167e14dc268SJim Ingham 
2168e14dc268SJim Ingham   ~CommandObjectBreakpointRead() override = default;
2169e14dc268SJim Ingham 
2170e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2171e14dc268SJim Ingham 
2172e14dc268SJim Ingham   class CommandOptions : public Options {
2173e14dc268SJim Ingham   public:
2174e14dc268SJim Ingham     CommandOptions() : Options() {}
2175e14dc268SJim Ingham 
2176e14dc268SJim Ingham     ~CommandOptions() override = default;
2177e14dc268SJim Ingham 
217897206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2179e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
218097206d57SZachary Turner       Status error;
2181e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2182e14dc268SJim Ingham 
2183e14dc268SJim Ingham       switch (short_option) {
2184e14dc268SJim Ingham       case 'f':
2185e14dc268SJim Ingham         m_filename.assign(option_arg);
2186e14dc268SJim Ingham         break;
21873acdf385SJim Ingham       case 'N': {
218897206d57SZachary Turner         Status name_error;
21893acdf385SJim Ingham         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
21903acdf385SJim Ingham                                                   name_error)) {
21913acdf385SJim Ingham           error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
21923acdf385SJim Ingham                                          name_error.AsCString());
21933acdf385SJim Ingham         }
21943acdf385SJim Ingham         m_names.push_back(option_arg);
21953acdf385SJim Ingham         break;
21963acdf385SJim Ingham       }
2197e14dc268SJim Ingham       default:
2198e14dc268SJim Ingham         error.SetErrorStringWithFormat("unrecognized option '%c'",
2199e14dc268SJim Ingham                                        short_option);
2200e14dc268SJim Ingham         break;
2201e14dc268SJim Ingham       }
2202e14dc268SJim Ingham 
2203e14dc268SJim Ingham       return error;
2204e14dc268SJim Ingham     }
2205e14dc268SJim Ingham 
2206e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2207e14dc268SJim Ingham       m_filename.clear();
22083acdf385SJim Ingham       m_names.clear();
2209e14dc268SJim Ingham     }
2210e14dc268SJim Ingham 
22111f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
221270602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_read_options);
22131f0f5b5bSZachary Turner     }
2214e14dc268SJim Ingham 
2215e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2216e14dc268SJim Ingham 
2217e14dc268SJim Ingham     std::string m_filename;
22183acdf385SJim Ingham     std::vector<std::string> m_names;
2219e14dc268SJim Ingham   };
2220e14dc268SJim Ingham 
2221e14dc268SJim Ingham protected:
2222e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2223e14dc268SJim Ingham     Target *target = GetSelectedOrDummyTarget();
2224e14dc268SJim Ingham     if (target == nullptr) {
2225e14dc268SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
2226e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
2227e14dc268SJim Ingham       return false;
2228e14dc268SJim Ingham     }
2229e14dc268SJim Ingham 
22303acdf385SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
22313acdf385SJim Ingham     target->GetBreakpointList().GetListMutex(lock);
22323acdf385SJim Ingham 
22338f3be7a3SJonas Devlieghere     FileSpec input_spec(m_options.m_filename);
22348f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(input_spec);
223501f16664SJim Ingham     BreakpointIDList new_bps;
223697206d57SZachary Turner     Status error = target->CreateBreakpointsFromFile(
223797206d57SZachary Turner         input_spec, m_options.m_names, new_bps);
2238e14dc268SJim Ingham 
2239e14dc268SJim Ingham     if (!error.Success()) {
224001f16664SJim Ingham       result.AppendError(error.AsCString());
2241e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
224201f16664SJim Ingham       return false;
2243e14dc268SJim Ingham     }
22443acdf385SJim Ingham 
22453acdf385SJim Ingham     Stream &output_stream = result.GetOutputStream();
22463acdf385SJim Ingham 
22473acdf385SJim Ingham     size_t num_breakpoints = new_bps.GetSize();
22483acdf385SJim Ingham     if (num_breakpoints == 0) {
22493acdf385SJim Ingham       result.AppendMessage("No breakpoints added.");
22503acdf385SJim Ingham     } else {
22513acdf385SJim Ingham       // No breakpoint selected; show info about all currently set breakpoints.
22523acdf385SJim Ingham       result.AppendMessage("New breakpoints:");
22533acdf385SJim Ingham       for (size_t i = 0; i < num_breakpoints; ++i) {
22543acdf385SJim Ingham         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
22553acdf385SJim Ingham         Breakpoint *bp = target->GetBreakpointList()
22563acdf385SJim Ingham                              .FindBreakpointByID(bp_id.GetBreakpointID())
22573acdf385SJim Ingham                              .get();
22583acdf385SJim Ingham         if (bp)
22593acdf385SJim Ingham           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
22603acdf385SJim Ingham                              false);
22613acdf385SJim Ingham       }
22623acdf385SJim Ingham     }
2263e14dc268SJim Ingham     return result.Succeeded();
2264e14dc268SJim Ingham   }
2265e14dc268SJim Ingham 
2266e14dc268SJim Ingham private:
2267e14dc268SJim Ingham   CommandOptions m_options;
2268e14dc268SJim Ingham };
2269e14dc268SJim Ingham 
2270e14dc268SJim Ingham // CommandObjectBreakpointWrite
22711f0f5b5bSZachary Turner #pragma mark Write::CommandOptions
22728fe53c49STatyana Krasnukha static constexpr OptionDefinition g_breakpoint_write_options[] = {
2273*f94668e3SRaphael Isemann #define LLDB_OPTIONS_breakpoint_write
2274*f94668e3SRaphael Isemann #include "CommandOptions.inc"
22751f0f5b5bSZachary Turner };
22761f0f5b5bSZachary Turner 
22771f0f5b5bSZachary Turner #pragma mark Write
2278e14dc268SJim Ingham class CommandObjectBreakpointWrite : public CommandObjectParsed {
2279e14dc268SJim Ingham public:
2280e14dc268SJim Ingham   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2281e14dc268SJim Ingham       : CommandObjectParsed(interpreter, "breakpoint write",
2282e14dc268SJim Ingham                             "Write the breakpoints listed to a file that can "
2283e14dc268SJim Ingham                             "be read in with \"breakpoint read\".  "
2284e14dc268SJim Ingham                             "If given no arguments, writes all breakpoints.",
2285e14dc268SJim Ingham                             nullptr),
2286e14dc268SJim Ingham         m_options() {
2287e14dc268SJim Ingham     CommandArgumentEntry arg;
2288e14dc268SJim Ingham     CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2289e14dc268SJim Ingham                                       eArgTypeBreakpointIDRange);
2290e14dc268SJim Ingham     // Add the entry for the first argument for this command to the object's
2291e14dc268SJim Ingham     // arguments vector.
2292e14dc268SJim Ingham     m_arguments.push_back(arg);
2293e14dc268SJim Ingham   }
2294e14dc268SJim Ingham 
2295e14dc268SJim Ingham   ~CommandObjectBreakpointWrite() override = default;
2296e14dc268SJim Ingham 
2297e14dc268SJim Ingham   Options *GetOptions() override { return &m_options; }
2298e14dc268SJim Ingham 
2299e14dc268SJim Ingham   class CommandOptions : public Options {
2300e14dc268SJim Ingham   public:
2301e14dc268SJim Ingham     CommandOptions() : Options() {}
2302e14dc268SJim Ingham 
2303e14dc268SJim Ingham     ~CommandOptions() override = default;
2304e14dc268SJim Ingham 
230597206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2306e14dc268SJim Ingham                           ExecutionContext *execution_context) override {
230797206d57SZachary Turner       Status error;
2308e14dc268SJim Ingham       const int short_option = m_getopt_table[option_idx].val;
2309e14dc268SJim Ingham 
2310e14dc268SJim Ingham       switch (short_option) {
2311e14dc268SJim Ingham       case 'f':
2312e14dc268SJim Ingham         m_filename.assign(option_arg);
2313e14dc268SJim Ingham         break;
23142d3628e1SJim Ingham       case 'a':
23152d3628e1SJim Ingham         m_append = true;
23162d3628e1SJim Ingham         break;
2317e14dc268SJim Ingham       default:
2318e14dc268SJim Ingham         error.SetErrorStringWithFormat("unrecognized option '%c'",
2319e14dc268SJim Ingham                                        short_option);
2320e14dc268SJim Ingham         break;
2321e14dc268SJim Ingham       }
2322e14dc268SJim Ingham 
2323e14dc268SJim Ingham       return error;
2324e14dc268SJim Ingham     }
2325e14dc268SJim Ingham 
2326e14dc268SJim Ingham     void OptionParsingStarting(ExecutionContext *execution_context) override {
2327e14dc268SJim Ingham       m_filename.clear();
23282d3628e1SJim Ingham       m_append = false;
2329e14dc268SJim Ingham     }
2330e14dc268SJim Ingham 
23311f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
233270602439SZachary Turner       return llvm::makeArrayRef(g_breakpoint_write_options);
23331f0f5b5bSZachary Turner     }
2334e14dc268SJim Ingham 
2335e14dc268SJim Ingham     // Instance variables to hold the values for command options.
2336e14dc268SJim Ingham 
2337e14dc268SJim Ingham     std::string m_filename;
23382d3628e1SJim Ingham     bool m_append = false;
2339e14dc268SJim Ingham   };
2340e14dc268SJim Ingham 
2341e14dc268SJim Ingham protected:
2342e14dc268SJim Ingham   bool DoExecute(Args &command, CommandReturnObject &result) override {
2343e14dc268SJim Ingham     Target *target = GetSelectedOrDummyTarget();
2344e14dc268SJim Ingham     if (target == nullptr) {
2345e14dc268SJim Ingham       result.AppendError("Invalid target.  No existing target or breakpoints.");
2346e14dc268SJim Ingham       result.SetStatus(eReturnStatusFailed);
2347e14dc268SJim Ingham       return false;
2348e14dc268SJim Ingham     }
2349e14dc268SJim Ingham 
2350e14dc268SJim Ingham     std::unique_lock<std::recursive_mutex> lock;
2351e14dc268SJim Ingham     target->GetBreakpointList().GetListMutex(lock);
2352e14dc268SJim Ingham 
2353e14dc268SJim Ingham     BreakpointIDList valid_bp_ids;
235411eb9c64SZachary Turner     if (!command.empty()) {
2355e14dc268SJim Ingham       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2356b842f2ecSJim Ingham           command, target, result, &valid_bp_ids,
2357b842f2ecSJim Ingham           BreakpointName::Permissions::PermissionKinds::listPerm);
2358e14dc268SJim Ingham 
235901f16664SJim Ingham       if (!result.Succeeded()) {
2360e14dc268SJim Ingham         result.SetStatus(eReturnStatusFailed);
2361e14dc268SJim Ingham         return false;
2362e14dc268SJim Ingham       }
2363e14dc268SJim Ingham     }
23648f3be7a3SJonas Devlieghere     FileSpec file_spec(m_options.m_filename);
23658f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(file_spec);
23668f3be7a3SJonas Devlieghere     Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
23678f3be7a3SJonas Devlieghere                                                       m_options.m_append);
236801f16664SJim Ingham     if (!error.Success()) {
236901f16664SJim Ingham       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
237001f16664SJim Ingham                                    error.AsCString());
237101f16664SJim Ingham       result.SetStatus(eReturnStatusFailed);
2372e14dc268SJim Ingham     }
2373e14dc268SJim Ingham     return result.Succeeded();
2374e14dc268SJim Ingham   }
2375e14dc268SJim Ingham 
2376e14dc268SJim Ingham private:
2377e14dc268SJim Ingham   CommandOptions m_options;
2378e14dc268SJim Ingham };
2379e14dc268SJim Ingham 
238030fdc8d8SChris Lattner // CommandObjectMultiwordBreakpoint
2381ae1c4cf5SJim Ingham #pragma mark MultiwordBreakpoint
238230fdc8d8SChris Lattner 
2383b9c1b51eSKate Stone CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2384b9c1b51eSKate Stone     CommandInterpreter &interpreter)
2385b9c1b51eSKate Stone     : CommandObjectMultiword(
2386b9c1b51eSKate Stone           interpreter, "breakpoint",
23877428a18cSKate Stone           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2388b9c1b51eSKate Stone           "breakpoint <subcommand> [<command-options>]") {
2389b9c1b51eSKate Stone   CommandObjectSP list_command_object(
2390b9c1b51eSKate Stone       new CommandObjectBreakpointList(interpreter));
2391b9c1b51eSKate Stone   CommandObjectSP enable_command_object(
2392b9c1b51eSKate Stone       new CommandObjectBreakpointEnable(interpreter));
2393b9c1b51eSKate Stone   CommandObjectSP disable_command_object(
2394b9c1b51eSKate Stone       new CommandObjectBreakpointDisable(interpreter));
2395b9c1b51eSKate Stone   CommandObjectSP clear_command_object(
2396b9c1b51eSKate Stone       new CommandObjectBreakpointClear(interpreter));
2397b9c1b51eSKate Stone   CommandObjectSP delete_command_object(
2398b9c1b51eSKate Stone       new CommandObjectBreakpointDelete(interpreter));
2399b9c1b51eSKate Stone   CommandObjectSP set_command_object(
2400b9c1b51eSKate Stone       new CommandObjectBreakpointSet(interpreter));
2401b9c1b51eSKate Stone   CommandObjectSP command_command_object(
2402b9c1b51eSKate Stone       new CommandObjectBreakpointCommand(interpreter));
2403b9c1b51eSKate Stone   CommandObjectSP modify_command_object(
2404b9c1b51eSKate Stone       new CommandObjectBreakpointModify(interpreter));
2405b9c1b51eSKate Stone   CommandObjectSP name_command_object(
2406b9c1b51eSKate Stone       new CommandObjectBreakpointName(interpreter));
2407e14dc268SJim Ingham   CommandObjectSP write_command_object(
2408e14dc268SJim Ingham       new CommandObjectBreakpointWrite(interpreter));
2409e14dc268SJim Ingham   CommandObjectSP read_command_object(
2410e14dc268SJim Ingham       new CommandObjectBreakpointRead(interpreter));
241130fdc8d8SChris Lattner 
2412b7234e40SJohnny Chen   list_command_object->SetCommandName("breakpoint list");
241330fdc8d8SChris Lattner   enable_command_object->SetCommandName("breakpoint enable");
241430fdc8d8SChris Lattner   disable_command_object->SetCommandName("breakpoint disable");
2415b7234e40SJohnny Chen   clear_command_object->SetCommandName("breakpoint clear");
2416b7234e40SJohnny Chen   delete_command_object->SetCommandName("breakpoint delete");
2417ae1c4cf5SJim Ingham   set_command_object->SetCommandName("breakpoint set");
2418b7234e40SJohnny Chen   command_command_object->SetCommandName("breakpoint command");
2419b7234e40SJohnny Chen   modify_command_object->SetCommandName("breakpoint modify");
24205e09c8c3SJim Ingham   name_command_object->SetCommandName("breakpoint name");
2421e14dc268SJim Ingham   write_command_object->SetCommandName("breakpoint write");
2422e14dc268SJim Ingham   read_command_object->SetCommandName("breakpoint read");
242330fdc8d8SChris Lattner 
242423f59509SGreg Clayton   LoadSubCommand("list", list_command_object);
242523f59509SGreg Clayton   LoadSubCommand("enable", enable_command_object);
242623f59509SGreg Clayton   LoadSubCommand("disable", disable_command_object);
242723f59509SGreg Clayton   LoadSubCommand("clear", clear_command_object);
242823f59509SGreg Clayton   LoadSubCommand("delete", delete_command_object);
242923f59509SGreg Clayton   LoadSubCommand("set", set_command_object);
243023f59509SGreg Clayton   LoadSubCommand("command", command_command_object);
243123f59509SGreg Clayton   LoadSubCommand("modify", modify_command_object);
24325e09c8c3SJim Ingham   LoadSubCommand("name", name_command_object);
2433e14dc268SJim Ingham   LoadSubCommand("write", write_command_object);
2434e14dc268SJim Ingham   LoadSubCommand("read", read_command_object);
243530fdc8d8SChris Lattner }
243630fdc8d8SChris Lattner 
24379e85e5a8SEugene Zelenko CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
243830fdc8d8SChris Lattner 
2439b9c1b51eSKate Stone void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
24405e09c8c3SJim Ingham                                                  bool allow_locations,
24415e09c8c3SJim Ingham                                                  CommandReturnObject &result,
2442b842f2ecSJim Ingham                                                  BreakpointIDList *valid_ids,
2443b842f2ecSJim Ingham                                                  BreakpointName::Permissions
2444b842f2ecSJim Ingham                                                      ::PermissionKinds
2445b842f2ecSJim Ingham                                                      purpose) {
244630fdc8d8SChris Lattner   // args can be strings representing 1). integers (for breakpoint ids)
2447b9c1b51eSKate Stone   //                                  2). the full breakpoint & location
2448b9c1b51eSKate Stone   //                                  canonical representation
2449b9c1b51eSKate Stone   //                                  3). the word "to" or a hyphen,
2450b9c1b51eSKate Stone   //                                  representing a range (in which case there
2451b9c1b51eSKate Stone   //                                      had *better* be an entry both before &
2452b9c1b51eSKate Stone   //                                      after of one of the first two types.
24535e09c8c3SJim Ingham   //                                  4). A breakpoint name
2454b9c1b51eSKate Stone   // If args is empty, we will use the last created breakpoint (if there is
2455b9c1b51eSKate Stone   // one.)
245630fdc8d8SChris Lattner 
245730fdc8d8SChris Lattner   Args temp_args;
245830fdc8d8SChris Lattner 
245911eb9c64SZachary Turner   if (args.empty()) {
2460b9c1b51eSKate Stone     if (target->GetLastCreatedBreakpoint()) {
2461b9c1b51eSKate Stone       valid_ids->AddBreakpointID(BreakpointID(
2462b9c1b51eSKate Stone           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
246336f3b369SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2464b9c1b51eSKate Stone     } else {
2465b9c1b51eSKate Stone       result.AppendError(
2466b9c1b51eSKate Stone           "No breakpoint specified and no last created breakpoint.");
246736f3b369SJim Ingham       result.SetStatus(eReturnStatusFailed);
246836f3b369SJim Ingham     }
246936f3b369SJim Ingham     return;
247036f3b369SJim Ingham   }
247136f3b369SJim Ingham 
2472b9c1b51eSKate Stone   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
247305097246SAdrian Prantl   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
247405097246SAdrian Prantl   // id range strings over; instead generate a list of strings for all the
247505097246SAdrian Prantl   // breakpoint ids in the range, and shove all of those breakpoint id strings
247605097246SAdrian Prantl   // into TEMP_ARGS.
247730fdc8d8SChris Lattner 
2478b9c1b51eSKate Stone   BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2479b842f2ecSJim Ingham                                            purpose, result, temp_args);
248030fdc8d8SChris Lattner 
2481b9c1b51eSKate Stone   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2482b9c1b51eSKate Stone   // BreakpointIDList:
248330fdc8d8SChris Lattner 
248416662f3cSPavel Labath   valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
248530fdc8d8SChris Lattner 
248605097246SAdrian Prantl   // At this point,  all of the breakpoint ids that the user passed in have
248705097246SAdrian Prantl   // been converted to breakpoint IDs and put into valid_ids.
248830fdc8d8SChris Lattner 
2489b9c1b51eSKate Stone   if (result.Succeeded()) {
2490b9c1b51eSKate Stone     // Now that we've converted everything from args into a list of breakpoint
249105097246SAdrian Prantl     // ids, go through our tentative list of breakpoint id's and verify that
249205097246SAdrian Prantl     // they correspond to valid/currently set breakpoints.
249330fdc8d8SChris Lattner 
2494c982c768SGreg Clayton     const size_t count = valid_ids->GetSize();
2495b9c1b51eSKate Stone     for (size_t i = 0; i < count; ++i) {
249630fdc8d8SChris Lattner       BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2497b9c1b51eSKate Stone       Breakpoint *breakpoint =
2498b9c1b51eSKate Stone           target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2499b9c1b51eSKate Stone       if (breakpoint != nullptr) {
2500c7bece56SGreg Clayton         const size_t num_locations = breakpoint->GetNumLocations();
2501b9c1b51eSKate Stone         if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
250230fdc8d8SChris Lattner           StreamString id_str;
2503b9c1b51eSKate Stone           BreakpointID::GetCanonicalReference(
2504b9c1b51eSKate Stone               &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2505c982c768SGreg Clayton           i = valid_ids->GetSize() + 1;
2506b9c1b51eSKate Stone           result.AppendErrorWithFormat(
2507b9c1b51eSKate Stone               "'%s' is not a currently valid breakpoint/location id.\n",
250830fdc8d8SChris Lattner               id_str.GetData());
250930fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
251030fdc8d8SChris Lattner         }
2511b9c1b51eSKate Stone       } else {
2512c982c768SGreg Clayton         i = valid_ids->GetSize() + 1;
2513b9c1b51eSKate Stone         result.AppendErrorWithFormat(
2514b9c1b51eSKate Stone             "'%d' is not a currently valid breakpoint ID.\n",
25157428a18cSKate Stone             cur_bp_id.GetBreakpointID());
251630fdc8d8SChris Lattner         result.SetStatus(eReturnStatusFailed);
251730fdc8d8SChris Lattner       }
251830fdc8d8SChris Lattner     }
251930fdc8d8SChris Lattner   }
252030fdc8d8SChris Lattner }
2521