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