xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectBreakpoint.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "CommandObjectBreakpoint.h"
10f3fbd1c0SDimitry Andric #include "CommandObjectBreakpointCommand.h"
11f034231aSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
12f034231aSEd Maste #include "lldb/Breakpoint/BreakpointIDList.h"
13f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
1474a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
1514f1b3e8SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
164b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
1714f1b3e8SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
18f73363f1SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
19ead24645SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
205e95aa85SEd Maste #include "lldb/Interpreter/OptionValueBoolean.h"
21b60736ecSDimitry Andric #include "lldb/Interpreter/OptionValueFileColonLine.h"
22205afe67SEd Maste #include "lldb/Interpreter/OptionValueString.h"
23205afe67SEd Maste #include "lldb/Interpreter/OptionValueUInt64.h"
2414f1b3e8SDimitry Andric #include "lldb/Interpreter/Options.h"
25e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
26f034231aSEd Maste #include "lldb/Target/StackFrame.h"
2714f1b3e8SDimitry Andric #include "lldb/Target/Target.h"
28f034231aSEd Maste #include "lldb/Target/ThreadSpec.h"
2974a628f7SDimitry Andric #include "lldb/Utility/RegularExpression.h"
3074a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
31f034231aSEd Maste 
325f29bb8aSDimitry Andric #include <memory>
33e3b55780SDimitry Andric #include <optional>
345f29bb8aSDimitry Andric #include <vector>
355f29bb8aSDimitry Andric 
36f034231aSEd Maste using namespace lldb;
37f034231aSEd Maste using namespace lldb_private;
38f034231aSEd Maste 
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)3914f1b3e8SDimitry Andric static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
4014f1b3e8SDimitry Andric                                      lldb::DescriptionLevel level) {
41f034231aSEd Maste   s->IndentMore();
42f034231aSEd Maste   bp->GetDescription(s, level, true);
43f034231aSEd Maste   s->IndentLess();
44f034231aSEd Maste   s->EOL();
45f034231aSEd Maste }
46f034231aSEd Maste 
47ef5d0b5eSDimitry Andric // Modifiable Breakpoint Options
48ef5d0b5eSDimitry Andric #pragma mark Modify::CommandOptions
49ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_modify
50ead24645SDimitry Andric #include "CommandOptions.inc"
51ead24645SDimitry Andric 
52706b4fc4SDimitry Andric class lldb_private::BreakpointOptionGroup : public OptionGroup {
53ef5d0b5eSDimitry Andric public:
BreakpointOptionGroup()546f8fc217SDimitry Andric   BreakpointOptionGroup() : m_bp_opts(false) {}
55ef5d0b5eSDimitry Andric 
56ef5d0b5eSDimitry Andric   ~BreakpointOptionGroup() override = default;
57ef5d0b5eSDimitry Andric 
GetDefinitions()58ef5d0b5eSDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
59e3b55780SDimitry Andric     return llvm::ArrayRef(g_breakpoint_modify_options);
60ef5d0b5eSDimitry Andric   }
61ef5d0b5eSDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)62ef5d0b5eSDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
63ef5d0b5eSDimitry Andric                         ExecutionContext *execution_context) override {
64ef5d0b5eSDimitry Andric     Status error;
65706b4fc4SDimitry Andric     const int short_option =
66706b4fc4SDimitry Andric         g_breakpoint_modify_options[option_idx].short_option;
67ac9a064cSDimitry Andric     const char *long_option =
68ac9a064cSDimitry Andric         g_breakpoint_modify_options[option_idx].long_option;
69ef5d0b5eSDimitry Andric 
70ef5d0b5eSDimitry Andric     switch (short_option) {
71ef5d0b5eSDimitry Andric     case 'c':
72f73363f1SDimitry Andric       // Normally an empty breakpoint condition marks is as unset. But we need
73f73363f1SDimitry Andric       // to say it was passed in.
74ef5d0b5eSDimitry Andric       m_bp_opts.SetCondition(option_arg.str().c_str());
75ef5d0b5eSDimitry Andric       m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
76ef5d0b5eSDimitry Andric       break;
77ef5d0b5eSDimitry Andric     case 'C':
78cfca06d7SDimitry Andric       m_commands.push_back(std::string(option_arg));
79ef5d0b5eSDimitry Andric       break;
80ef5d0b5eSDimitry Andric     case 'd':
81ef5d0b5eSDimitry Andric       m_bp_opts.SetEnabled(false);
82ef5d0b5eSDimitry Andric       break;
83ef5d0b5eSDimitry Andric     case 'e':
84ef5d0b5eSDimitry Andric       m_bp_opts.SetEnabled(true);
85ef5d0b5eSDimitry Andric       break;
86ef5d0b5eSDimitry Andric     case 'G': {
87ef5d0b5eSDimitry Andric       bool value, success;
88f73363f1SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
89ac9a064cSDimitry Andric       if (success)
90ef5d0b5eSDimitry Andric         m_bp_opts.SetAutoContinue(value);
91ac9a064cSDimitry Andric       else
92ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
93ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
94706b4fc4SDimitry Andric     } break;
95706b4fc4SDimitry Andric     case 'i': {
96ef5d0b5eSDimitry Andric       uint32_t ignore_count;
97ef5d0b5eSDimitry Andric       if (option_arg.getAsInteger(0, ignore_count))
98ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
99ac9a064cSDimitry Andric                                          g_int_parsing_error_message);
100ef5d0b5eSDimitry Andric       else
101ef5d0b5eSDimitry Andric         m_bp_opts.SetIgnoreCount(ignore_count);
102706b4fc4SDimitry Andric     } break;
103ef5d0b5eSDimitry Andric     case 'o': {
104ef5d0b5eSDimitry Andric       bool value, success;
105f73363f1SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
106ef5d0b5eSDimitry Andric       if (success) {
107ef5d0b5eSDimitry Andric         m_bp_opts.SetOneShot(value);
108ef5d0b5eSDimitry Andric       } else
109ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
110ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
111ef5d0b5eSDimitry Andric     } break;
112706b4fc4SDimitry Andric     case 't': {
113ef5d0b5eSDimitry Andric       lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
114c0981da4SDimitry Andric       if (option_arg == "current") {
115c0981da4SDimitry Andric         if (!execution_context) {
116ac9a064cSDimitry Andric           error = CreateOptionParsingError(
117ac9a064cSDimitry Andric               option_arg, short_option, long_option,
118ac9a064cSDimitry Andric               "No context to determine current thread");
119c0981da4SDimitry Andric         } else {
120c0981da4SDimitry Andric           ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
121c0981da4SDimitry Andric           if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
122ac9a064cSDimitry Andric             error =
123ac9a064cSDimitry Andric                 CreateOptionParsingError(option_arg, short_option, long_option,
124ac9a064cSDimitry Andric                                          "No currently selected thread");
125c0981da4SDimitry Andric           } else {
126c0981da4SDimitry Andric             thread_id = ctx_thread_sp->GetID();
127c0981da4SDimitry Andric           }
128c0981da4SDimitry Andric         }
129e3b55780SDimitry Andric       } else if (option_arg.getAsInteger(0, thread_id)) {
130ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
131ac9a064cSDimitry Andric                                          g_int_parsing_error_message);
132ef5d0b5eSDimitry Andric       }
133e3b55780SDimitry Andric       if (thread_id != LLDB_INVALID_THREAD_ID)
134ef5d0b5eSDimitry Andric         m_bp_opts.SetThreadID(thread_id);
135706b4fc4SDimitry Andric     } break;
136ef5d0b5eSDimitry Andric     case 'T':
137ef5d0b5eSDimitry Andric       m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
138ef5d0b5eSDimitry Andric       break;
139ef5d0b5eSDimitry Andric     case 'q':
140ef5d0b5eSDimitry Andric       m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
141ef5d0b5eSDimitry Andric       break;
142706b4fc4SDimitry Andric     case 'x': {
143ef5d0b5eSDimitry Andric       uint32_t thread_index = UINT32_MAX;
144e3b55780SDimitry Andric       if (option_arg.getAsInteger(0, thread_index)) {
145ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
146ac9a064cSDimitry Andric                                          g_int_parsing_error_message);
147e3b55780SDimitry Andric       } else {
148ef5d0b5eSDimitry Andric         m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
149e3b55780SDimitry Andric       }
150706b4fc4SDimitry Andric     } break;
151ef5d0b5eSDimitry Andric     default:
152ead24645SDimitry Andric       llvm_unreachable("Unimplemented option");
153ef5d0b5eSDimitry Andric     }
154ef5d0b5eSDimitry Andric 
155ef5d0b5eSDimitry Andric     return error;
156ef5d0b5eSDimitry Andric   }
157ef5d0b5eSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)158ef5d0b5eSDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
159ef5d0b5eSDimitry Andric     m_bp_opts.Clear();
160ef5d0b5eSDimitry Andric     m_commands.clear();
161ef5d0b5eSDimitry Andric   }
162ef5d0b5eSDimitry Andric 
OptionParsingFinished(ExecutionContext * execution_context)163ef5d0b5eSDimitry Andric   Status OptionParsingFinished(ExecutionContext *execution_context) override {
164706b4fc4SDimitry Andric     if (!m_commands.empty()) {
165ead24645SDimitry Andric       auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
166ef5d0b5eSDimitry Andric 
167ef5d0b5eSDimitry Andric       for (std::string &str : m_commands)
168ef5d0b5eSDimitry Andric         cmd_data->user_source.AppendString(str);
169ef5d0b5eSDimitry Andric 
170ef5d0b5eSDimitry Andric       cmd_data->stop_on_error = true;
171ef5d0b5eSDimitry Andric       m_bp_opts.SetCommandDataCallback(cmd_data);
172ef5d0b5eSDimitry Andric     }
173ef5d0b5eSDimitry Andric     return Status();
174ef5d0b5eSDimitry Andric   }
175ef5d0b5eSDimitry Andric 
GetBreakpointOptions()176706b4fc4SDimitry Andric   const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
177ef5d0b5eSDimitry Andric 
178ef5d0b5eSDimitry Andric   std::vector<std::string> m_commands;
179ef5d0b5eSDimitry Andric   BreakpointOptions m_bp_opts;
180ef5d0b5eSDimitry Andric };
181ead24645SDimitry Andric 
182ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_dummy
183ead24645SDimitry Andric #include "CommandOptions.inc"
184ef5d0b5eSDimitry Andric 
185706b4fc4SDimitry Andric class BreakpointDummyOptionGroup : public OptionGroup {
186ef5d0b5eSDimitry Andric public:
187145449b1SDimitry Andric   BreakpointDummyOptionGroup() = default;
188ef5d0b5eSDimitry Andric 
189ef5d0b5eSDimitry Andric   ~BreakpointDummyOptionGroup() override = default;
190ef5d0b5eSDimitry Andric 
GetDefinitions()191ef5d0b5eSDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
192e3b55780SDimitry Andric     return llvm::ArrayRef(g_breakpoint_dummy_options);
193ef5d0b5eSDimitry Andric   }
194ef5d0b5eSDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)195ef5d0b5eSDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
196ef5d0b5eSDimitry Andric                         ExecutionContext *execution_context) override {
197ef5d0b5eSDimitry Andric     Status error;
198706b4fc4SDimitry Andric     const int short_option =
199706b4fc4SDimitry Andric         g_breakpoint_dummy_options[option_idx].short_option;
200ef5d0b5eSDimitry Andric 
201ef5d0b5eSDimitry Andric     switch (short_option) {
202ef5d0b5eSDimitry Andric     case 'D':
203ef5d0b5eSDimitry Andric       m_use_dummy = true;
204ef5d0b5eSDimitry Andric       break;
205ef5d0b5eSDimitry Andric     default:
206ead24645SDimitry Andric       llvm_unreachable("Unimplemented option");
207ef5d0b5eSDimitry Andric     }
208ef5d0b5eSDimitry Andric 
209ef5d0b5eSDimitry Andric     return error;
210ef5d0b5eSDimitry Andric   }
211ef5d0b5eSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)212ef5d0b5eSDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
213ef5d0b5eSDimitry Andric     m_use_dummy = false;
214ef5d0b5eSDimitry Andric   }
215ef5d0b5eSDimitry Andric 
216ef5d0b5eSDimitry Andric   bool m_use_dummy;
217ef5d0b5eSDimitry Andric };
218ef5d0b5eSDimitry Andric 
219ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_set
220ead24645SDimitry Andric #include "CommandOptions.inc"
22114f1b3e8SDimitry Andric 
222f034231aSEd Maste // CommandObjectBreakpointSet
223f034231aSEd Maste 
22414f1b3e8SDimitry Andric class CommandObjectBreakpointSet : public CommandObjectParsed {
225f034231aSEd Maste public:
2265f29bb8aSDimitry Andric   enum BreakpointSetType {
227f034231aSEd Maste     eSetTypeInvalid,
228f034231aSEd Maste     eSetTypeFileAndLine,
229f034231aSEd Maste     eSetTypeAddress,
230f034231aSEd Maste     eSetTypeFunctionName,
231f034231aSEd Maste     eSetTypeFunctionRegexp,
232f034231aSEd Maste     eSetTypeSourceRegexp,
23394994d37SDimitry Andric     eSetTypeException,
23494994d37SDimitry Andric     eSetTypeScripted,
2355f29bb8aSDimitry Andric   };
236f034231aSEd Maste 
CommandObjectBreakpointSet(CommandInterpreter & interpreter)23714f1b3e8SDimitry Andric   CommandObjectBreakpointSet(CommandInterpreter &interpreter)
23814f1b3e8SDimitry Andric       : CommandObjectParsed(
23914f1b3e8SDimitry Andric             interpreter, "breakpoint set",
240f034231aSEd Maste             "Sets a breakpoint or set of breakpoints in the executable.",
241f034231aSEd Maste             "breakpoint set <cmd-options>"),
2426f8fc217SDimitry Andric         m_python_class_options("scripted breakpoint", true, 'P') {
243ef5d0b5eSDimitry Andric     // We're picking up all the normal options, commands and disable.
244706b4fc4SDimitry Andric     m_all_options.Append(&m_python_class_options,
245706b4fc4SDimitry Andric                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
246ef5d0b5eSDimitry Andric     m_all_options.Append(&m_bp_opts,
247ef5d0b5eSDimitry Andric                          LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
248ef5d0b5eSDimitry Andric                          LLDB_OPT_SET_ALL);
249ef5d0b5eSDimitry Andric     m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
250ef5d0b5eSDimitry Andric     m_all_options.Append(&m_options);
251ef5d0b5eSDimitry Andric     m_all_options.Finalize();
252ef5d0b5eSDimitry Andric   }
253f034231aSEd Maste 
254f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointSet() override = default;
255f034231aSEd Maste 
GetOptions()256ef5d0b5eSDimitry Andric   Options *GetOptions() override { return &m_all_options; }
257f034231aSEd Maste 
258ef5d0b5eSDimitry Andric   class CommandOptions : public OptionGroup {
259f034231aSEd Maste   public:
260145449b1SDimitry Andric     CommandOptions() = default;
261f034231aSEd Maste 
262f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
263f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)264b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
26514f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
266b76161e4SDimitry Andric       Status error;
267706b4fc4SDimitry Andric       const int short_option =
268706b4fc4SDimitry Andric           g_breakpoint_set_options[option_idx].short_option;
269ac9a064cSDimitry Andric       const char *long_option =
270ac9a064cSDimitry Andric           g_breakpoint_set_options[option_idx].long_option;
271f034231aSEd Maste 
27214f1b3e8SDimitry Andric       switch (short_option) {
27314f1b3e8SDimitry Andric       case 'a': {
274f73363f1SDimitry Andric         m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
27514f1b3e8SDimitry Andric                                                  LLDB_INVALID_ADDRESS, &error);
27614f1b3e8SDimitry Andric       } break;
277f034231aSEd Maste 
2785e95aa85SEd Maste       case 'A':
2795e95aa85SEd Maste         m_all_files = true;
2805e95aa85SEd Maste         break;
2815e95aa85SEd Maste 
282f034231aSEd Maste       case 'b':
283cfca06d7SDimitry Andric         m_func_names.push_back(std::string(option_arg));
284f034231aSEd Maste         m_func_name_type_mask |= eFunctionNameTypeBase;
285f034231aSEd Maste         break;
286f034231aSEd Maste 
287cfca06d7SDimitry Andric       case 'u':
28814f1b3e8SDimitry Andric         if (option_arg.getAsInteger(0, m_column))
289ac9a064cSDimitry Andric           error =
290ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
291ac9a064cSDimitry Andric                                        g_int_parsing_error_message);
292f034231aSEd Maste         break;
293f3fbd1c0SDimitry Andric 
29414f1b3e8SDimitry Andric       case 'E': {
295e81d9d49SDimitry Andric         LanguageType language = Language::GetLanguageTypeFromString(option_arg);
296f034231aSEd Maste 
297ac9a064cSDimitry Andric         llvm::StringRef error_context;
29814f1b3e8SDimitry Andric         switch (language) {
299f034231aSEd Maste         case eLanguageTypeC89:
300f034231aSEd Maste         case eLanguageTypeC:
301f034231aSEd Maste         case eLanguageTypeC99:
3020cac4ca3SEd Maste         case eLanguageTypeC11:
3035e95aa85SEd Maste           m_exception_language = eLanguageTypeC;
304f034231aSEd Maste           break;
305f034231aSEd Maste         case eLanguageTypeC_plus_plus:
3060cac4ca3SEd Maste         case eLanguageTypeC_plus_plus_03:
3070cac4ca3SEd Maste         case eLanguageTypeC_plus_plus_11:
30812bd4897SEd Maste         case eLanguageTypeC_plus_plus_14:
3095e95aa85SEd Maste           m_exception_language = eLanguageTypeC_plus_plus;
310f034231aSEd Maste           break;
311f034231aSEd Maste         case eLanguageTypeObjC_plus_plus:
312ac9a064cSDimitry Andric           error_context =
313ac9a064cSDimitry Andric               "Set exception breakpoints separately for c++ and objective-c";
314f034231aSEd Maste           break;
315f034231aSEd Maste         case eLanguageTypeUnknown:
316ac9a064cSDimitry Andric           error_context = "Unknown language type for exception breakpoint";
317f034231aSEd Maste           break;
318f034231aSEd Maste         default:
319ac9a064cSDimitry Andric           if (Language *languagePlugin = Language::FindPlugin(language)) {
320ac9a064cSDimitry Andric             if (languagePlugin->SupportsExceptionBreakpointsOnThrow() ||
321ac9a064cSDimitry Andric                 languagePlugin->SupportsExceptionBreakpointsOnCatch()) {
322ac9a064cSDimitry Andric               m_exception_language = language;
323ac9a064cSDimitry Andric               break;
324f034231aSEd Maste             }
325ac9a064cSDimitry Andric           }
326ac9a064cSDimitry Andric           error_context = "Unsupported language type for exception breakpoint";
327ac9a064cSDimitry Andric         }
328ac9a064cSDimitry Andric         if (!error_context.empty())
329ac9a064cSDimitry Andric           error = CreateOptionParsingError(option_arg, short_option,
330ac9a064cSDimitry Andric                                            long_option, error_context);
33114f1b3e8SDimitry Andric       } break;
332f034231aSEd Maste 
333f034231aSEd Maste       case 'f':
33494994d37SDimitry Andric         m_filenames.AppendIfUnique(FileSpec(option_arg));
335f034231aSEd Maste         break;
336f034231aSEd Maste 
337f034231aSEd Maste       case 'F':
338cfca06d7SDimitry Andric         m_func_names.push_back(std::string(option_arg));
339f034231aSEd Maste         m_func_name_type_mask |= eFunctionNameTypeFull;
340f034231aSEd Maste         break;
341f034231aSEd Maste 
34214f1b3e8SDimitry Andric       case 'h': {
343f034231aSEd Maste         bool success;
344f73363f1SDimitry Andric         m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
345f034231aSEd Maste         if (!success)
346ac9a064cSDimitry Andric           error =
347ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
348ac9a064cSDimitry Andric                                        g_bool_parsing_error_message);
34914f1b3e8SDimitry Andric       } break;
350f21a844fSEd Maste 
351f21a844fSEd Maste       case 'H':
352f21a844fSEd Maste         m_hardware = true;
353f21a844fSEd Maste         break;
354f21a844fSEd Maste 
35514f1b3e8SDimitry Andric       case 'K': {
356f034231aSEd Maste         bool success;
357f034231aSEd Maste         bool value;
358f73363f1SDimitry Andric         value = OptionArgParser::ToBoolean(option_arg, true, &success);
359f034231aSEd Maste         if (value)
360f034231aSEd Maste           m_skip_prologue = eLazyBoolYes;
361f034231aSEd Maste         else
362f034231aSEd Maste           m_skip_prologue = eLazyBoolNo;
363f034231aSEd Maste 
364f034231aSEd Maste         if (!success)
365ac9a064cSDimitry Andric           error =
366ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
367ac9a064cSDimitry Andric                                        g_bool_parsing_error_message);
36814f1b3e8SDimitry Andric       } break;
369f034231aSEd Maste 
370f034231aSEd Maste       case 'l':
37114f1b3e8SDimitry Andric         if (option_arg.getAsInteger(0, m_line_num))
372ac9a064cSDimitry Andric           error =
373ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
374ac9a064cSDimitry Andric                                        g_int_parsing_error_message);
375f034231aSEd Maste         break;
3765e95aa85SEd Maste 
377e81d9d49SDimitry Andric       case 'L':
378e81d9d49SDimitry Andric         m_language = Language::GetLanguageTypeFromString(option_arg);
379e81d9d49SDimitry Andric         if (m_language == eLanguageTypeUnknown)
380ac9a064cSDimitry Andric           error =
381ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
382ac9a064cSDimitry Andric                                        g_language_parsing_error_message);
383e81d9d49SDimitry Andric         break;
384e81d9d49SDimitry Andric 
38514f1b3e8SDimitry Andric       case 'm': {
3865e95aa85SEd Maste         bool success;
3875e95aa85SEd Maste         bool value;
388f73363f1SDimitry Andric         value = OptionArgParser::ToBoolean(option_arg, true, &success);
3895e95aa85SEd Maste         if (value)
3905e95aa85SEd Maste           m_move_to_nearest_code = eLazyBoolYes;
3915e95aa85SEd Maste         else
3925e95aa85SEd Maste           m_move_to_nearest_code = eLazyBoolNo;
3935e95aa85SEd Maste 
3945e95aa85SEd Maste         if (!success)
395ac9a064cSDimitry Andric           error =
396ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
397ac9a064cSDimitry Andric                                        g_bool_parsing_error_message);
3985e95aa85SEd Maste         break;
3995e95aa85SEd Maste       }
400f034231aSEd Maste 
401f034231aSEd Maste       case 'M':
402cfca06d7SDimitry Andric         m_func_names.push_back(std::string(option_arg));
403f034231aSEd Maste         m_func_name_type_mask |= eFunctionNameTypeMethod;
404f034231aSEd Maste         break;
405f034231aSEd Maste 
406f034231aSEd Maste       case 'n':
407cfca06d7SDimitry Andric         m_func_names.push_back(std::string(option_arg));
408f034231aSEd Maste         m_func_name_type_mask |= eFunctionNameTypeAuto;
409f034231aSEd Maste         break;
410f034231aSEd Maste 
41114f1b3e8SDimitry Andric       case 'N': {
412205afe67SEd Maste         if (BreakpointID::StringIsBreakpointName(option_arg, error))
413cfca06d7SDimitry Andric           m_breakpoint_names.push_back(std::string(option_arg));
41414f1b3e8SDimitry Andric         else
415ac9a064cSDimitry Andric           error = CreateOptionParsingError(
416ac9a064cSDimitry Andric               option_arg, short_option, long_option, "Invalid breakpoint name");
417205afe67SEd Maste         break;
41814f1b3e8SDimitry Andric       }
419205afe67SEd Maste 
42014f1b3e8SDimitry Andric       case 'R': {
421f3fbd1c0SDimitry Andric         lldb::addr_t tmp_offset_addr;
422f73363f1SDimitry Andric         tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
423f73363f1SDimitry Andric                                                      option_arg, 0, &error);
424f3fbd1c0SDimitry Andric         if (error.Success())
425f3fbd1c0SDimitry Andric           m_offset_addr = tmp_offset_addr;
42614f1b3e8SDimitry Andric       } break;
427f3fbd1c0SDimitry Andric 
4285e95aa85SEd Maste       case 'O':
4295e95aa85SEd Maste         m_exception_extra_args.AppendArgument("-O");
4305e95aa85SEd Maste         m_exception_extra_args.AppendArgument(option_arg);
4315e95aa85SEd Maste         break;
4325e95aa85SEd Maste 
433f034231aSEd Maste       case 'p':
434cfca06d7SDimitry Andric         m_source_text_regexp.assign(std::string(option_arg));
435f034231aSEd Maste         break;
436f034231aSEd Maste 
437f034231aSEd Maste       case 'r':
438cfca06d7SDimitry Andric         m_func_regexp.assign(std::string(option_arg));
439f034231aSEd Maste         break;
440f034231aSEd Maste 
441f034231aSEd Maste       case 's':
44294994d37SDimitry Andric         m_modules.AppendIfUnique(FileSpec(option_arg));
443f034231aSEd Maste         break;
444f034231aSEd Maste 
445f034231aSEd Maste       case 'S':
446cfca06d7SDimitry Andric         m_func_names.push_back(std::string(option_arg));
447f034231aSEd Maste         m_func_name_type_mask |= eFunctionNameTypeSelector;
448f034231aSEd Maste         break;
449f034231aSEd Maste 
45014f1b3e8SDimitry Andric       case 'w': {
451f034231aSEd Maste         bool success;
452f73363f1SDimitry Andric         m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
453f034231aSEd Maste         if (!success)
454ac9a064cSDimitry Andric           error =
455ac9a064cSDimitry Andric               CreateOptionParsingError(option_arg, short_option, long_option,
456ac9a064cSDimitry Andric                                        g_bool_parsing_error_message);
45714f1b3e8SDimitry Andric       } break;
458f034231aSEd Maste 
459f3fbd1c0SDimitry Andric       case 'X':
460cfca06d7SDimitry Andric         m_source_regex_func_names.insert(std::string(option_arg));
461f034231aSEd Maste         break;
462f034231aSEd Maste 
463b60736ecSDimitry Andric       case 'y':
464b60736ecSDimitry Andric       {
465b60736ecSDimitry Andric         OptionValueFileColonLine value;
466b60736ecSDimitry Andric         Status fcl_err = value.SetValueFromString(option_arg);
467b60736ecSDimitry Andric         if (!fcl_err.Success()) {
468ac9a064cSDimitry Andric           error = CreateOptionParsingError(option_arg, short_option,
469ac9a064cSDimitry Andric                                            long_option, fcl_err.AsCString());
470b60736ecSDimitry Andric         } else {
471b60736ecSDimitry Andric           m_filenames.AppendIfUnique(value.GetFileSpec());
472b60736ecSDimitry Andric           m_line_num = value.GetLineNumber();
473b60736ecSDimitry Andric           m_column = value.GetColumnNumber();
474b60736ecSDimitry Andric         }
475b60736ecSDimitry Andric       } break;
476b60736ecSDimitry Andric 
477f034231aSEd Maste       default:
478ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
479f034231aSEd Maste       }
480f034231aSEd Maste 
481f034231aSEd Maste       return error;
482f034231aSEd Maste     }
483f3fbd1c0SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)48414f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
485f034231aSEd Maste       m_filenames.Clear();
486f034231aSEd Maste       m_line_num = 0;
487f034231aSEd Maste       m_column = 0;
488f034231aSEd Maste       m_func_names.clear();
489f034231aSEd Maste       m_func_name_type_mask = eFunctionNameTypeNone;
490f034231aSEd Maste       m_func_regexp.clear();
491f034231aSEd Maste       m_source_text_regexp.clear();
492f034231aSEd Maste       m_modules.Clear();
493f034231aSEd Maste       m_load_addr = LLDB_INVALID_ADDRESS;
494f3fbd1c0SDimitry Andric       m_offset_addr = 0;
495f034231aSEd Maste       m_catch_bp = false;
496f034231aSEd Maste       m_throw_bp = true;
497f21a844fSEd Maste       m_hardware = false;
4985e95aa85SEd Maste       m_exception_language = eLanguageTypeUnknown;
499e81d9d49SDimitry Andric       m_language = lldb::eLanguageTypeUnknown;
500f034231aSEd Maste       m_skip_prologue = eLazyBoolCalculate;
501205afe67SEd Maste       m_breakpoint_names.clear();
5025e95aa85SEd Maste       m_all_files = false;
5035e95aa85SEd Maste       m_exception_extra_args.Clear();
5045e95aa85SEd Maste       m_move_to_nearest_code = eLazyBoolCalculate;
505f3fbd1c0SDimitry Andric       m_source_regex_func_names.clear();
50694994d37SDimitry Andric       m_current_key.clear();
507f034231aSEd Maste     }
508f034231aSEd Maste 
GetDefinitions()50914f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
510e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_set_options);
511f034231aSEd Maste     }
512f034231aSEd Maste 
513f034231aSEd Maste     // Instance variables to hold the values for command options.
514f034231aSEd Maste 
515f034231aSEd Maste     std::string m_condition;
516f034231aSEd Maste     FileSpecList m_filenames;
517344a3780SDimitry Andric     uint32_t m_line_num = 0;
518344a3780SDimitry Andric     uint32_t m_column = 0;
519f034231aSEd Maste     std::vector<std::string> m_func_names;
520205afe67SEd Maste     std::vector<std::string> m_breakpoint_names;
521344a3780SDimitry Andric     lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
522f034231aSEd Maste     std::string m_func_regexp;
523f034231aSEd Maste     std::string m_source_text_regexp;
524f034231aSEd Maste     FileSpecList m_modules;
525344a3780SDimitry Andric     lldb::addr_t m_load_addr = 0;
526f3fbd1c0SDimitry Andric     lldb::addr_t m_offset_addr;
527344a3780SDimitry Andric     bool m_catch_bp = false;
528344a3780SDimitry Andric     bool m_throw_bp = true;
529344a3780SDimitry Andric     bool m_hardware = false; // Request to use hardware breakpoints
530344a3780SDimitry Andric     lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
531344a3780SDimitry Andric     lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
532344a3780SDimitry Andric     LazyBool m_skip_prologue = eLazyBoolCalculate;
533344a3780SDimitry Andric     bool m_all_files = false;
5345e95aa85SEd Maste     Args m_exception_extra_args;
535344a3780SDimitry Andric     LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
536f3fbd1c0SDimitry Andric     std::unordered_set<std::string> m_source_regex_func_names;
53794994d37SDimitry Andric     std::string m_current_key;
538f034231aSEd Maste   };
539f034231aSEd Maste 
540f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)541b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
542ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
543f034231aSEd Maste 
544f034231aSEd Maste     // The following are the various types of breakpoints that could be set:
545f034231aSEd Maste     //   1).  -f -l -p  [-s -g]   (setting breakpoint by source location)
546f034231aSEd Maste     //   2).  -a  [-s -g]         (setting breakpoint by address)
547f034231aSEd Maste     //   3).  -n  [-s -g]         (setting breakpoint by function name)
54814f1b3e8SDimitry Andric     //   4).  -r  [-s -g]         (setting breakpoint by function name regular
54914f1b3e8SDimitry Andric     //   expression)
55014f1b3e8SDimitry Andric     //   5).  -p -f               (setting a breakpoint by comparing a reg-exp
55114f1b3e8SDimitry Andric     //   to source text)
55214f1b3e8SDimitry Andric     //   6).  -E [-w -h]          (setting a breakpoint for exceptions for a
55314f1b3e8SDimitry Andric     //   given language.)
554f034231aSEd Maste 
555f034231aSEd Maste     BreakpointSetType break_type = eSetTypeInvalid;
556f034231aSEd Maste 
557706b4fc4SDimitry Andric     if (!m_python_class_options.GetName().empty())
55894994d37SDimitry Andric       break_type = eSetTypeScripted;
55994994d37SDimitry Andric     else if (m_options.m_line_num != 0)
560f034231aSEd Maste       break_type = eSetTypeFileAndLine;
561f034231aSEd Maste     else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
562f034231aSEd Maste       break_type = eSetTypeAddress;
563f034231aSEd Maste     else if (!m_options.m_func_names.empty())
564f034231aSEd Maste       break_type = eSetTypeFunctionName;
565f034231aSEd Maste     else if (!m_options.m_func_regexp.empty())
566f034231aSEd Maste       break_type = eSetTypeFunctionRegexp;
567f034231aSEd Maste     else if (!m_options.m_source_text_regexp.empty())
568f034231aSEd Maste       break_type = eSetTypeSourceRegexp;
5695e95aa85SEd Maste     else if (m_options.m_exception_language != eLanguageTypeUnknown)
570f034231aSEd Maste       break_type = eSetTypeException;
571f034231aSEd Maste 
572ef5d0b5eSDimitry Andric     BreakpointSP bp_sp = nullptr;
573f034231aSEd Maste     FileSpec module_spec;
574f034231aSEd Maste     const bool internal = false;
575f034231aSEd Maste 
57614f1b3e8SDimitry Andric     // If the user didn't specify skip-prologue, having an offset should turn
57714f1b3e8SDimitry Andric     // that off.
57814f1b3e8SDimitry Andric     if (m_options.m_offset_addr != 0 &&
57914f1b3e8SDimitry Andric         m_options.m_skip_prologue == eLazyBoolCalculate)
580f3fbd1c0SDimitry Andric       m_options.m_skip_prologue = eLazyBoolNo;
581f3fbd1c0SDimitry Andric 
58214f1b3e8SDimitry Andric     switch (break_type) {
583f034231aSEd Maste     case eSetTypeFileAndLine: // Breakpoint by source position
584f034231aSEd Maste     {
585f034231aSEd Maste       FileSpec file;
586f034231aSEd Maste       const size_t num_files = m_options.m_filenames.GetSize();
58714f1b3e8SDimitry Andric       if (num_files == 0) {
58814f1b3e8SDimitry Andric         if (!GetDefaultFile(target, file, result)) {
589f034231aSEd Maste           result.AppendError("No file supplied and no default file available.");
590b1c73532SDimitry Andric           return;
591f034231aSEd Maste         }
59214f1b3e8SDimitry Andric       } else if (num_files > 1) {
59314f1b3e8SDimitry Andric         result.AppendError("Only one file at a time is allowed for file and "
59414f1b3e8SDimitry Andric                            "line breakpoints.");
595b1c73532SDimitry Andric         return;
59614f1b3e8SDimitry Andric       } else
597f034231aSEd Maste         file = m_options.m_filenames.GetFileSpecAtIndex(0);
598f034231aSEd Maste 
599f034231aSEd Maste       // Only check for inline functions if
600f034231aSEd Maste       LazyBool check_inlines = eLazyBoolCalculate;
601f034231aSEd Maste 
602ead24645SDimitry Andric       bp_sp = target.CreateBreakpoint(
603ead24645SDimitry Andric           &(m_options.m_modules), file, m_options.m_line_num,
604ead24645SDimitry Andric           m_options.m_column, m_options.m_offset_addr, check_inlines,
605ead24645SDimitry Andric           m_options.m_skip_prologue, internal, m_options.m_hardware,
606ef5d0b5eSDimitry Andric           m_options.m_move_to_nearest_code);
60714f1b3e8SDimitry Andric     } break;
608f034231aSEd Maste 
609f034231aSEd Maste     case eSetTypeAddress: // Breakpoint by address
610e81d9d49SDimitry Andric     {
61114f1b3e8SDimitry Andric       // If a shared library has been specified, make an lldb_private::Address
612ef5d0b5eSDimitry Andric       // with the library, and use that.  That way the address breakpoint
613ef5d0b5eSDimitry Andric       //  will track the load location of the library.
614e81d9d49SDimitry Andric       size_t num_modules_specified = m_options.m_modules.GetSize();
61514f1b3e8SDimitry Andric       if (num_modules_specified == 1) {
616b1c73532SDimitry Andric         const FileSpec &file_spec =
617b1c73532SDimitry Andric             m_options.m_modules.GetFileSpecAtIndex(0);
618ead24645SDimitry Andric         bp_sp = target.CreateAddressInModuleBreakpoint(
619ead24645SDimitry Andric             m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
62014f1b3e8SDimitry Andric       } else if (num_modules_specified == 0) {
621ead24645SDimitry Andric         bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
622ef5d0b5eSDimitry Andric                                         m_options.m_hardware);
62314f1b3e8SDimitry Andric       } else {
62414f1b3e8SDimitry Andric         result.AppendError("Only one shared library can be specified for "
62514f1b3e8SDimitry Andric                            "address breakpoints.");
626b1c73532SDimitry Andric         return;
627e81d9d49SDimitry Andric       }
628f034231aSEd Maste       break;
629e81d9d49SDimitry Andric     }
630f034231aSEd Maste     case eSetTypeFunctionName: // Breakpoint by function name
631f034231aSEd Maste     {
63294994d37SDimitry Andric       FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
633f034231aSEd Maste 
634f034231aSEd Maste       if (name_type_mask == 0)
635f034231aSEd Maste         name_type_mask = eFunctionNameTypeAuto;
636f034231aSEd Maste 
637ead24645SDimitry Andric       bp_sp = target.CreateBreakpoint(
638ead24645SDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames),
639ead24645SDimitry Andric           m_options.m_func_names, name_type_mask, m_options.m_language,
640ead24645SDimitry Andric           m_options.m_offset_addr, m_options.m_skip_prologue, internal,
641ef5d0b5eSDimitry Andric           m_options.m_hardware);
64214f1b3e8SDimitry Andric     } break;
643f034231aSEd Maste 
64414f1b3e8SDimitry Andric     case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
64514f1b3e8SDimitry Andric                                  // name
646f034231aSEd Maste     {
64714f1b3e8SDimitry Andric       RegularExpression regexp(m_options.m_func_regexp);
648ead24645SDimitry Andric       if (llvm::Error err = regexp.GetError()) {
64914f1b3e8SDimitry Andric         result.AppendErrorWithFormat(
650cfca06d7SDimitry Andric             "Function name regular expression could not be compiled: %s",
651ead24645SDimitry Andric             llvm::toString(std::move(err)).c_str());
652cfca06d7SDimitry Andric         // Check if the incorrect regex looks like a globbing expression and
653cfca06d7SDimitry Andric         // warn the user about it.
654cfca06d7SDimitry Andric         if (!m_options.m_func_regexp.empty()) {
655cfca06d7SDimitry Andric           if (m_options.m_func_regexp[0] == '*' ||
656cfca06d7SDimitry Andric               m_options.m_func_regexp[0] == '?')
657cfca06d7SDimitry Andric             result.AppendWarning(
658cfca06d7SDimitry Andric                 "Function name regex does not accept glob patterns.");
659cfca06d7SDimitry Andric         }
660b1c73532SDimitry Andric         return;
661f034231aSEd Maste       }
662f034231aSEd Maste 
663ead24645SDimitry Andric       bp_sp = target.CreateFuncRegexBreakpoint(
664ead24645SDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
665ead24645SDimitry Andric           m_options.m_language, m_options.m_skip_prologue, internal,
666ef5d0b5eSDimitry Andric           m_options.m_hardware);
667706b4fc4SDimitry Andric     } break;
668f034231aSEd Maste     case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
669f034231aSEd Maste     {
670f034231aSEd Maste       const size_t num_files = m_options.m_filenames.GetSize();
671f034231aSEd Maste 
67214f1b3e8SDimitry Andric       if (num_files == 0 && !m_options.m_all_files) {
673f034231aSEd Maste         FileSpec file;
67414f1b3e8SDimitry Andric         if (!GetDefaultFile(target, file, result)) {
67514f1b3e8SDimitry Andric           result.AppendError(
67614f1b3e8SDimitry Andric               "No files provided and could not find default file.");
677b1c73532SDimitry Andric           return;
67814f1b3e8SDimitry Andric         } else {
679f034231aSEd Maste           m_options.m_filenames.Append(file);
680f034231aSEd Maste         }
681f034231aSEd Maste       }
682f034231aSEd Maste 
68314f1b3e8SDimitry Andric       RegularExpression regexp(m_options.m_source_text_regexp);
684ead24645SDimitry Andric       if (llvm::Error err = regexp.GetError()) {
68514f1b3e8SDimitry Andric         result.AppendErrorWithFormat(
68614f1b3e8SDimitry Andric             "Source text regular expression could not be compiled: \"%s\"",
687ead24645SDimitry Andric             llvm::toString(std::move(err)).c_str());
688b1c73532SDimitry Andric         return;
689f034231aSEd Maste       }
690ead24645SDimitry Andric       bp_sp = target.CreateSourceRegexBreakpoint(
691ead24645SDimitry Andric           &(m_options.m_modules), &(m_options.m_filenames),
692ead24645SDimitry Andric           m_options.m_source_regex_func_names, std::move(regexp), internal,
693ead24645SDimitry Andric           m_options.m_hardware, m_options.m_move_to_nearest_code);
69414f1b3e8SDimitry Andric     } break;
69514f1b3e8SDimitry Andric     case eSetTypeException: {
696b76161e4SDimitry Andric       Status precond_error;
697ead24645SDimitry Andric       bp_sp = target.CreateExceptionBreakpoint(
698ead24645SDimitry Andric           m_options.m_exception_language, m_options.m_catch_bp,
699ead24645SDimitry Andric           m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
700ef5d0b5eSDimitry Andric           &precond_error);
70114f1b3e8SDimitry Andric       if (precond_error.Fail()) {
70214f1b3e8SDimitry Andric         result.AppendErrorWithFormat(
70314f1b3e8SDimitry Andric             "Error setting extra exception arguments: %s",
7045e95aa85SEd Maste             precond_error.AsCString());
705ead24645SDimitry Andric         target.RemoveBreakpointByID(bp_sp->GetID());
706b1c73532SDimitry Andric         return;
7075e95aa85SEd Maste       }
70814f1b3e8SDimitry Andric     } break;
70994994d37SDimitry Andric     case eSetTypeScripted: {
71094994d37SDimitry Andric 
71194994d37SDimitry Andric       Status error;
712ead24645SDimitry Andric       bp_sp = target.CreateScriptedBreakpoint(
713706b4fc4SDimitry Andric           m_python_class_options.GetName().c_str(), &(m_options.m_modules),
714ead24645SDimitry Andric           &(m_options.m_filenames), false, m_options.m_hardware,
715ead24645SDimitry Andric           m_python_class_options.GetStructuredData(), &error);
71694994d37SDimitry Andric       if (error.Fail()) {
71794994d37SDimitry Andric         result.AppendErrorWithFormat(
718706b4fc4SDimitry Andric             "Error setting extra exception arguments: %s", error.AsCString());
719ead24645SDimitry Andric         target.RemoveBreakpointByID(bp_sp->GetID());
720b1c73532SDimitry Andric         return;
72194994d37SDimitry Andric       }
72294994d37SDimitry Andric     } break;
723f034231aSEd Maste     default:
724f034231aSEd Maste       break;
725f034231aSEd Maste     }
726f034231aSEd Maste 
727f034231aSEd Maste     // Now set the various options that were passed in:
728ef5d0b5eSDimitry Andric     if (bp_sp) {
729344a3780SDimitry Andric       bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
730f034231aSEd Maste 
73114f1b3e8SDimitry Andric       if (!m_options.m_breakpoint_names.empty()) {
732b76161e4SDimitry Andric         Status name_error;
73314f1b3e8SDimitry Andric         for (auto name : m_options.m_breakpoint_names) {
734ead24645SDimitry Andric           target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
73514f1b3e8SDimitry Andric           if (name_error.Fail()) {
73614f1b3e8SDimitry Andric             result.AppendErrorWithFormat("Invalid breakpoint name: %s",
73714f1b3e8SDimitry Andric                                          name.c_str());
738ead24645SDimitry Andric             target.RemoveBreakpointByID(bp_sp->GetID());
739b1c73532SDimitry Andric             return;
74014f1b3e8SDimitry Andric           }
74114f1b3e8SDimitry Andric         }
742205afe67SEd Maste       }
743f034231aSEd Maste     }
744f034231aSEd Maste 
745ef5d0b5eSDimitry Andric     if (bp_sp) {
746f034231aSEd Maste       Stream &output_stream = result.GetOutputStream();
747f034231aSEd Maste       const bool show_locations = false;
748ef5d0b5eSDimitry Andric       bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
74914f1b3e8SDimitry Andric                             show_locations);
750ead24645SDimitry Andric       if (&target == &GetDummyTarget())
75114f1b3e8SDimitry Andric         output_stream.Printf("Breakpoint set in dummy target, will get copied "
75214f1b3e8SDimitry Andric                              "into future targets.\n");
75314f1b3e8SDimitry Andric       else {
754f73363f1SDimitry Andric         // Don't print out this warning for exception breakpoints.  They can
755f73363f1SDimitry Andric         // get set before the target is set, but we won't know how to actually
756f73363f1SDimitry Andric         // set the breakpoint till we run.
757ef5d0b5eSDimitry Andric         if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
75814f1b3e8SDimitry Andric           output_stream.Printf("WARNING:  Unable to resolve breakpoint to any "
75914f1b3e8SDimitry Andric                                "actual locations.\n");
760205afe67SEd Maste         }
761205afe67SEd Maste       }
762f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
763ef5d0b5eSDimitry Andric     } else if (!bp_sp) {
764f034231aSEd Maste       result.AppendError("Breakpoint creation failed: No breakpoint created.");
765f034231aSEd Maste     }
766f034231aSEd Maste   }
767f034231aSEd Maste 
768f034231aSEd Maste private:
GetDefaultFile(Target & target,FileSpec & file,CommandReturnObject & result)769ead24645SDimitry Andric   bool GetDefaultFile(Target &target, FileSpec &file,
77014f1b3e8SDimitry Andric                       CommandReturnObject &result) {
771f034231aSEd Maste     uint32_t default_line;
772f73363f1SDimitry Andric     // First use the Source Manager's default file. Then use the current stack
773f73363f1SDimitry Andric     // frame's file.
774ead24645SDimitry Andric     if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
775f034231aSEd Maste       StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
77614f1b3e8SDimitry Andric       if (cur_frame == nullptr) {
77714f1b3e8SDimitry Andric         result.AppendError(
77814f1b3e8SDimitry Andric             "No selected frame to use to find the default file.");
779f034231aSEd Maste         return false;
78014f1b3e8SDimitry Andric       } else if (!cur_frame->HasDebugInformation()) {
78114f1b3e8SDimitry Andric         result.AppendError("Cannot use the selected frame to find the default "
78214f1b3e8SDimitry Andric                            "file, it has no debug info.");
783f034231aSEd Maste         return false;
78414f1b3e8SDimitry Andric       } else {
78514f1b3e8SDimitry Andric         const SymbolContext &sc =
78614f1b3e8SDimitry Andric             cur_frame->GetSymbolContext(eSymbolContextLineEntry);
787ac9a064cSDimitry Andric         if (sc.line_entry.GetFile()) {
788ac9a064cSDimitry Andric           file = sc.line_entry.GetFile();
78914f1b3e8SDimitry Andric         } else {
79014f1b3e8SDimitry Andric           result.AppendError("Can't find the file for the selected frame to "
79114f1b3e8SDimitry Andric                              "use as the default file.");
792f034231aSEd Maste           return false;
793f034231aSEd Maste         }
794f034231aSEd Maste       }
795f034231aSEd Maste     }
796f034231aSEd Maste     return true;
797f034231aSEd Maste   }
798f034231aSEd Maste 
799ef5d0b5eSDimitry Andric   BreakpointOptionGroup m_bp_opts;
800ef5d0b5eSDimitry Andric   BreakpointDummyOptionGroup m_dummy_options;
801ead24645SDimitry Andric   OptionGroupPythonClassWithDict m_python_class_options;
802f034231aSEd Maste   CommandOptions m_options;
803ef5d0b5eSDimitry Andric   OptionGroupOptions m_all_options;
804f034231aSEd Maste };
805f3fbd1c0SDimitry Andric 
806f034231aSEd Maste // CommandObjectBreakpointModify
807f034231aSEd Maste #pragma mark Modify
808f034231aSEd Maste 
80914f1b3e8SDimitry Andric class CommandObjectBreakpointModify : public CommandObjectParsed {
810f034231aSEd Maste public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)81114f1b3e8SDimitry Andric   CommandObjectBreakpointModify(CommandInterpreter &interpreter)
81214f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint modify",
81314f1b3e8SDimitry Andric                             "Modify the options on a breakpoint or set of "
81414f1b3e8SDimitry Andric                             "breakpoints in the executable.  "
81514f1b3e8SDimitry Andric                             "If no breakpoint is specified, acts on the last "
81614f1b3e8SDimitry Andric                             "created breakpoint.  "
81714f1b3e8SDimitry Andric                             "With the exception of -e, -d and -i, passing an "
81814f1b3e8SDimitry Andric                             "empty argument clears the modification.",
8196f8fc217SDimitry Andric                             nullptr) {
820ac9a064cSDimitry Andric     CommandObject::AddIDsArgumentData(eBreakpointArgs);
821ef5d0b5eSDimitry Andric 
822ef5d0b5eSDimitry Andric     m_options.Append(&m_bp_opts,
823ef5d0b5eSDimitry Andric                      LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
824ef5d0b5eSDimitry Andric                      LLDB_OPT_SET_ALL);
825ef5d0b5eSDimitry Andric     m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
826ef5d0b5eSDimitry Andric     m_options.Finalize();
827f034231aSEd Maste   }
828f034231aSEd Maste 
829f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointModify() override = default;
830f034231aSEd Maste 
831cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)832cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
833cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
8347fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
8357fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
836cfca06d7SDimitry Andric   }
837cfca06d7SDimitry Andric 
GetOptions()83814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
839f034231aSEd Maste 
840f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)841b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
842ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
843f034231aSEd Maste 
844f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
845ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
846f034231aSEd Maste 
847f034231aSEd Maste     BreakpointIDList valid_bp_ids;
848f034231aSEd Maste 
84914f1b3e8SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
850ead24645SDimitry Andric         command, &target, result, &valid_bp_ids,
851ef5d0b5eSDimitry Andric         BreakpointName::Permissions::PermissionKinds::disablePerm);
852f034231aSEd Maste 
85314f1b3e8SDimitry Andric     if (result.Succeeded()) {
854f034231aSEd Maste       const size_t count = valid_bp_ids.GetSize();
85514f1b3e8SDimitry Andric       for (size_t i = 0; i < count; ++i) {
856f034231aSEd Maste         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
857f034231aSEd Maste 
85814f1b3e8SDimitry Andric         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
85914f1b3e8SDimitry Andric           Breakpoint *bp =
860ead24645SDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
86114f1b3e8SDimitry Andric           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
86214f1b3e8SDimitry Andric             BreakpointLocation *location =
86314f1b3e8SDimitry Andric                 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
864ef5d0b5eSDimitry Andric             if (location)
865344a3780SDimitry Andric               location->GetLocationOptions().CopyOverSetOptions(
866706b4fc4SDimitry Andric                   m_bp_opts.GetBreakpointOptions());
86714f1b3e8SDimitry Andric           } else {
868344a3780SDimitry Andric             bp->GetOptions().CopyOverSetOptions(
869706b4fc4SDimitry Andric                 m_bp_opts.GetBreakpointOptions());
870f034231aSEd Maste           }
871f034231aSEd Maste         }
872f034231aSEd Maste       }
873f034231aSEd Maste     }
874f034231aSEd Maste   }
875f034231aSEd Maste 
876f034231aSEd Maste private:
877ef5d0b5eSDimitry Andric   BreakpointOptionGroup m_bp_opts;
878ef5d0b5eSDimitry Andric   BreakpointDummyOptionGroup m_dummy_opts;
879ef5d0b5eSDimitry Andric   OptionGroupOptions m_options;
880f034231aSEd Maste };
881f034231aSEd Maste 
882f034231aSEd Maste // CommandObjectBreakpointEnable
883f034231aSEd Maste #pragma mark Enable
884f034231aSEd Maste 
88514f1b3e8SDimitry Andric class CommandObjectBreakpointEnable : public CommandObjectParsed {
886f034231aSEd Maste public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)88714f1b3e8SDimitry Andric   CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
88814f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "enable",
88914f1b3e8SDimitry Andric                             "Enable the specified disabled breakpoint(s). If "
89014f1b3e8SDimitry Andric                             "no breakpoints are specified, enable all of them.",
89114f1b3e8SDimitry Andric                             nullptr) {
892ac9a064cSDimitry Andric     CommandObject::AddIDsArgumentData(eBreakpointArgs);
893f034231aSEd Maste   }
894f034231aSEd Maste 
895f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointEnable() override = default;
896f034231aSEd Maste 
897cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)898cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
899cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
9007fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
9017fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
902cfca06d7SDimitry Andric   }
903cfca06d7SDimitry Andric 
904f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)905b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
906ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
907f034231aSEd Maste 
908f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
909ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
910f034231aSEd Maste 
911ead24645SDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
912f034231aSEd Maste 
913f034231aSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
914f034231aSEd Maste 
91514f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
916f034231aSEd Maste       result.AppendError("No breakpoints exist to be enabled.");
917b1c73532SDimitry Andric       return;
918f034231aSEd Maste     }
919f034231aSEd Maste 
92014f1b3e8SDimitry Andric     if (command.empty()) {
921f034231aSEd Maste       // No breakpoint selected; enable all currently set breakpoints.
922ead24645SDimitry Andric       target.EnableAllowedBreakpoints();
92314f1b3e8SDimitry Andric       result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
92414f1b3e8SDimitry Andric                                      " breakpoints)\n",
92514f1b3e8SDimitry Andric                                      (uint64_t)num_breakpoints);
926f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
92714f1b3e8SDimitry Andric     } else {
928f034231aSEd Maste       // Particular breakpoint selected; enable that breakpoint.
929f034231aSEd Maste       BreakpointIDList valid_bp_ids;
93014f1b3e8SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
931ead24645SDimitry Andric           command, &target, result, &valid_bp_ids,
932ef5d0b5eSDimitry Andric           BreakpointName::Permissions::PermissionKinds::disablePerm);
933f034231aSEd Maste 
93414f1b3e8SDimitry Andric       if (result.Succeeded()) {
935f034231aSEd Maste         int enable_count = 0;
936f034231aSEd Maste         int loc_count = 0;
937f034231aSEd Maste         const size_t count = valid_bp_ids.GetSize();
93814f1b3e8SDimitry Andric         for (size_t i = 0; i < count; ++i) {
939f034231aSEd Maste           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
940f034231aSEd Maste 
94114f1b3e8SDimitry Andric           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
94214f1b3e8SDimitry Andric             Breakpoint *breakpoint =
943ead24645SDimitry Andric                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
94414f1b3e8SDimitry Andric             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
94514f1b3e8SDimitry Andric               BreakpointLocation *location =
94614f1b3e8SDimitry Andric                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
94714f1b3e8SDimitry Andric               if (location) {
948f034231aSEd Maste                 location->SetEnabled(true);
949f034231aSEd Maste                 ++loc_count;
950f034231aSEd Maste               }
95114f1b3e8SDimitry Andric             } else {
952f034231aSEd Maste               breakpoint->SetEnabled(true);
953f034231aSEd Maste               ++enable_count;
954f034231aSEd Maste             }
955f034231aSEd Maste           }
956f034231aSEd Maste         }
95714f1b3e8SDimitry Andric         result.AppendMessageWithFormat("%d breakpoints enabled.\n",
95814f1b3e8SDimitry Andric                                        enable_count + loc_count);
959f034231aSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
960f034231aSEd Maste       }
961f034231aSEd Maste     }
962f034231aSEd Maste   }
963f034231aSEd Maste };
964f034231aSEd Maste 
965f034231aSEd Maste // CommandObjectBreakpointDisable
966f034231aSEd Maste #pragma mark Disable
967f034231aSEd Maste 
96814f1b3e8SDimitry Andric class CommandObjectBreakpointDisable : public CommandObjectParsed {
969f034231aSEd Maste public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)970f3fbd1c0SDimitry Andric   CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
97114f1b3e8SDimitry Andric       : CommandObjectParsed(
97214f1b3e8SDimitry Andric             interpreter, "breakpoint disable",
97314f1b3e8SDimitry Andric             "Disable the specified breakpoint(s) without deleting "
974f3fbd1c0SDimitry Andric             "them.  If none are specified, disable all "
975f3fbd1c0SDimitry Andric             "breakpoints.",
97614f1b3e8SDimitry Andric             nullptr) {
97714f1b3e8SDimitry Andric     SetHelpLong(
97814f1b3e8SDimitry Andric         "Disable the specified breakpoint(s) without deleting them.  \
979f3fbd1c0SDimitry Andric If none are specified, disable all breakpoints."
980f3fbd1c0SDimitry Andric         R"(
981027f1c96SDimitry Andric 
982f3fbd1c0SDimitry Andric )"
983f3fbd1c0SDimitry Andric         "Note: disabling a breakpoint will cause none of its locations to be hit \
984f3fbd1c0SDimitry Andric regardless of whether individual locations are enabled or disabled.  After the sequence:"
985f3fbd1c0SDimitry Andric         R"(
986027f1c96SDimitry Andric 
987027f1c96SDimitry Andric     (lldb) break disable 1
988027f1c96SDimitry Andric     (lldb) break enable 1.1
989027f1c96SDimitry Andric 
990027f1c96SDimitry Andric execution will NOT stop at location 1.1.  To achieve that, type:
991027f1c96SDimitry Andric 
992027f1c96SDimitry Andric     (lldb) break disable 1.*
993027f1c96SDimitry Andric     (lldb) break enable 1.1
994027f1c96SDimitry Andric 
995f3fbd1c0SDimitry Andric )"
996f3fbd1c0SDimitry Andric         "The first command disables all locations for breakpoint 1, \
997f3fbd1c0SDimitry Andric the second re-enables the first location.");
998f034231aSEd Maste 
999ac9a064cSDimitry Andric     CommandObject::AddIDsArgumentData(eBreakpointArgs);
1000f034231aSEd Maste   }
1001f034231aSEd Maste 
1002f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointDisable() override = default;
1003f034231aSEd Maste 
1004cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1005cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1006cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
10077fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
10087fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1009cfca06d7SDimitry Andric   }
1010cfca06d7SDimitry Andric 
1011f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1012b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1013ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
1014f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1015ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1016f034231aSEd Maste 
1017ead24645SDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
1018f034231aSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
1019f034231aSEd Maste 
102014f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1021f034231aSEd Maste       result.AppendError("No breakpoints exist to be disabled.");
1022b1c73532SDimitry Andric       return;
1023f034231aSEd Maste     }
1024f034231aSEd Maste 
102514f1b3e8SDimitry Andric     if (command.empty()) {
1026f034231aSEd Maste       // No breakpoint selected; disable all currently set breakpoints.
1027ead24645SDimitry Andric       target.DisableAllowedBreakpoints();
102814f1b3e8SDimitry Andric       result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
102914f1b3e8SDimitry Andric                                      " breakpoints)\n",
103014f1b3e8SDimitry Andric                                      (uint64_t)num_breakpoints);
1031f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
103214f1b3e8SDimitry Andric     } else {
1033f034231aSEd Maste       // Particular breakpoint selected; disable that breakpoint.
1034f034231aSEd Maste       BreakpointIDList valid_bp_ids;
1035f034231aSEd Maste 
103614f1b3e8SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1037ead24645SDimitry Andric           command, &target, result, &valid_bp_ids,
1038ef5d0b5eSDimitry Andric           BreakpointName::Permissions::PermissionKinds::disablePerm);
1039f034231aSEd Maste 
104014f1b3e8SDimitry Andric       if (result.Succeeded()) {
1041f034231aSEd Maste         int disable_count = 0;
1042f034231aSEd Maste         int loc_count = 0;
1043f034231aSEd Maste         const size_t count = valid_bp_ids.GetSize();
104414f1b3e8SDimitry Andric         for (size_t i = 0; i < count; ++i) {
1045f034231aSEd Maste           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1046f034231aSEd Maste 
104714f1b3e8SDimitry Andric           if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
104814f1b3e8SDimitry Andric             Breakpoint *breakpoint =
1049ead24645SDimitry Andric                 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
105014f1b3e8SDimitry Andric             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
105114f1b3e8SDimitry Andric               BreakpointLocation *location =
105214f1b3e8SDimitry Andric                   breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
105314f1b3e8SDimitry Andric               if (location) {
1054f034231aSEd Maste                 location->SetEnabled(false);
1055f034231aSEd Maste                 ++loc_count;
1056f034231aSEd Maste               }
105714f1b3e8SDimitry Andric             } else {
1058f034231aSEd Maste               breakpoint->SetEnabled(false);
1059f034231aSEd Maste               ++disable_count;
1060f034231aSEd Maste             }
1061f034231aSEd Maste           }
1062f034231aSEd Maste         }
106314f1b3e8SDimitry Andric         result.AppendMessageWithFormat("%d breakpoints disabled.\n",
106414f1b3e8SDimitry Andric                                        disable_count + loc_count);
1065f034231aSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1066f034231aSEd Maste       }
1067f034231aSEd Maste     }
1068f034231aSEd Maste   }
1069f034231aSEd Maste };
1070f034231aSEd Maste 
1071f034231aSEd Maste // CommandObjectBreakpointList
107214f1b3e8SDimitry Andric 
107314f1b3e8SDimitry Andric #pragma mark List::CommandOptions
10745f29bb8aSDimitry Andric #define LLDB_OPTIONS_breakpoint_list
10755f29bb8aSDimitry Andric #include "CommandOptions.inc"
107614f1b3e8SDimitry Andric 
1077f034231aSEd Maste #pragma mark List
1078f034231aSEd Maste 
107914f1b3e8SDimitry Andric class CommandObjectBreakpointList : public CommandObjectParsed {
1080f034231aSEd Maste public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)108114f1b3e8SDimitry Andric   CommandObjectBreakpointList(CommandInterpreter &interpreter)
108214f1b3e8SDimitry Andric       : CommandObjectParsed(
108314f1b3e8SDimitry Andric             interpreter, "breakpoint list",
1084f034231aSEd Maste             "List some or all breakpoints at configurable levels of detail.",
10856f8fc217SDimitry Andric             nullptr) {
1086f034231aSEd Maste     CommandArgumentEntry arg;
1087f034231aSEd Maste     CommandArgumentData bp_id_arg;
1088f034231aSEd Maste 
1089f034231aSEd Maste     // Define the first (and only) variant of this arg.
1090ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1091f034231aSEd Maste   }
1092f034231aSEd Maste 
1093f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointList() override = default;
1094f034231aSEd Maste 
GetOptions()109514f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
1096f034231aSEd Maste 
109714f1b3e8SDimitry Andric   class CommandOptions : public Options {
1098f034231aSEd Maste   public:
1099145449b1SDimitry Andric     CommandOptions() = default;
1100f034231aSEd Maste 
1101f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
1102f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1103b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
110414f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
1105b76161e4SDimitry Andric       Status error;
1106f034231aSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1107f034231aSEd Maste 
110814f1b3e8SDimitry Andric       switch (short_option) {
1109f034231aSEd Maste       case 'b':
1110f034231aSEd Maste         m_level = lldb::eDescriptionLevelBrief;
1111f034231aSEd Maste         break;
1112205afe67SEd Maste       case 'D':
1113205afe67SEd Maste         m_use_dummy = true;
1114205afe67SEd Maste         break;
1115f034231aSEd Maste       case 'f':
1116f034231aSEd Maste         m_level = lldb::eDescriptionLevelFull;
1117f034231aSEd Maste         break;
1118f034231aSEd Maste       case 'v':
1119f034231aSEd Maste         m_level = lldb::eDescriptionLevelVerbose;
1120f034231aSEd Maste         break;
1121f034231aSEd Maste       case 'i':
1122f034231aSEd Maste         m_internal = true;
1123f034231aSEd Maste         break;
1124f034231aSEd Maste       default:
1125ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
1126f034231aSEd Maste       }
1127f034231aSEd Maste 
1128f034231aSEd Maste       return error;
1129f034231aSEd Maste     }
1130f034231aSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)113114f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1132f034231aSEd Maste       m_level = lldb::eDescriptionLevelFull;
1133f034231aSEd Maste       m_internal = false;
1134205afe67SEd Maste       m_use_dummy = false;
1135f034231aSEd Maste     }
1136f034231aSEd Maste 
GetDefinitions()113714f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1138e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_list_options);
1139f034231aSEd Maste     }
1140f034231aSEd Maste 
1141f034231aSEd Maste     // Instance variables to hold the values for command options.
1142f034231aSEd Maste 
1143344a3780SDimitry Andric     lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
1144f034231aSEd Maste 
1145f034231aSEd Maste     bool m_internal;
1146344a3780SDimitry Andric     bool m_use_dummy = false;
1147f034231aSEd Maste   };
1148f034231aSEd Maste 
1149f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1150b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1151ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1152f034231aSEd Maste 
115314f1b3e8SDimitry Andric     const BreakpointList &breakpoints =
1154ead24645SDimitry Andric         target.GetBreakpointList(m_options.m_internal);
1155f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1156ead24645SDimitry Andric     target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1157f034231aSEd Maste 
1158f034231aSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
1159f034231aSEd Maste 
116014f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1161f034231aSEd Maste       result.AppendMessage("No breakpoints currently set.");
1162f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1163b1c73532SDimitry Andric       return;
1164f034231aSEd Maste     }
1165f034231aSEd Maste 
1166f034231aSEd Maste     Stream &output_stream = result.GetOutputStream();
1167f034231aSEd Maste 
116814f1b3e8SDimitry Andric     if (command.empty()) {
1169f034231aSEd Maste       // No breakpoint selected; show info about all currently set breakpoints.
1170f034231aSEd Maste       result.AppendMessage("Current breakpoints:");
117114f1b3e8SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
1172f034231aSEd Maste         Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1173ef5d0b5eSDimitry Andric         if (breakpoint->AllowList())
1174ef5d0b5eSDimitry Andric           AddBreakpointDescription(&output_stream, breakpoint,
1175ef5d0b5eSDimitry Andric                                    m_options.m_level);
1176f034231aSEd Maste       }
1177f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
117814f1b3e8SDimitry Andric     } else {
1179f034231aSEd Maste       // Particular breakpoints selected; show info about that breakpoint.
1180f034231aSEd Maste       BreakpointIDList valid_bp_ids;
118114f1b3e8SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1182ead24645SDimitry Andric           command, &target, result, &valid_bp_ids,
1183ef5d0b5eSDimitry Andric           BreakpointName::Permissions::PermissionKinds::listPerm);
1184f034231aSEd Maste 
118514f1b3e8SDimitry Andric       if (result.Succeeded()) {
118614f1b3e8SDimitry Andric         for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1187f034231aSEd Maste           BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
118814f1b3e8SDimitry Andric           Breakpoint *breakpoint =
1189ead24645SDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
119014f1b3e8SDimitry Andric           AddBreakpointDescription(&output_stream, breakpoint,
119114f1b3e8SDimitry Andric                                    m_options.m_level);
1192f034231aSEd Maste         }
1193f034231aSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
119414f1b3e8SDimitry Andric       } else {
1195f3fbd1c0SDimitry Andric         result.AppendError("Invalid breakpoint ID.");
1196f034231aSEd Maste       }
1197f034231aSEd Maste     }
1198f034231aSEd Maste   }
1199f034231aSEd Maste 
1200f034231aSEd Maste private:
1201f034231aSEd Maste   CommandOptions m_options;
1202f034231aSEd Maste };
1203f034231aSEd Maste 
1204f034231aSEd Maste // CommandObjectBreakpointClear
120514f1b3e8SDimitry Andric #pragma mark Clear::CommandOptions
120614f1b3e8SDimitry Andric 
1207ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_clear
1208ead24645SDimitry Andric #include "CommandOptions.inc"
120914f1b3e8SDimitry Andric 
1210f034231aSEd Maste #pragma mark Clear
1211f034231aSEd Maste 
121214f1b3e8SDimitry Andric class CommandObjectBreakpointClear : public CommandObjectParsed {
1213f034231aSEd Maste public:
12145f29bb8aSDimitry Andric   enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1215f034231aSEd Maste 
CommandObjectBreakpointClear(CommandInterpreter & interpreter)1216f3fbd1c0SDimitry Andric   CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1217f3fbd1c0SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint clear",
121814f1b3e8SDimitry Andric                             "Delete or disable breakpoints matching the "
121914f1b3e8SDimitry Andric                             "specified source file and line.",
12206f8fc217SDimitry Andric                             "breakpoint clear <cmd-options>") {}
1221f034231aSEd Maste 
1222f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointClear() override = default;
1223f034231aSEd Maste 
GetOptions()122414f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
1225f034231aSEd Maste 
122614f1b3e8SDimitry Andric   class CommandOptions : public Options {
1227f034231aSEd Maste   public:
1228145449b1SDimitry Andric     CommandOptions() = default;
1229f034231aSEd Maste 
1230f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
1231f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1232b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
123314f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
1234b76161e4SDimitry Andric       Status error;
1235f034231aSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1236f034231aSEd Maste 
123714f1b3e8SDimitry Andric       switch (short_option) {
1238f034231aSEd Maste       case 'f':
1239cfca06d7SDimitry Andric         m_filename.assign(std::string(option_arg));
1240f034231aSEd Maste         break;
1241f034231aSEd Maste 
1242f034231aSEd Maste       case 'l':
124314f1b3e8SDimitry Andric         option_arg.getAsInteger(0, m_line_num);
1244f034231aSEd Maste         break;
1245f034231aSEd Maste 
1246f034231aSEd Maste       default:
1247ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
1248f034231aSEd Maste       }
1249f034231aSEd Maste 
1250f034231aSEd Maste       return error;
1251f034231aSEd Maste     }
1252f034231aSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)125314f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1254f034231aSEd Maste       m_filename.clear();
1255f034231aSEd Maste       m_line_num = 0;
1256f034231aSEd Maste     }
1257f034231aSEd Maste 
GetDefinitions()125814f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1259e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_clear_options);
1260f034231aSEd Maste     }
1261f034231aSEd Maste 
1262f034231aSEd Maste     // Instance variables to hold the values for command options.
1263f034231aSEd Maste 
1264f034231aSEd Maste     std::string m_filename;
1265344a3780SDimitry Andric     uint32_t m_line_num = 0;
1266f034231aSEd Maste   };
1267f034231aSEd Maste 
1268f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1269b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1270ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
1271f034231aSEd Maste 
1272f73363f1SDimitry Andric     // The following are the various types of breakpoints that could be
1273f73363f1SDimitry Andric     // cleared:
1274f034231aSEd Maste     //   1). -f -l (clearing breakpoint by source location)
1275f034231aSEd Maste 
1276f034231aSEd Maste     BreakpointClearType break_type = eClearTypeInvalid;
1277f034231aSEd Maste 
1278f034231aSEd Maste     if (m_options.m_line_num != 0)
1279f034231aSEd Maste       break_type = eClearTypeFileAndLine;
1280f034231aSEd Maste 
1281f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1282ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1283f034231aSEd Maste 
1284ead24645SDimitry Andric     BreakpointList &breakpoints = target.GetBreakpointList();
1285f034231aSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
1286f034231aSEd Maste 
1287f034231aSEd Maste     // Early return if there's no breakpoint at all.
128814f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1289f034231aSEd Maste       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1290b1c73532SDimitry Andric       return;
1291f034231aSEd Maste     }
1292f034231aSEd Maste 
1293f034231aSEd Maste     // Find matching breakpoints and delete them.
1294f034231aSEd Maste 
1295f034231aSEd Maste     // First create a copy of all the IDs.
1296f034231aSEd Maste     std::vector<break_id_t> BreakIDs;
1297f034231aSEd Maste     for (size_t i = 0; i < num_breakpoints; ++i)
1298f3fbd1c0SDimitry Andric       BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1299f034231aSEd Maste 
1300f034231aSEd Maste     int num_cleared = 0;
1301f034231aSEd Maste     StreamString ss;
130214f1b3e8SDimitry Andric     switch (break_type) {
1303f034231aSEd Maste     case eClearTypeFileAndLine: // Breakpoint by source position
1304f034231aSEd Maste     {
1305f034231aSEd Maste       const ConstString filename(m_options.m_filename.c_str());
1306f034231aSEd Maste       BreakpointLocationCollection loc_coll;
1307f034231aSEd Maste 
130814f1b3e8SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
1309f034231aSEd Maste         Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1310f034231aSEd Maste 
131114f1b3e8SDimitry Andric         if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
131214f1b3e8SDimitry Andric           // If the collection size is 0, it's a full match and we can just
131314f1b3e8SDimitry Andric           // remove the breakpoint.
131414f1b3e8SDimitry Andric           if (loc_coll.GetSize() == 0) {
1315f034231aSEd Maste             bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1316f034231aSEd Maste             ss.EOL();
1317ead24645SDimitry Andric             target.RemoveBreakpointByID(bp->GetID());
1318f034231aSEd Maste             ++num_cleared;
1319f034231aSEd Maste           }
1320f034231aSEd Maste         }
1321f034231aSEd Maste       }
132214f1b3e8SDimitry Andric     } break;
1323f034231aSEd Maste 
1324f034231aSEd Maste     default:
1325f034231aSEd Maste       break;
1326f034231aSEd Maste     }
1327f034231aSEd Maste 
132814f1b3e8SDimitry Andric     if (num_cleared > 0) {
1329f034231aSEd Maste       Stream &output_stream = result.GetOutputStream();
1330f034231aSEd Maste       output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
133114f1b3e8SDimitry Andric       output_stream << ss.GetString();
1332f034231aSEd Maste       output_stream.EOL();
1333f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
133414f1b3e8SDimitry Andric     } else {
1335f034231aSEd Maste       result.AppendError("Breakpoint clear: No breakpoint cleared.");
1336f034231aSEd Maste     }
1337f034231aSEd Maste   }
1338f034231aSEd Maste 
1339f034231aSEd Maste private:
1340f034231aSEd Maste   CommandOptions m_options;
1341f034231aSEd Maste };
1342f034231aSEd Maste 
1343f034231aSEd Maste // CommandObjectBreakpointDelete
1344ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_delete
1345ead24645SDimitry Andric #include "CommandOptions.inc"
134614f1b3e8SDimitry Andric 
1347f034231aSEd Maste #pragma mark Delete
1348f034231aSEd Maste 
134914f1b3e8SDimitry Andric class CommandObjectBreakpointDelete : public CommandObjectParsed {
1350f034231aSEd Maste public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)135114f1b3e8SDimitry Andric   CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
135214f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint delete",
135314f1b3e8SDimitry Andric                             "Delete the specified breakpoint(s).  If no "
135414f1b3e8SDimitry Andric                             "breakpoints are specified, delete them all.",
13556f8fc217SDimitry Andric                             nullptr) {
1356ac9a064cSDimitry Andric     CommandObject::AddIDsArgumentData(eBreakpointArgs);
1357f034231aSEd Maste   }
1358f034231aSEd Maste 
1359f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointDelete() override = default;
1360f034231aSEd Maste 
1361cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1362cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1363cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
13647fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
13657fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1366cfca06d7SDimitry Andric   }
1367cfca06d7SDimitry Andric 
GetOptions()136814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
1369205afe67SEd Maste 
137014f1b3e8SDimitry Andric   class CommandOptions : public Options {
1371205afe67SEd Maste   public:
1372145449b1SDimitry Andric     CommandOptions() = default;
1373205afe67SEd Maste 
1374f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
1375205afe67SEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1376b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
137714f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
1378b76161e4SDimitry Andric       Status error;
1379205afe67SEd Maste       const int short_option = m_getopt_table[option_idx].val;
1380205afe67SEd Maste 
138114f1b3e8SDimitry Andric       switch (short_option) {
1382205afe67SEd Maste       case 'f':
1383205afe67SEd Maste         m_force = true;
1384205afe67SEd Maste         break;
1385205afe67SEd Maste 
1386205afe67SEd Maste       case 'D':
1387205afe67SEd Maste         m_use_dummy = true;
1388205afe67SEd Maste         break;
1389205afe67SEd Maste 
1390b60736ecSDimitry Andric       case 'd':
1391b60736ecSDimitry Andric         m_delete_disabled = true;
1392b60736ecSDimitry Andric         break;
1393b60736ecSDimitry Andric 
1394205afe67SEd Maste       default:
1395ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
1396205afe67SEd Maste       }
1397205afe67SEd Maste 
1398205afe67SEd Maste       return error;
1399205afe67SEd Maste     }
1400205afe67SEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)140114f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1402205afe67SEd Maste       m_use_dummy = false;
1403205afe67SEd Maste       m_force = false;
1404b60736ecSDimitry Andric       m_delete_disabled = false;
1405205afe67SEd Maste     }
1406205afe67SEd Maste 
GetDefinitions()140714f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1408e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_delete_options);
1409205afe67SEd Maste     }
1410205afe67SEd Maste 
1411205afe67SEd Maste     // Instance variables to hold the values for command options.
1412344a3780SDimitry Andric     bool m_use_dummy = false;
1413344a3780SDimitry Andric     bool m_force = false;
1414344a3780SDimitry Andric     bool m_delete_disabled = false;
1415205afe67SEd Maste   };
1416205afe67SEd Maste 
1417f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1418b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1419ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
1420b60736ecSDimitry Andric     result.Clear();
1421f034231aSEd Maste 
1422f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1423ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1424f034231aSEd Maste 
1425b60736ecSDimitry Andric     BreakpointList &breakpoints = target.GetBreakpointList();
1426f034231aSEd Maste 
1427f034231aSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
1428f034231aSEd Maste 
142914f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1430f034231aSEd Maste       result.AppendError("No breakpoints exist to be deleted.");
1431b1c73532SDimitry Andric       return;
1432f034231aSEd Maste     }
1433f034231aSEd Maste 
1434344a3780SDimitry Andric     // Handle the delete all breakpoints case:
1435b60736ecSDimitry Andric     if (command.empty() && !m_options.m_delete_disabled) {
143614f1b3e8SDimitry Andric       if (!m_options.m_force &&
143714f1b3e8SDimitry Andric           !m_interpreter.Confirm(
143814f1b3e8SDimitry Andric               "About to delete all breakpoints, do you want to do that?",
143914f1b3e8SDimitry Andric               true)) {
1440f034231aSEd Maste         result.AppendMessage("Operation cancelled...");
144114f1b3e8SDimitry Andric       } else {
1442ead24645SDimitry Andric         target.RemoveAllowedBreakpoints();
144314f1b3e8SDimitry Andric         result.AppendMessageWithFormat(
144414f1b3e8SDimitry Andric             "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
144514f1b3e8SDimitry Andric             (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1446f034231aSEd Maste       }
1447f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1448b1c73532SDimitry Andric       return;
1449344a3780SDimitry Andric     }
1450344a3780SDimitry Andric 
1451344a3780SDimitry Andric     // Either we have some kind of breakpoint specification(s),
1452344a3780SDimitry Andric     // or we are handling "break disable --deleted".  Gather the list
1453344a3780SDimitry Andric     // of breakpoints to delete here, the we'll delete them below.
1454f034231aSEd Maste     BreakpointIDList valid_bp_ids;
1455b60736ecSDimitry Andric 
1456b60736ecSDimitry Andric     if (m_options.m_delete_disabled) {
1457b60736ecSDimitry Andric       BreakpointIDList excluded_bp_ids;
1458b60736ecSDimitry Andric 
1459b60736ecSDimitry Andric       if (!command.empty()) {
1460b60736ecSDimitry Andric         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1461b60736ecSDimitry Andric             command, &target, result, &excluded_bp_ids,
1462b60736ecSDimitry Andric             BreakpointName::Permissions::PermissionKinds::deletePerm);
1463344a3780SDimitry Andric         if (!result.Succeeded())
1464b1c73532SDimitry Andric           return;
1465b60736ecSDimitry Andric       }
1466344a3780SDimitry Andric 
1467b60736ecSDimitry Andric       for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1468b60736ecSDimitry Andric         if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1469b60736ecSDimitry Andric           BreakpointID bp_id(breakpoint_sp->GetID());
1470ac9a064cSDimitry Andric           if (!excluded_bp_ids.Contains(bp_id))
1471ac9a064cSDimitry Andric             valid_bp_ids.AddBreakpointID(bp_id);
1472b60736ecSDimitry Andric         }
1473b60736ecSDimitry Andric       }
1474b60736ecSDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1475b60736ecSDimitry Andric         result.AppendError("No disabled breakpoints.");
1476b1c73532SDimitry Andric         return;
1477b60736ecSDimitry Andric       }
1478b60736ecSDimitry Andric     } else {
147914f1b3e8SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1480ead24645SDimitry Andric           command, &target, result, &valid_bp_ids,
1481ef5d0b5eSDimitry Andric           BreakpointName::Permissions::PermissionKinds::deletePerm);
1482344a3780SDimitry Andric       if (!result.Succeeded())
1483b1c73532SDimitry Andric         return;
1484b60736ecSDimitry Andric     }
1485f034231aSEd Maste 
1486f034231aSEd Maste     int delete_count = 0;
1487f034231aSEd Maste     int disable_count = 0;
1488f034231aSEd Maste     const size_t count = valid_bp_ids.GetSize();
148914f1b3e8SDimitry Andric     for (size_t i = 0; i < count; ++i) {
1490f034231aSEd Maste       BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1491f034231aSEd Maste 
149214f1b3e8SDimitry Andric       if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
149314f1b3e8SDimitry Andric         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
149414f1b3e8SDimitry Andric           Breakpoint *breakpoint =
1495ead24645SDimitry Andric               target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
149614f1b3e8SDimitry Andric           BreakpointLocation *location =
149714f1b3e8SDimitry Andric               breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
149814f1b3e8SDimitry Andric           // It makes no sense to try to delete individual locations, so we
149914f1b3e8SDimitry Andric           // disable them instead.
150014f1b3e8SDimitry Andric           if (location) {
1501f034231aSEd Maste             location->SetEnabled(false);
1502f034231aSEd Maste             ++disable_count;
1503f034231aSEd Maste           }
150414f1b3e8SDimitry Andric         } else {
1505ead24645SDimitry Andric           target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1506f034231aSEd Maste           ++delete_count;
1507f034231aSEd Maste         }
1508f034231aSEd Maste       }
1509f034231aSEd Maste     }
151014f1b3e8SDimitry Andric     result.AppendMessageWithFormat(
151114f1b3e8SDimitry Andric         "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1512f034231aSEd Maste         delete_count, disable_count);
1513f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1514f034231aSEd Maste   }
1515f3fbd1c0SDimitry Andric 
1516205afe67SEd Maste private:
1517205afe67SEd Maste   CommandOptions m_options;
1518f034231aSEd Maste };
1519f034231aSEd Maste 
1520205afe67SEd Maste // CommandObjectBreakpointName
1521ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_name
1522ead24645SDimitry Andric #include "CommandOptions.inc"
1523205afe67SEd Maste 
152414f1b3e8SDimitry Andric class BreakpointNameOptionGroup : public OptionGroup {
1525205afe67SEd Maste public:
BreakpointNameOptionGroup()152614f1b3e8SDimitry Andric   BreakpointNameOptionGroup()
15276f8fc217SDimitry Andric       : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
1528205afe67SEd Maste 
1529f3fbd1c0SDimitry Andric   ~BreakpointNameOptionGroup() override = default;
1530205afe67SEd Maste 
GetDefinitions()153114f1b3e8SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1532e3b55780SDimitry Andric     return llvm::ArrayRef(g_breakpoint_name_options);
1533205afe67SEd Maste   }
1534205afe67SEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1535b76161e4SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
153614f1b3e8SDimitry Andric                         ExecutionContext *execution_context) override {
1537b76161e4SDimitry Andric     Status error;
1538205afe67SEd Maste     const int short_option = g_breakpoint_name_options[option_idx].short_option;
1539ac9a064cSDimitry Andric     const char *long_option = g_breakpoint_name_options[option_idx].long_option;
1540205afe67SEd Maste 
154114f1b3e8SDimitry Andric     switch (short_option) {
1542205afe67SEd Maste     case 'N':
154314f1b3e8SDimitry Andric       if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
154414f1b3e8SDimitry Andric           error.Success())
154514f1b3e8SDimitry Andric         m_name.SetValueFromString(option_arg);
1546205afe67SEd Maste       break;
1547205afe67SEd Maste     case 'B':
154814f1b3e8SDimitry Andric       if (m_breakpoint.SetValueFromString(option_arg).Fail())
1549ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
1550ac9a064cSDimitry Andric                                          g_int_parsing_error_message);
1551205afe67SEd Maste       break;
1552205afe67SEd Maste     case 'D':
155314f1b3e8SDimitry Andric       if (m_use_dummy.SetValueFromString(option_arg).Fail())
1554ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
1555ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
1556205afe67SEd Maste       break;
1557ef5d0b5eSDimitry Andric     case 'H':
1558ef5d0b5eSDimitry Andric       m_help_string.SetValueFromString(option_arg);
1559ef5d0b5eSDimitry Andric       break;
1560205afe67SEd Maste 
1561205afe67SEd Maste     default:
1562ead24645SDimitry Andric       llvm_unreachable("Unimplemented option");
1563205afe67SEd Maste     }
1564205afe67SEd Maste     return error;
1565205afe67SEd Maste   }
1566205afe67SEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)156714f1b3e8SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
1568205afe67SEd Maste     m_name.Clear();
1569205afe67SEd Maste     m_breakpoint.Clear();
1570205afe67SEd Maste     m_use_dummy.Clear();
1571205afe67SEd Maste     m_use_dummy.SetDefaultValue(false);
1572ef5d0b5eSDimitry Andric     m_help_string.Clear();
1573205afe67SEd Maste   }
1574205afe67SEd Maste 
1575205afe67SEd Maste   OptionValueString m_name;
1576205afe67SEd Maste   OptionValueUInt64 m_breakpoint;
1577205afe67SEd Maste   OptionValueBoolean m_use_dummy;
1578ef5d0b5eSDimitry Andric   OptionValueString m_help_string;
1579ef5d0b5eSDimitry Andric };
1580ef5d0b5eSDimitry Andric 
1581ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_access
1582ead24645SDimitry Andric #include "CommandOptions.inc"
1583ef5d0b5eSDimitry Andric 
158494994d37SDimitry Andric class BreakpointAccessOptionGroup : public OptionGroup {
1585ef5d0b5eSDimitry Andric public:
1586145449b1SDimitry Andric   BreakpointAccessOptionGroup() = default;
1587ef5d0b5eSDimitry Andric 
1588ef5d0b5eSDimitry Andric   ~BreakpointAccessOptionGroup() override = default;
1589ef5d0b5eSDimitry Andric 
GetDefinitions()1590ef5d0b5eSDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1591e3b55780SDimitry Andric     return llvm::ArrayRef(g_breakpoint_access_options);
1592ef5d0b5eSDimitry Andric   }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1593ef5d0b5eSDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1594ef5d0b5eSDimitry Andric                         ExecutionContext *execution_context) override {
1595ef5d0b5eSDimitry Andric     Status error;
1596706b4fc4SDimitry Andric     const int short_option =
1597706b4fc4SDimitry Andric         g_breakpoint_access_options[option_idx].short_option;
1598ac9a064cSDimitry Andric     const char *long_option =
1599ac9a064cSDimitry Andric         g_breakpoint_access_options[option_idx].long_option;
1600ef5d0b5eSDimitry Andric 
1601ef5d0b5eSDimitry Andric     switch (short_option) {
1602ef5d0b5eSDimitry Andric     case 'L': {
1603ef5d0b5eSDimitry Andric       bool value, success;
1604f73363f1SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1605ef5d0b5eSDimitry Andric       if (success) {
1606ef5d0b5eSDimitry Andric         m_permissions.SetAllowList(value);
1607ef5d0b5eSDimitry Andric       } else
1608ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
1609ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
1610ef5d0b5eSDimitry Andric     } break;
1611ef5d0b5eSDimitry Andric     case 'A': {
1612ef5d0b5eSDimitry Andric       bool value, success;
1613f73363f1SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1614ef5d0b5eSDimitry Andric       if (success) {
1615ef5d0b5eSDimitry Andric         m_permissions.SetAllowDisable(value);
1616ef5d0b5eSDimitry Andric       } else
1617ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
1618ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
1619ef5d0b5eSDimitry Andric     } break;
1620ef5d0b5eSDimitry Andric     case 'D': {
1621ef5d0b5eSDimitry Andric       bool value, success;
1622f73363f1SDimitry Andric       value = OptionArgParser::ToBoolean(option_arg, false, &success);
1623ef5d0b5eSDimitry Andric       if (success) {
1624ef5d0b5eSDimitry Andric         m_permissions.SetAllowDelete(value);
1625ef5d0b5eSDimitry Andric       } else
1626ac9a064cSDimitry Andric         error = CreateOptionParsingError(option_arg, short_option, long_option,
1627ac9a064cSDimitry Andric                                          g_bool_parsing_error_message);
1628ef5d0b5eSDimitry Andric     } break;
1629ead24645SDimitry Andric     default:
1630ead24645SDimitry Andric       llvm_unreachable("Unimplemented option");
1631ef5d0b5eSDimitry Andric     }
1632ef5d0b5eSDimitry Andric 
1633ef5d0b5eSDimitry Andric     return error;
1634ef5d0b5eSDimitry Andric   }
1635ef5d0b5eSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1636706b4fc4SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {}
1637ef5d0b5eSDimitry Andric 
GetPermissions() const1638706b4fc4SDimitry Andric   const BreakpointName::Permissions &GetPermissions() const {
1639ef5d0b5eSDimitry Andric     return m_permissions;
1640ef5d0b5eSDimitry Andric   }
1641ef5d0b5eSDimitry Andric   BreakpointName::Permissions m_permissions;
1642ef5d0b5eSDimitry Andric };
1643ef5d0b5eSDimitry Andric 
1644ef5d0b5eSDimitry Andric class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1645ef5d0b5eSDimitry Andric public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)1646ef5d0b5eSDimitry Andric   CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1647ef5d0b5eSDimitry Andric       : CommandObjectParsed(
1648706b4fc4SDimitry Andric             interpreter, "configure",
1649706b4fc4SDimitry Andric             "Configure the options for the breakpoint"
1650ef5d0b5eSDimitry Andric             " name provided.  "
1651ef5d0b5eSDimitry Andric             "If you provide a breakpoint id, the options will be copied from "
1652ef5d0b5eSDimitry Andric             "the breakpoint, otherwise only the options specified will be set "
1653ef5d0b5eSDimitry Andric             "on the name.",
1654ef5d0b5eSDimitry Andric             "breakpoint name configure <command-options> "
16556f8fc217SDimitry Andric             "<breakpoint-name-list>") {
1656ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeBreakpointName, eArgRepeatOptional);
1657ef5d0b5eSDimitry Andric 
1658706b4fc4SDimitry Andric     m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1659706b4fc4SDimitry Andric     m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1660ef5d0b5eSDimitry Andric                           LLDB_OPT_SET_ALL);
1661706b4fc4SDimitry Andric     m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1662ef5d0b5eSDimitry Andric                           LLDB_OPT_SET_ALL);
1663ef5d0b5eSDimitry Andric     m_option_group.Finalize();
1664ef5d0b5eSDimitry Andric   }
1665ef5d0b5eSDimitry Andric 
1666ef5d0b5eSDimitry Andric   ~CommandObjectBreakpointNameConfigure() override = default;
1667ef5d0b5eSDimitry Andric 
GetOptions()1668ef5d0b5eSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1669ef5d0b5eSDimitry Andric 
1670ef5d0b5eSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1671b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1672ef5d0b5eSDimitry Andric 
1673ef5d0b5eSDimitry Andric     const size_t argc = command.GetArgumentCount();
1674ef5d0b5eSDimitry Andric     if (argc == 0) {
1675ef5d0b5eSDimitry Andric       result.AppendError("No names provided.");
1676b1c73532SDimitry Andric       return;
1677ef5d0b5eSDimitry Andric     }
1678ef5d0b5eSDimitry Andric 
1679ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget(false);
1680ef5d0b5eSDimitry Andric 
1681ef5d0b5eSDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1682ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1683ef5d0b5eSDimitry Andric 
1684ef5d0b5eSDimitry Andric     // Make a pass through first to see that all the names are legal.
1685ef5d0b5eSDimitry Andric     for (auto &entry : command.entries()) {
1686ef5d0b5eSDimitry Andric       Status error;
1687706b4fc4SDimitry Andric       if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1688ef5d0b5eSDimitry Andric         result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1689ef5d0b5eSDimitry Andric                                      entry.c_str(), error.AsCString());
1690b1c73532SDimitry Andric         return;
1691ef5d0b5eSDimitry Andric       }
1692ef5d0b5eSDimitry Andric     }
1693f73363f1SDimitry Andric     // Now configure them, we already pre-checked the names so we don't need to
1694f73363f1SDimitry Andric     // check the error:
1695ef5d0b5eSDimitry Andric     BreakpointSP bp_sp;
1696706b4fc4SDimitry Andric     if (m_bp_id.m_breakpoint.OptionWasSet()) {
16977fa27ce4SDimitry Andric       lldb::break_id_t bp_id =
16987fa27ce4SDimitry Andric           m_bp_id.m_breakpoint.GetValueAs<uint64_t>().value_or(0);
1699ead24645SDimitry Andric       bp_sp = target.GetBreakpointByID(bp_id);
1700706b4fc4SDimitry Andric       if (!bp_sp) {
1701ef5d0b5eSDimitry Andric         result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1702ef5d0b5eSDimitry Andric                                       bp_id);
1703b1c73532SDimitry Andric         return;
1704ef5d0b5eSDimitry Andric       }
1705ef5d0b5eSDimitry Andric     }
1706ef5d0b5eSDimitry Andric 
1707ef5d0b5eSDimitry Andric     Status error;
1708ef5d0b5eSDimitry Andric     for (auto &entry : command.entries()) {
1709ef5d0b5eSDimitry Andric       ConstString name(entry.c_str());
1710ead24645SDimitry Andric       BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1711ef5d0b5eSDimitry Andric       if (!bp_name)
1712ef5d0b5eSDimitry Andric         continue;
1713ef5d0b5eSDimitry Andric       if (m_bp_id.m_help_string.OptionWasSet())
17147fa27ce4SDimitry Andric         bp_name->SetHelp(m_bp_id.m_help_string.GetValueAs<llvm::StringRef>()
17157fa27ce4SDimitry Andric                              .value_or("")
17167fa27ce4SDimitry Andric                              .str()
17177fa27ce4SDimitry Andric                              .c_str());
1718ef5d0b5eSDimitry Andric 
1719ef5d0b5eSDimitry Andric       if (bp_sp)
1720344a3780SDimitry Andric         target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1721ef5d0b5eSDimitry Andric                                        m_access_options.GetPermissions());
1722ef5d0b5eSDimitry Andric       else
1723ead24645SDimitry Andric         target.ConfigureBreakpointName(*bp_name,
1724ef5d0b5eSDimitry Andric                                        m_bp_opts.GetBreakpointOptions(),
1725ef5d0b5eSDimitry Andric                                        m_access_options.GetPermissions());
1726ef5d0b5eSDimitry Andric     }
1727ef5d0b5eSDimitry Andric   }
1728ef5d0b5eSDimitry Andric 
1729ef5d0b5eSDimitry Andric private:
1730ef5d0b5eSDimitry Andric   BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1731ef5d0b5eSDimitry Andric   BreakpointOptionGroup m_bp_opts;
1732ef5d0b5eSDimitry Andric   BreakpointAccessOptionGroup m_access_options;
1733ef5d0b5eSDimitry Andric   OptionGroupOptions m_option_group;
1734205afe67SEd Maste };
1735205afe67SEd Maste 
173614f1b3e8SDimitry Andric class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1737205afe67SEd Maste public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)173814f1b3e8SDimitry Andric   CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
173914f1b3e8SDimitry Andric       : CommandObjectParsed(
174014f1b3e8SDimitry Andric             interpreter, "add", "Add a name to the breakpoints provided.",
17416f8fc217SDimitry Andric             "breakpoint name add <command-options> <breakpoint-id-list>") {
1742ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1743205afe67SEd Maste 
1744205afe67SEd Maste     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1745205afe67SEd Maste     m_option_group.Finalize();
1746205afe67SEd Maste   }
1747205afe67SEd Maste 
1748f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointNameAdd() override = default;
1749205afe67SEd Maste 
1750cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1751cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1752cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
17537fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
17547fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1755cfca06d7SDimitry Andric   }
1756cfca06d7SDimitry Andric 
GetOptions()175714f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1758205afe67SEd Maste 
1759205afe67SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1760b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
176114f1b3e8SDimitry Andric     if (!m_name_options.m_name.OptionWasSet()) {
1762344a3780SDimitry Andric       result.AppendError("No name option provided.");
1763b1c73532SDimitry Andric       return;
1764205afe67SEd Maste     }
1765205afe67SEd Maste 
1766ead24645SDimitry Andric     Target &target =
176714f1b3e8SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1768205afe67SEd Maste 
1769f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1770ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1771205afe67SEd Maste 
1772ead24645SDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
1773205afe67SEd Maste 
1774205afe67SEd Maste     size_t num_breakpoints = breakpoints.GetSize();
177514f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1776344a3780SDimitry Andric       result.AppendError("No breakpoints, cannot add names.");
1777b1c73532SDimitry Andric       return;
1778205afe67SEd Maste     }
1779205afe67SEd Maste 
1780205afe67SEd Maste     // Particular breakpoint selected; disable that breakpoint.
1781205afe67SEd Maste     BreakpointIDList valid_bp_ids;
178214f1b3e8SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1783ead24645SDimitry Andric         command, &target, result, &valid_bp_ids,
1784ef5d0b5eSDimitry Andric         BreakpointName::Permissions::PermissionKinds::listPerm);
1785205afe67SEd Maste 
178614f1b3e8SDimitry Andric     if (result.Succeeded()) {
178714f1b3e8SDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1788344a3780SDimitry Andric         result.AppendError("No breakpoints specified, cannot add names.");
1789b1c73532SDimitry Andric         return;
1790205afe67SEd Maste       }
1791205afe67SEd Maste       size_t num_valid_ids = valid_bp_ids.GetSize();
1792ef5d0b5eSDimitry Andric       const char *bp_name = m_name_options.m_name.GetCurrentValue();
1793ef5d0b5eSDimitry Andric       Status error; // This error reports illegal names, but we've already
1794ef5d0b5eSDimitry Andric                     // checked that, so we don't need to check it again here.
179514f1b3e8SDimitry Andric       for (size_t index = 0; index < num_valid_ids; index++) {
179614f1b3e8SDimitry Andric         lldb::break_id_t bp_id =
179714f1b3e8SDimitry Andric             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1798205afe67SEd Maste         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1799ead24645SDimitry Andric         target.AddNameToBreakpoint(bp_sp, bp_name, error);
1800205afe67SEd Maste       }
1801205afe67SEd Maste     }
1802205afe67SEd Maste   }
1803205afe67SEd Maste 
1804205afe67SEd Maste private:
1805205afe67SEd Maste   BreakpointNameOptionGroup m_name_options;
1806205afe67SEd Maste   OptionGroupOptions m_option_group;
1807205afe67SEd Maste };
1808205afe67SEd Maste 
180914f1b3e8SDimitry Andric class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1810205afe67SEd Maste public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)181114f1b3e8SDimitry Andric   CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
181214f1b3e8SDimitry Andric       : CommandObjectParsed(
181314f1b3e8SDimitry Andric             interpreter, "delete",
1814205afe67SEd Maste             "Delete a name from the breakpoints provided.",
18156f8fc217SDimitry Andric             "breakpoint name delete <command-options> <breakpoint-id-list>") {
1816ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1817205afe67SEd Maste 
1818205afe67SEd Maste     m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1819205afe67SEd Maste     m_option_group.Finalize();
1820205afe67SEd Maste   }
1821205afe67SEd Maste 
1822f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointNameDelete() override = default;
1823205afe67SEd Maste 
1824cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1825cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1826cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
18277fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
18287fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1829cfca06d7SDimitry Andric   }
1830cfca06d7SDimitry Andric 
GetOptions()183114f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1832205afe67SEd Maste 
1833205afe67SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1834b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
183514f1b3e8SDimitry Andric     if (!m_name_options.m_name.OptionWasSet()) {
1836344a3780SDimitry Andric       result.AppendError("No name option provided.");
1837b1c73532SDimitry Andric       return;
1838205afe67SEd Maste     }
1839205afe67SEd Maste 
1840ead24645SDimitry Andric     Target &target =
184114f1b3e8SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1842205afe67SEd Maste 
1843f3fbd1c0SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
1844ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
1845205afe67SEd Maste 
1846ead24645SDimitry Andric     const BreakpointList &breakpoints = target.GetBreakpointList();
1847205afe67SEd Maste 
1848205afe67SEd Maste     size_t num_breakpoints = breakpoints.GetSize();
184914f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
1850344a3780SDimitry Andric       result.AppendError("No breakpoints, cannot delete names.");
1851b1c73532SDimitry Andric       return;
1852205afe67SEd Maste     }
1853205afe67SEd Maste 
1854205afe67SEd Maste     // Particular breakpoint selected; disable that breakpoint.
1855205afe67SEd Maste     BreakpointIDList valid_bp_ids;
185614f1b3e8SDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1857ead24645SDimitry Andric         command, &target, result, &valid_bp_ids,
1858ef5d0b5eSDimitry Andric         BreakpointName::Permissions::PermissionKinds::deletePerm);
1859205afe67SEd Maste 
186014f1b3e8SDimitry Andric     if (result.Succeeded()) {
186114f1b3e8SDimitry Andric       if (valid_bp_ids.GetSize() == 0) {
1862344a3780SDimitry Andric         result.AppendError("No breakpoints specified, cannot delete names.");
1863b1c73532SDimitry Andric         return;
1864205afe67SEd Maste       }
1865ef5d0b5eSDimitry Andric       ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1866205afe67SEd Maste       size_t num_valid_ids = valid_bp_ids.GetSize();
186714f1b3e8SDimitry Andric       for (size_t index = 0; index < num_valid_ids; index++) {
186814f1b3e8SDimitry Andric         lldb::break_id_t bp_id =
186914f1b3e8SDimitry Andric             valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1870205afe67SEd Maste         BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1871ead24645SDimitry Andric         target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1872205afe67SEd Maste       }
1873205afe67SEd Maste     }
1874205afe67SEd Maste   }
1875205afe67SEd Maste 
1876205afe67SEd Maste private:
1877205afe67SEd Maste   BreakpointNameOptionGroup m_name_options;
1878205afe67SEd Maste   OptionGroupOptions m_option_group;
1879205afe67SEd Maste };
1880205afe67SEd Maste 
188114f1b3e8SDimitry Andric class CommandObjectBreakpointNameList : public CommandObjectParsed {
1882205afe67SEd Maste public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)188314f1b3e8SDimitry Andric   CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
188414f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "list",
1885ef5d0b5eSDimitry Andric                             "List either the names for a breakpoint or info "
1886ef5d0b5eSDimitry Andric                             "about a given name.  With no arguments, lists all "
1887ef5d0b5eSDimitry Andric                             "names",
18886f8fc217SDimitry Andric                             "breakpoint name list <command-options>") {
1889ef5d0b5eSDimitry Andric     m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1890205afe67SEd Maste     m_option_group.Finalize();
1891205afe67SEd Maste   }
1892205afe67SEd Maste 
1893f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointNameList() override = default;
1894205afe67SEd Maste 
GetOptions()189514f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1896205afe67SEd Maste 
1897205afe67SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1898b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1899ead24645SDimitry Andric     Target &target =
190014f1b3e8SDimitry Andric         GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1901205afe67SEd Maste 
1902ef5d0b5eSDimitry Andric     std::vector<std::string> name_list;
1903ef5d0b5eSDimitry Andric     if (command.empty()) {
1904ead24645SDimitry Andric       target.GetBreakpointNames(name_list);
1905ef5d0b5eSDimitry Andric     } else {
1906706b4fc4SDimitry Andric       for (const Args::ArgEntry &arg : command) {
1907ef5d0b5eSDimitry Andric         name_list.push_back(arg.c_str());
1908ef5d0b5eSDimitry Andric       }
1909ef5d0b5eSDimitry Andric     }
1910ef5d0b5eSDimitry Andric 
1911ef5d0b5eSDimitry Andric     if (name_list.empty()) {
1912ef5d0b5eSDimitry Andric       result.AppendMessage("No breakpoint names found.");
1913ef5d0b5eSDimitry Andric     } else {
1914ef5d0b5eSDimitry Andric       for (const std::string &name_str : name_list) {
1915ef5d0b5eSDimitry Andric         const char *name = name_str.c_str();
1916ef5d0b5eSDimitry Andric         // First print out the options for the name:
1917ef5d0b5eSDimitry Andric         Status error;
1918ead24645SDimitry Andric         BreakpointName *bp_name =
1919ead24645SDimitry Andric             target.FindBreakpointName(ConstString(name), false, error);
1920706b4fc4SDimitry Andric         if (bp_name) {
1921ef5d0b5eSDimitry Andric           StreamString s;
1922ef5d0b5eSDimitry Andric           result.AppendMessageWithFormat("Name: %s\n", name);
1923706b4fc4SDimitry Andric           if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1924ef5d0b5eSDimitry Andric             result.AppendMessage(s.GetString());
1925ef5d0b5eSDimitry Andric           }
1926ef5d0b5eSDimitry Andric 
1927f3fbd1c0SDimitry Andric           std::unique_lock<std::recursive_mutex> lock;
1928ead24645SDimitry Andric           target.GetBreakpointList().GetListMutex(lock);
1929205afe67SEd Maste 
1930ead24645SDimitry Andric           BreakpointList &breakpoints = target.GetBreakpointList();
1931ef5d0b5eSDimitry Andric           bool any_set = false;
193214f1b3e8SDimitry Andric           for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
193314f1b3e8SDimitry Andric             if (bp_sp->MatchesName(name)) {
1934205afe67SEd Maste               StreamString s;
1935ef5d0b5eSDimitry Andric               any_set = true;
1936205afe67SEd Maste               bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1937205afe67SEd Maste               s.EOL();
193814f1b3e8SDimitry Andric               result.AppendMessage(s.GetString());
1939205afe67SEd Maste             }
1940205afe67SEd Maste           }
1941ef5d0b5eSDimitry Andric           if (!any_set)
1942ef5d0b5eSDimitry Andric             result.AppendMessage("No breakpoints using this name.");
194314f1b3e8SDimitry Andric         } else {
1944ef5d0b5eSDimitry Andric           result.AppendMessageWithFormat("Name: %s not found.\n", name);
1945205afe67SEd Maste         }
1946ef5d0b5eSDimitry Andric       }
1947205afe67SEd Maste     }
1948205afe67SEd Maste   }
1949205afe67SEd Maste 
1950205afe67SEd Maste private:
1951205afe67SEd Maste   BreakpointNameOptionGroup m_name_options;
1952205afe67SEd Maste   OptionGroupOptions m_option_group;
1953205afe67SEd Maste };
1954205afe67SEd Maste 
195514f1b3e8SDimitry Andric // CommandObjectBreakpointName
195614f1b3e8SDimitry Andric class CommandObjectBreakpointName : public CommandObjectMultiword {
1957205afe67SEd Maste public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)1958f3fbd1c0SDimitry Andric   CommandObjectBreakpointName(CommandInterpreter &interpreter)
195914f1b3e8SDimitry Andric       : CommandObjectMultiword(
1960145449b1SDimitry Andric             interpreter, "name", "Commands to manage breakpoint names") {
1961145449b1SDimitry Andric 
1962145449b1SDimitry Andric 
1963145449b1SDimitry Andric     SetHelpLong(
1964145449b1SDimitry Andric             R"(
1965145449b1SDimitry Andric Breakpoint names provide a general tagging mechanism for breakpoints.  Each
1966145449b1SDimitry Andric breakpoint name can be added to any number of breakpoints, and each breakpoint
1967145449b1SDimitry Andric can have any number of breakpoint names attached to it. For instance:
1968145449b1SDimitry Andric 
1969145449b1SDimitry Andric     (lldb) break name add -N MyName 1-10
1970145449b1SDimitry Andric 
1971145449b1SDimitry Andric adds the name MyName to breakpoints 1-10, and:
1972145449b1SDimitry Andric 
1973145449b1SDimitry Andric     (lldb) break set -n myFunc -N Name1 -N Name2
1974145449b1SDimitry Andric 
1975145449b1SDimitry Andric adds two names to the breakpoint set at myFunc.
1976145449b1SDimitry Andric 
1977145449b1SDimitry Andric They have a number of interrelated uses:
1978145449b1SDimitry Andric 
1979145449b1SDimitry Andric 1) They provide a stable way to refer to a breakpoint (e.g. in another
1980145449b1SDimitry Andric breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
1981145449b1SDimitry Andric it depends on the order of breakpoint creation.  Giving a name to the breakpoint
1982145449b1SDimitry Andric you want to act on, and then referring to it by name, is more robust:
1983145449b1SDimitry Andric 
1984145449b1SDimitry Andric     (lldb) break set -n myFunc -N BKPT1
1985145449b1SDimitry Andric     (lldb) break set -n myOtherFunc -C "break disable BKPT1"
1986145449b1SDimitry Andric 
1987145449b1SDimitry Andric 2) This is actually just a specific use of a more general feature of breakpoint
1988145449b1SDimitry Andric names.  The <breakpt-id-list> argument type used to specify one or more
1989145449b1SDimitry Andric breakpoints in most of the commands that deal with breakpoints also accepts
1990145449b1SDimitry Andric breakpoint names.  That allows you to refer to one breakpoint in a stable
1991145449b1SDimitry Andric manner, but also makes them a convenient grouping mechanism, allowing you to
1992145449b1SDimitry Andric easily act on a group of breakpoints by using their name, for instance disabling
1993145449b1SDimitry Andric them all in one action:
1994145449b1SDimitry Andric 
1995145449b1SDimitry Andric     (lldb) break set -n myFunc -N Group1
1996145449b1SDimitry Andric     (lldb) break set -n myOtherFunc -N Group1
1997145449b1SDimitry Andric     (lldb) break disable Group1
1998145449b1SDimitry Andric 
1999145449b1SDimitry Andric 3) But breakpoint names are also entities in their own right, and can be
2000145449b1SDimitry Andric configured with all the modifiable attributes of a breakpoint.  Then when you
2001145449b1SDimitry Andric add a breakpoint name to a breakpoint, the breakpoint will be configured to
2002145449b1SDimitry Andric match the state of the breakpoint name.  The link between the name and the
2003145449b1SDimitry Andric breakpoints sharing it remains live, so if you change the configuration on the
2004145449b1SDimitry Andric name, it will also change the configurations on the breakpoints:
2005145449b1SDimitry Andric 
2006145449b1SDimitry Andric     (lldb) break name configure -i 10 IgnoreSome
2007145449b1SDimitry Andric     (lldb) break set -n myFunc -N IgnoreSome
2008145449b1SDimitry Andric     (lldb) break list IgnoreSome
2009145449b1SDimitry Andric     2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2010145449b1SDimitry Andric       Names:
2011145449b1SDimitry Andric         IgnoreSome
2012145449b1SDimitry Andric     (lldb) break name configure -i 5 IgnoreSome
2013145449b1SDimitry Andric     (lldb) break list IgnoreSome
2014145449b1SDimitry Andric     2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2015145449b1SDimitry Andric       Names:
2016145449b1SDimitry Andric         IgnoreSome
2017145449b1SDimitry Andric 
2018145449b1SDimitry Andric Options that are not configured on a breakpoint name don't affect the value of
2019145449b1SDimitry Andric those options on the breakpoints they are added to.  So for instance, if Name1
2020145449b1SDimitry Andric has the -i option configured and Name2 the -c option, adding both names to a
2021145449b1SDimitry Andric breakpoint will set the -i option from Name1 and the -c option from Name2, and
2022145449b1SDimitry Andric the other options will be unaltered.
2023145449b1SDimitry Andric 
2024145449b1SDimitry Andric If you add multiple names to a breakpoint which have configured values for
2025145449b1SDimitry Andric the same option, the last name added's value wins.
2026145449b1SDimitry Andric 
2027145449b1SDimitry Andric The "liveness" of these settings is one way, from name to breakpoint.
2028145449b1SDimitry Andric If you use "break modify" to change an option that is also configured on a name
2029145449b1SDimitry Andric which that breakpoint has, the "break modify" command will override the setting
2030145449b1SDimitry Andric for that breakpoint, but won't change the value configured in the name or on the
2031145449b1SDimitry Andric other breakpoints sharing that name.
2032145449b1SDimitry Andric 
2033145449b1SDimitry Andric 4) Breakpoint names are also a convenient way to copy option sets from one
2034145449b1SDimitry Andric breakpoint to another.  Using the -B option to "breakpoint name configure" makes
2035145449b1SDimitry Andric a name configured with all the options of the original breakpoint.  Then
2036145449b1SDimitry Andric adding that name to another breakpoint copies over all the values from the
2037145449b1SDimitry Andric original breakpoint to the new one.
2038145449b1SDimitry Andric 
2039145449b1SDimitry Andric 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2040145449b1SDimitry Andric operations that act on all breakpoints: "break delete", "break disable" and
2041145449b1SDimitry Andric "break list".  You do that by specifying a "false" value for the
2042145449b1SDimitry Andric --allow-{list,delete,disable} options to "breakpoint name configure" and then
2043145449b1SDimitry Andric adding that name to a breakpoint.
2044145449b1SDimitry Andric 
2045145449b1SDimitry Andric This won't keep the breakpoint from being deleted or disabled if you refer to it
2046145449b1SDimitry Andric specifically by ID. The point of the feature is to make sure users don't
2047145449b1SDimitry Andric inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2048145449b1SDimitry Andric for its own purposes) as part of a "delete all" or "disable all" operation.  The
2049145449b1SDimitry Andric list hiding is because it's confusing for people to see breakpoints they
2050145449b1SDimitry Andric didn't set.
2051145449b1SDimitry Andric 
2052145449b1SDimitry Andric )");
205314f1b3e8SDimitry Andric     CommandObjectSP add_command_object(
205414f1b3e8SDimitry Andric         new CommandObjectBreakpointNameAdd(interpreter));
205514f1b3e8SDimitry Andric     CommandObjectSP delete_command_object(
205614f1b3e8SDimitry Andric         new CommandObjectBreakpointNameDelete(interpreter));
205714f1b3e8SDimitry Andric     CommandObjectSP list_command_object(
205814f1b3e8SDimitry Andric         new CommandObjectBreakpointNameList(interpreter));
2059ef5d0b5eSDimitry Andric     CommandObjectSP configure_command_object(
2060ef5d0b5eSDimitry Andric         new CommandObjectBreakpointNameConfigure(interpreter));
2061205afe67SEd Maste 
2062205afe67SEd Maste     LoadSubCommand("add", add_command_object);
2063205afe67SEd Maste     LoadSubCommand("delete", delete_command_object);
2064205afe67SEd Maste     LoadSubCommand("list", list_command_object);
2065ef5d0b5eSDimitry Andric     LoadSubCommand("configure", configure_command_object);
2066205afe67SEd Maste   }
2067205afe67SEd Maste 
2068f3fbd1c0SDimitry Andric   ~CommandObjectBreakpointName() override = default;
2069205afe67SEd Maste };
2070205afe67SEd Maste 
207114f1b3e8SDimitry Andric // CommandObjectBreakpointRead
207214f1b3e8SDimitry Andric #pragma mark Read::CommandOptions
2073ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_read
2074ead24645SDimitry Andric #include "CommandOptions.inc"
207514f1b3e8SDimitry Andric 
207614f1b3e8SDimitry Andric #pragma mark Read
207714f1b3e8SDimitry Andric 
207814f1b3e8SDimitry Andric class CommandObjectBreakpointRead : public CommandObjectParsed {
207914f1b3e8SDimitry Andric public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)208014f1b3e8SDimitry Andric   CommandObjectBreakpointRead(CommandInterpreter &interpreter)
208114f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint read",
208214f1b3e8SDimitry Andric                             "Read and set the breakpoints previously saved to "
208314f1b3e8SDimitry Andric                             "a file with \"breakpoint write\".  ",
20846f8fc217SDimitry Andric                             nullptr) {}
208514f1b3e8SDimitry Andric 
208614f1b3e8SDimitry Andric   ~CommandObjectBreakpointRead() override = default;
208714f1b3e8SDimitry Andric 
GetOptions()208814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
208914f1b3e8SDimitry Andric 
209014f1b3e8SDimitry Andric   class CommandOptions : public Options {
209114f1b3e8SDimitry Andric   public:
2092145449b1SDimitry Andric     CommandOptions() = default;
209314f1b3e8SDimitry Andric 
209414f1b3e8SDimitry Andric     ~CommandOptions() override = default;
209514f1b3e8SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2096b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
209714f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
2098b76161e4SDimitry Andric       Status error;
209914f1b3e8SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
2100ac9a064cSDimitry Andric       const char *long_option =
2101ac9a064cSDimitry Andric           m_getopt_table[option_idx].definition->long_option;
210214f1b3e8SDimitry Andric 
210314f1b3e8SDimitry Andric       switch (short_option) {
210414f1b3e8SDimitry Andric       case 'f':
2105cfca06d7SDimitry Andric         m_filename.assign(std::string(option_arg));
210614f1b3e8SDimitry Andric         break;
210714f1b3e8SDimitry Andric       case 'N': {
2108b76161e4SDimitry Andric         Status name_error;
210914f1b3e8SDimitry Andric         if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
211014f1b3e8SDimitry Andric                                                   name_error)) {
2111ac9a064cSDimitry Andric           error = CreateOptionParsingError(option_arg, short_option,
2112ac9a064cSDimitry Andric                                            long_option, name_error.AsCString());
211314f1b3e8SDimitry Andric         }
2114cfca06d7SDimitry Andric         m_names.push_back(std::string(option_arg));
211514f1b3e8SDimitry Andric         break;
211614f1b3e8SDimitry Andric       }
211714f1b3e8SDimitry Andric       default:
2118ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
211914f1b3e8SDimitry Andric       }
212014f1b3e8SDimitry Andric 
212114f1b3e8SDimitry Andric       return error;
212214f1b3e8SDimitry Andric     }
212314f1b3e8SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)212414f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
212514f1b3e8SDimitry Andric       m_filename.clear();
212614f1b3e8SDimitry Andric       m_names.clear();
212714f1b3e8SDimitry Andric     }
212814f1b3e8SDimitry Andric 
GetDefinitions()212914f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2130e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_read_options);
213114f1b3e8SDimitry Andric     }
213214f1b3e8SDimitry Andric 
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)2133b60736ecSDimitry Andric     void HandleOptionArgumentCompletion(
2134b60736ecSDimitry Andric         CompletionRequest &request, OptionElementVector &opt_element_vector,
2135b60736ecSDimitry Andric         int opt_element_index, CommandInterpreter &interpreter) override {
2136b60736ecSDimitry Andric       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2137b60736ecSDimitry Andric       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2138b60736ecSDimitry Andric 
2139b60736ecSDimitry Andric       switch (GetDefinitions()[opt_defs_index].short_option) {
2140b60736ecSDimitry Andric       case 'f':
21417fa27ce4SDimitry Andric         lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
21427fa27ce4SDimitry Andric             interpreter, lldb::eDiskFileCompletion, request, nullptr);
2143b60736ecSDimitry Andric         break;
2144b60736ecSDimitry Andric 
2145b60736ecSDimitry Andric       case 'N':
2146e3b55780SDimitry Andric         std::optional<FileSpec> file_spec;
2147b60736ecSDimitry Andric         const llvm::StringRef dash_f("-f");
2148b60736ecSDimitry Andric         for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2149b60736ecSDimitry Andric           if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2150b60736ecSDimitry Andric             file_spec.emplace(
2151b60736ecSDimitry Andric                 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2152b60736ecSDimitry Andric             break;
2153b60736ecSDimitry Andric           }
2154b60736ecSDimitry Andric         }
2155b60736ecSDimitry Andric         if (!file_spec)
2156b60736ecSDimitry Andric           return;
2157b60736ecSDimitry Andric 
2158b60736ecSDimitry Andric         FileSystem::Instance().Resolve(*file_spec);
2159b60736ecSDimitry Andric         Status error;
2160b60736ecSDimitry Andric         StructuredData::ObjectSP input_data_sp =
2161b60736ecSDimitry Andric             StructuredData::ParseJSONFromFile(*file_spec, error);
2162b60736ecSDimitry Andric         if (!error.Success())
2163b60736ecSDimitry Andric           return;
2164b60736ecSDimitry Andric 
2165b60736ecSDimitry Andric         StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2166b60736ecSDimitry Andric         if (!bkpt_array)
2167b60736ecSDimitry Andric           return;
2168b60736ecSDimitry Andric 
2169b60736ecSDimitry Andric         const size_t num_bkpts = bkpt_array->GetSize();
2170b60736ecSDimitry Andric         for (size_t i = 0; i < num_bkpts; i++) {
2171b60736ecSDimitry Andric           StructuredData::ObjectSP bkpt_object_sp =
2172b60736ecSDimitry Andric               bkpt_array->GetItemAtIndex(i);
2173b60736ecSDimitry Andric           if (!bkpt_object_sp)
2174b60736ecSDimitry Andric             return;
2175b60736ecSDimitry Andric 
2176b60736ecSDimitry Andric           StructuredData::Dictionary *bkpt_dict =
2177b60736ecSDimitry Andric               bkpt_object_sp->GetAsDictionary();
2178b60736ecSDimitry Andric           if (!bkpt_dict)
2179b60736ecSDimitry Andric             return;
2180b60736ecSDimitry Andric 
2181b60736ecSDimitry Andric           StructuredData::ObjectSP bkpt_data_sp =
2182b60736ecSDimitry Andric               bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2183b60736ecSDimitry Andric           if (!bkpt_data_sp)
2184b60736ecSDimitry Andric             return;
2185b60736ecSDimitry Andric 
2186b60736ecSDimitry Andric           bkpt_dict = bkpt_data_sp->GetAsDictionary();
2187b60736ecSDimitry Andric           if (!bkpt_dict)
2188b60736ecSDimitry Andric             return;
2189b60736ecSDimitry Andric 
2190b60736ecSDimitry Andric           StructuredData::Array *names_array;
2191b60736ecSDimitry Andric 
2192b60736ecSDimitry Andric           if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2193b60736ecSDimitry Andric             return;
2194b60736ecSDimitry Andric 
2195b60736ecSDimitry Andric           size_t num_names = names_array->GetSize();
2196b60736ecSDimitry Andric 
2197b60736ecSDimitry Andric           for (size_t i = 0; i < num_names; i++) {
2198b1c73532SDimitry Andric             if (std::optional<llvm::StringRef> maybe_name =
2199b1c73532SDimitry Andric                     names_array->GetItemAtIndexAsString(i))
2200b1c73532SDimitry Andric               request.TryCompleteCurrentArg(*maybe_name);
2201b60736ecSDimitry Andric           }
2202b60736ecSDimitry Andric         }
2203b60736ecSDimitry Andric       }
2204b60736ecSDimitry Andric     }
220514f1b3e8SDimitry Andric 
220614f1b3e8SDimitry Andric     std::string m_filename;
220714f1b3e8SDimitry Andric     std::vector<std::string> m_names;
220814f1b3e8SDimitry Andric   };
220914f1b3e8SDimitry Andric 
221014f1b3e8SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2211b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
2212ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
221314f1b3e8SDimitry Andric 
221414f1b3e8SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
2215ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
221614f1b3e8SDimitry Andric 
221794994d37SDimitry Andric     FileSpec input_spec(m_options.m_filename);
221894994d37SDimitry Andric     FileSystem::Instance().Resolve(input_spec);
221914f1b3e8SDimitry Andric     BreakpointIDList new_bps;
2220ead24645SDimitry Andric     Status error = target.CreateBreakpointsFromFile(input_spec,
2221ead24645SDimitry Andric                                                     m_options.m_names, new_bps);
222214f1b3e8SDimitry Andric 
222314f1b3e8SDimitry Andric     if (!error.Success()) {
222414f1b3e8SDimitry Andric       result.AppendError(error.AsCString());
2225b1c73532SDimitry Andric       return;
222614f1b3e8SDimitry Andric     }
222714f1b3e8SDimitry Andric 
222814f1b3e8SDimitry Andric     Stream &output_stream = result.GetOutputStream();
222914f1b3e8SDimitry Andric 
223014f1b3e8SDimitry Andric     size_t num_breakpoints = new_bps.GetSize();
223114f1b3e8SDimitry Andric     if (num_breakpoints == 0) {
223214f1b3e8SDimitry Andric       result.AppendMessage("No breakpoints added.");
223314f1b3e8SDimitry Andric     } else {
223414f1b3e8SDimitry Andric       // No breakpoint selected; show info about all currently set breakpoints.
223514f1b3e8SDimitry Andric       result.AppendMessage("New breakpoints:");
223614f1b3e8SDimitry Andric       for (size_t i = 0; i < num_breakpoints; ++i) {
223714f1b3e8SDimitry Andric         BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2238ead24645SDimitry Andric         Breakpoint *bp = target.GetBreakpointList()
223914f1b3e8SDimitry Andric                              .FindBreakpointByID(bp_id.GetBreakpointID())
224014f1b3e8SDimitry Andric                              .get();
224114f1b3e8SDimitry Andric         if (bp)
224214f1b3e8SDimitry Andric           bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
224314f1b3e8SDimitry Andric                              false);
224414f1b3e8SDimitry Andric       }
224514f1b3e8SDimitry Andric     }
224614f1b3e8SDimitry Andric   }
224714f1b3e8SDimitry Andric 
224814f1b3e8SDimitry Andric private:
224914f1b3e8SDimitry Andric   CommandOptions m_options;
225014f1b3e8SDimitry Andric };
225114f1b3e8SDimitry Andric 
225214f1b3e8SDimitry Andric // CommandObjectBreakpointWrite
225314f1b3e8SDimitry Andric #pragma mark Write::CommandOptions
2254ead24645SDimitry Andric #define LLDB_OPTIONS_breakpoint_write
2255ead24645SDimitry Andric #include "CommandOptions.inc"
225614f1b3e8SDimitry Andric 
225714f1b3e8SDimitry Andric #pragma mark Write
225814f1b3e8SDimitry Andric class CommandObjectBreakpointWrite : public CommandObjectParsed {
225914f1b3e8SDimitry Andric public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)226014f1b3e8SDimitry Andric   CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
226114f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "breakpoint write",
226214f1b3e8SDimitry Andric                             "Write the breakpoints listed to a file that can "
226314f1b3e8SDimitry Andric                             "be read in with \"breakpoint read\".  "
226414f1b3e8SDimitry Andric                             "If given no arguments, writes all breakpoints.",
22656f8fc217SDimitry Andric                             nullptr) {
2266ac9a064cSDimitry Andric     CommandObject::AddIDsArgumentData(eBreakpointArgs);
226714f1b3e8SDimitry Andric   }
226814f1b3e8SDimitry Andric 
226914f1b3e8SDimitry Andric   ~CommandObjectBreakpointWrite() override = default;
227014f1b3e8SDimitry Andric 
2271cfca06d7SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2272cfca06d7SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
2273cfca06d7SDimitry Andric                            OptionElementVector &opt_element_vector) override {
22747fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
22757fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
2276cfca06d7SDimitry Andric   }
2277cfca06d7SDimitry Andric 
GetOptions()227814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
227914f1b3e8SDimitry Andric 
228014f1b3e8SDimitry Andric   class CommandOptions : public Options {
228114f1b3e8SDimitry Andric   public:
2282145449b1SDimitry Andric     CommandOptions() = default;
228314f1b3e8SDimitry Andric 
228414f1b3e8SDimitry Andric     ~CommandOptions() override = default;
228514f1b3e8SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2286b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
228714f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
2288b76161e4SDimitry Andric       Status error;
228914f1b3e8SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
229014f1b3e8SDimitry Andric 
229114f1b3e8SDimitry Andric       switch (short_option) {
229214f1b3e8SDimitry Andric       case 'f':
2293cfca06d7SDimitry Andric         m_filename.assign(std::string(option_arg));
229414f1b3e8SDimitry Andric         break;
229514f1b3e8SDimitry Andric       case 'a':
229614f1b3e8SDimitry Andric         m_append = true;
229714f1b3e8SDimitry Andric         break;
229814f1b3e8SDimitry Andric       default:
2299ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
230014f1b3e8SDimitry Andric       }
230114f1b3e8SDimitry Andric 
230214f1b3e8SDimitry Andric       return error;
230314f1b3e8SDimitry Andric     }
230414f1b3e8SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)230514f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
230614f1b3e8SDimitry Andric       m_filename.clear();
230714f1b3e8SDimitry Andric       m_append = false;
230814f1b3e8SDimitry Andric     }
230914f1b3e8SDimitry Andric 
GetDefinitions()231014f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2311e3b55780SDimitry Andric       return llvm::ArrayRef(g_breakpoint_write_options);
231214f1b3e8SDimitry Andric     }
231314f1b3e8SDimitry Andric 
231414f1b3e8SDimitry Andric     // Instance variables to hold the values for command options.
231514f1b3e8SDimitry Andric 
231614f1b3e8SDimitry Andric     std::string m_filename;
231714f1b3e8SDimitry Andric     bool m_append = false;
231814f1b3e8SDimitry Andric   };
231914f1b3e8SDimitry Andric 
232014f1b3e8SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2321b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
2322ead24645SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
232314f1b3e8SDimitry Andric 
232414f1b3e8SDimitry Andric     std::unique_lock<std::recursive_mutex> lock;
2325ead24645SDimitry Andric     target.GetBreakpointList().GetListMutex(lock);
232614f1b3e8SDimitry Andric 
232714f1b3e8SDimitry Andric     BreakpointIDList valid_bp_ids;
232814f1b3e8SDimitry Andric     if (!command.empty()) {
232914f1b3e8SDimitry Andric       CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2330ead24645SDimitry Andric           command, &target, result, &valid_bp_ids,
2331ef5d0b5eSDimitry Andric           BreakpointName::Permissions::PermissionKinds::listPerm);
233214f1b3e8SDimitry Andric 
233314f1b3e8SDimitry Andric       if (!result.Succeeded()) {
233414f1b3e8SDimitry Andric         result.SetStatus(eReturnStatusFailed);
2335b1c73532SDimitry Andric         return;
233614f1b3e8SDimitry Andric       }
233714f1b3e8SDimitry Andric     }
233894994d37SDimitry Andric     FileSpec file_spec(m_options.m_filename);
233994994d37SDimitry Andric     FileSystem::Instance().Resolve(file_spec);
2340ead24645SDimitry Andric     Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
234194994d37SDimitry Andric                                                      m_options.m_append);
234214f1b3e8SDimitry Andric     if (!error.Success()) {
234314f1b3e8SDimitry Andric       result.AppendErrorWithFormat("error serializing breakpoints: %s.",
234414f1b3e8SDimitry Andric                                    error.AsCString());
234514f1b3e8SDimitry Andric     }
234614f1b3e8SDimitry Andric   }
234714f1b3e8SDimitry Andric 
234814f1b3e8SDimitry Andric private:
234914f1b3e8SDimitry Andric   CommandOptions m_options;
235014f1b3e8SDimitry Andric };
235114f1b3e8SDimitry Andric 
2352f034231aSEd Maste // CommandObjectMultiwordBreakpoint
2353f034231aSEd Maste #pragma mark MultiwordBreakpoint
2354f034231aSEd Maste 
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)235514f1b3e8SDimitry Andric CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
235614f1b3e8SDimitry Andric     CommandInterpreter &interpreter)
235714f1b3e8SDimitry Andric     : CommandObjectMultiword(
235814f1b3e8SDimitry Andric           interpreter, "breakpoint",
2359f3fbd1c0SDimitry Andric           "Commands for operating on breakpoints (see 'help b' for shorthand.)",
236014f1b3e8SDimitry Andric           "breakpoint <subcommand> [<command-options>]") {
236114f1b3e8SDimitry Andric   CommandObjectSP list_command_object(
236214f1b3e8SDimitry Andric       new CommandObjectBreakpointList(interpreter));
236314f1b3e8SDimitry Andric   CommandObjectSP enable_command_object(
236414f1b3e8SDimitry Andric       new CommandObjectBreakpointEnable(interpreter));
236514f1b3e8SDimitry Andric   CommandObjectSP disable_command_object(
236614f1b3e8SDimitry Andric       new CommandObjectBreakpointDisable(interpreter));
236714f1b3e8SDimitry Andric   CommandObjectSP clear_command_object(
236814f1b3e8SDimitry Andric       new CommandObjectBreakpointClear(interpreter));
236914f1b3e8SDimitry Andric   CommandObjectSP delete_command_object(
237014f1b3e8SDimitry Andric       new CommandObjectBreakpointDelete(interpreter));
237114f1b3e8SDimitry Andric   CommandObjectSP set_command_object(
237214f1b3e8SDimitry Andric       new CommandObjectBreakpointSet(interpreter));
237314f1b3e8SDimitry Andric   CommandObjectSP command_command_object(
237414f1b3e8SDimitry Andric       new CommandObjectBreakpointCommand(interpreter));
237514f1b3e8SDimitry Andric   CommandObjectSP modify_command_object(
237614f1b3e8SDimitry Andric       new CommandObjectBreakpointModify(interpreter));
237714f1b3e8SDimitry Andric   CommandObjectSP name_command_object(
237814f1b3e8SDimitry Andric       new CommandObjectBreakpointName(interpreter));
237914f1b3e8SDimitry Andric   CommandObjectSP write_command_object(
238014f1b3e8SDimitry Andric       new CommandObjectBreakpointWrite(interpreter));
238114f1b3e8SDimitry Andric   CommandObjectSP read_command_object(
238214f1b3e8SDimitry Andric       new CommandObjectBreakpointRead(interpreter));
2383f034231aSEd Maste 
2384f034231aSEd Maste   list_command_object->SetCommandName("breakpoint list");
2385f034231aSEd Maste   enable_command_object->SetCommandName("breakpoint enable");
2386f034231aSEd Maste   disable_command_object->SetCommandName("breakpoint disable");
2387f034231aSEd Maste   clear_command_object->SetCommandName("breakpoint clear");
2388f034231aSEd Maste   delete_command_object->SetCommandName("breakpoint delete");
2389f034231aSEd Maste   set_command_object->SetCommandName("breakpoint set");
2390f034231aSEd Maste   command_command_object->SetCommandName("breakpoint command");
2391f034231aSEd Maste   modify_command_object->SetCommandName("breakpoint modify");
2392205afe67SEd Maste   name_command_object->SetCommandName("breakpoint name");
239314f1b3e8SDimitry Andric   write_command_object->SetCommandName("breakpoint write");
239414f1b3e8SDimitry Andric   read_command_object->SetCommandName("breakpoint read");
2395f034231aSEd Maste 
2396f034231aSEd Maste   LoadSubCommand("list", list_command_object);
2397f034231aSEd Maste   LoadSubCommand("enable", enable_command_object);
2398f034231aSEd Maste   LoadSubCommand("disable", disable_command_object);
2399f034231aSEd Maste   LoadSubCommand("clear", clear_command_object);
2400f034231aSEd Maste   LoadSubCommand("delete", delete_command_object);
2401f034231aSEd Maste   LoadSubCommand("set", set_command_object);
2402f034231aSEd Maste   LoadSubCommand("command", command_command_object);
2403f034231aSEd Maste   LoadSubCommand("modify", modify_command_object);
2404205afe67SEd Maste   LoadSubCommand("name", name_command_object);
240514f1b3e8SDimitry Andric   LoadSubCommand("write", write_command_object);
240614f1b3e8SDimitry Andric   LoadSubCommand("read", read_command_object);
2407f034231aSEd Maste }
2408f034231aSEd Maste 
2409f3fbd1c0SDimitry Andric CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2410f034231aSEd Maste 
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2411706b4fc4SDimitry Andric void CommandObjectMultiwordBreakpoint::VerifyIDs(
2412706b4fc4SDimitry Andric     Args &args, Target *target, bool allow_locations,
2413706b4fc4SDimitry Andric     CommandReturnObject &result, BreakpointIDList *valid_ids,
2414706b4fc4SDimitry Andric     BreakpointName::Permissions ::PermissionKinds purpose) {
2415f034231aSEd Maste   // args can be strings representing 1). integers (for breakpoint ids)
241614f1b3e8SDimitry Andric   //                                  2). the full breakpoint & location
241714f1b3e8SDimitry Andric   //                                  canonical representation
241814f1b3e8SDimitry Andric   //                                  3). the word "to" or a hyphen,
241914f1b3e8SDimitry Andric   //                                  representing a range (in which case there
242014f1b3e8SDimitry Andric   //                                      had *better* be an entry both before &
242114f1b3e8SDimitry Andric   //                                      after of one of the first two types.
2422205afe67SEd Maste   //                                  4). A breakpoint name
242314f1b3e8SDimitry Andric   // If args is empty, we will use the last created breakpoint (if there is
242414f1b3e8SDimitry Andric   // one.)
2425f034231aSEd Maste 
2426f034231aSEd Maste   Args temp_args;
2427f034231aSEd Maste 
242814f1b3e8SDimitry Andric   if (args.empty()) {
242914f1b3e8SDimitry Andric     if (target->GetLastCreatedBreakpoint()) {
243014f1b3e8SDimitry Andric       valid_ids->AddBreakpointID(BreakpointID(
243114f1b3e8SDimitry Andric           target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2432f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
243314f1b3e8SDimitry Andric     } else {
243414f1b3e8SDimitry Andric       result.AppendError(
243514f1b3e8SDimitry Andric           "No breakpoint specified and no last created breakpoint.");
2436f034231aSEd Maste     }
2437f034231aSEd Maste     return;
2438f034231aSEd Maste   }
2439f034231aSEd Maste 
244014f1b3e8SDimitry Andric   // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2441f73363f1SDimitry Andric   // directly from the old ARGS to the new TEMP_ARGS.  Do not copy breakpoint
2442f73363f1SDimitry Andric   // id range strings over; instead generate a list of strings for all the
2443f73363f1SDimitry Andric   // breakpoint ids in the range, and shove all of those breakpoint id strings
2444f73363f1SDimitry Andric   // into TEMP_ARGS.
2445f034231aSEd Maste 
24464df029ccSDimitry Andric   if (llvm::Error err = BreakpointIDList::FindAndReplaceIDRanges(
24474df029ccSDimitry Andric           args, target, allow_locations, purpose, temp_args)) {
24484df029ccSDimitry Andric     result.SetError(std::move(err));
24494df029ccSDimitry Andric     return;
24504df029ccSDimitry Andric   }
24514df029ccSDimitry Andric   result.SetStatus(eReturnStatusSuccessFinishNoResult);
2452f034231aSEd Maste 
245314f1b3e8SDimitry Andric   // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
245414f1b3e8SDimitry Andric   // BreakpointIDList:
2455f034231aSEd Maste 
2456aca2e42cSDimitry Andric   for (llvm::StringRef temp_arg : temp_args.GetArgumentArrayRef())
2457aca2e42cSDimitry Andric     if (auto bp_id = BreakpointID::ParseCanonicalReference(temp_arg))
2458aca2e42cSDimitry Andric       valid_ids->AddBreakpointID(*bp_id);
2459f034231aSEd Maste 
2460f73363f1SDimitry Andric   // At this point,  all of the breakpoint ids that the user passed in have
2461f73363f1SDimitry Andric   // been converted to breakpoint IDs and put into valid_ids.
2462f034231aSEd Maste 
246314f1b3e8SDimitry Andric   // Now that we've converted everything from args into a list of breakpoint
2464f73363f1SDimitry Andric   // ids, go through our tentative list of breakpoint id's and verify that
2465f73363f1SDimitry Andric   // they correspond to valid/currently set breakpoints.
2466f034231aSEd Maste 
2467f034231aSEd Maste   const size_t count = valid_ids->GetSize();
246814f1b3e8SDimitry Andric   for (size_t i = 0; i < count; ++i) {
2469f034231aSEd Maste     BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
247014f1b3e8SDimitry Andric     Breakpoint *breakpoint =
247114f1b3e8SDimitry Andric         target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
247214f1b3e8SDimitry Andric     if (breakpoint != nullptr) {
2473f034231aSEd Maste       const size_t num_locations = breakpoint->GetNumLocations();
247414f1b3e8SDimitry Andric       if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2475f034231aSEd Maste         StreamString id_str;
247614f1b3e8SDimitry Andric         BreakpointID::GetCanonicalReference(
247714f1b3e8SDimitry Andric             &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2478f034231aSEd Maste         i = valid_ids->GetSize() + 1;
247914f1b3e8SDimitry Andric         result.AppendErrorWithFormat(
248014f1b3e8SDimitry Andric             "'%s' is not a currently valid breakpoint/location id.\n",
2481f034231aSEd Maste             id_str.GetData());
2482f034231aSEd Maste       }
248314f1b3e8SDimitry Andric     } else {
2484f034231aSEd Maste       i = valid_ids->GetSize() + 1;
248514f1b3e8SDimitry Andric       result.AppendErrorWithFormat(
248614f1b3e8SDimitry Andric           "'%d' is not a currently valid breakpoint ID.\n",
2487f3fbd1c0SDimitry Andric           cur_bp_id.GetBreakpointID());
2488f034231aSEd Maste     }
2489f034231aSEd Maste   }
2490f034231aSEd Maste }
2491