1ac7ddfbfSEd Maste //===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
104bb0738eSEd Maste #include <vector>
114bb0738eSEd Maste
124bb0738eSEd Maste #include "CommandObjectBreakpoint.h"
134bb0738eSEd Maste #include "CommandObjectBreakpointCommand.h"
14ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
15ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointIDList.h"
16ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
17f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
18435933ddSDimitry Andric #include "lldb/Interpreter/CommandCompletions.h"
19435933ddSDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
20435933ddSDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
214ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
221c3bbb01SEd Maste #include "lldb/Interpreter/OptionValueBoolean.h"
237aa51b79SEd Maste #include "lldb/Interpreter/OptionValueString.h"
247aa51b79SEd Maste #include "lldb/Interpreter/OptionValueUInt64.h"
25435933ddSDimitry Andric #include "lldb/Interpreter/Options.h"
269f2f44ceSEd Maste #include "lldb/Target/Language.h"
27ac7ddfbfSEd Maste #include "lldb/Target/StackFrame.h"
28435933ddSDimitry Andric #include "lldb/Target/Target.h"
29ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
30ac7ddfbfSEd Maste #include "lldb/Target/ThreadSpec.h"
31f678e45dSDimitry Andric #include "lldb/Utility/RegularExpression.h"
32f678e45dSDimitry Andric #include "lldb/Utility/StreamString.h"
33ac7ddfbfSEd Maste
34ac7ddfbfSEd Maste using namespace lldb;
35ac7ddfbfSEd Maste using namespace lldb_private;
36ac7ddfbfSEd Maste
AddBreakpointDescription(Stream * s,Breakpoint * bp,lldb::DescriptionLevel level)37435933ddSDimitry Andric static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38435933ddSDimitry Andric lldb::DescriptionLevel level) {
39ac7ddfbfSEd Maste s->IndentMore();
40ac7ddfbfSEd Maste bp->GetDescription(s, level, true);
41ac7ddfbfSEd Maste s->IndentLess();
42ac7ddfbfSEd Maste s->EOL();
43ac7ddfbfSEd Maste }
44ac7ddfbfSEd Maste
45acac075bSDimitry Andric //-------------------------------------------------------------------------
46acac075bSDimitry Andric // Modifiable Breakpoint Options
47acac075bSDimitry Andric //-------------------------------------------------------------------------
48acac075bSDimitry Andric #pragma mark Modify::CommandOptions
49*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_modify_options[] = {
50acac075bSDimitry Andric // clang-format off
51*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
52*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
53*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
54*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
55*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
56*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
57*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
58*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
59*b5893f02SDimitry Andric { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
60*b5893f02SDimitry Andric { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
61*b5893f02SDimitry Andric { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
62acac075bSDimitry Andric // clang-format on
63acac075bSDimitry Andric };
64acac075bSDimitry Andric class lldb_private::BreakpointOptionGroup : public OptionGroup
65acac075bSDimitry Andric {
66acac075bSDimitry Andric public:
BreakpointOptionGroup()67acac075bSDimitry Andric BreakpointOptionGroup() :
68acac075bSDimitry Andric OptionGroup(),
69acac075bSDimitry Andric m_bp_opts(false) {}
70acac075bSDimitry Andric
71acac075bSDimitry Andric ~BreakpointOptionGroup() override = default;
72acac075bSDimitry Andric
GetDefinitions()73acac075bSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
74acac075bSDimitry Andric return llvm::makeArrayRef(g_breakpoint_modify_options);
75acac075bSDimitry Andric }
76acac075bSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)77acac075bSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
78acac075bSDimitry Andric ExecutionContext *execution_context) override {
79acac075bSDimitry Andric Status error;
80acac075bSDimitry Andric const int short_option = g_breakpoint_modify_options[option_idx].short_option;
81acac075bSDimitry Andric
82acac075bSDimitry Andric switch (short_option) {
83acac075bSDimitry Andric case 'c':
844ba319b5SDimitry Andric // Normally an empty breakpoint condition marks is as unset. But we need
854ba319b5SDimitry Andric // to say it was passed in.
86acac075bSDimitry Andric m_bp_opts.SetCondition(option_arg.str().c_str());
87acac075bSDimitry Andric m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
88acac075bSDimitry Andric break;
89acac075bSDimitry Andric case 'C':
90acac075bSDimitry Andric m_commands.push_back(option_arg);
91acac075bSDimitry Andric break;
92acac075bSDimitry Andric case 'd':
93acac075bSDimitry Andric m_bp_opts.SetEnabled(false);
94acac075bSDimitry Andric break;
95acac075bSDimitry Andric case 'e':
96acac075bSDimitry Andric m_bp_opts.SetEnabled(true);
97acac075bSDimitry Andric break;
98acac075bSDimitry Andric case 'G': {
99acac075bSDimitry Andric bool value, success;
1004ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
101acac075bSDimitry Andric if (success) {
102acac075bSDimitry Andric m_bp_opts.SetAutoContinue(value);
103acac075bSDimitry Andric } else
104acac075bSDimitry Andric error.SetErrorStringWithFormat(
105acac075bSDimitry Andric "invalid boolean value '%s' passed for -G option",
106acac075bSDimitry Andric option_arg.str().c_str());
107acac075bSDimitry Andric }
108acac075bSDimitry Andric break;
109acac075bSDimitry Andric case 'i':
110acac075bSDimitry Andric {
111acac075bSDimitry Andric uint32_t ignore_count;
112acac075bSDimitry Andric if (option_arg.getAsInteger(0, ignore_count))
113acac075bSDimitry Andric error.SetErrorStringWithFormat("invalid ignore count '%s'",
114acac075bSDimitry Andric option_arg.str().c_str());
115acac075bSDimitry Andric else
116acac075bSDimitry Andric m_bp_opts.SetIgnoreCount(ignore_count);
117acac075bSDimitry Andric }
118acac075bSDimitry Andric break;
119acac075bSDimitry Andric case 'o': {
120acac075bSDimitry Andric bool value, success;
1214ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
122acac075bSDimitry Andric if (success) {
123acac075bSDimitry Andric m_bp_opts.SetOneShot(value);
124acac075bSDimitry Andric } else
125acac075bSDimitry Andric error.SetErrorStringWithFormat(
126acac075bSDimitry Andric "invalid boolean value '%s' passed for -o option",
127acac075bSDimitry Andric option_arg.str().c_str());
128acac075bSDimitry Andric } break;
129acac075bSDimitry Andric case 't':
130acac075bSDimitry Andric {
131acac075bSDimitry Andric lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
132acac075bSDimitry Andric if (option_arg[0] != '\0') {
133acac075bSDimitry Andric if (option_arg.getAsInteger(0, thread_id))
134acac075bSDimitry Andric error.SetErrorStringWithFormat("invalid thread id string '%s'",
135acac075bSDimitry Andric option_arg.str().c_str());
136acac075bSDimitry Andric }
137acac075bSDimitry Andric m_bp_opts.SetThreadID(thread_id);
138acac075bSDimitry Andric }
139acac075bSDimitry Andric break;
140acac075bSDimitry Andric case 'T':
141acac075bSDimitry Andric m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
142acac075bSDimitry Andric break;
143acac075bSDimitry Andric case 'q':
144acac075bSDimitry Andric m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
145acac075bSDimitry Andric break;
146acac075bSDimitry Andric case 'x':
147acac075bSDimitry Andric {
148acac075bSDimitry Andric uint32_t thread_index = UINT32_MAX;
149acac075bSDimitry Andric if (option_arg[0] != '\n') {
150acac075bSDimitry Andric if (option_arg.getAsInteger(0, thread_index))
151acac075bSDimitry Andric error.SetErrorStringWithFormat("invalid thread index string '%s'",
152acac075bSDimitry Andric option_arg.str().c_str());
153acac075bSDimitry Andric }
154acac075bSDimitry Andric m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
155acac075bSDimitry Andric }
156acac075bSDimitry Andric break;
157acac075bSDimitry Andric default:
158acac075bSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
159acac075bSDimitry Andric short_option);
160acac075bSDimitry Andric break;
161acac075bSDimitry Andric }
162acac075bSDimitry Andric
163acac075bSDimitry Andric return error;
164acac075bSDimitry Andric }
165acac075bSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)166acac075bSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
167acac075bSDimitry Andric m_bp_opts.Clear();
168acac075bSDimitry Andric m_commands.clear();
169acac075bSDimitry Andric }
170acac075bSDimitry Andric
OptionParsingFinished(ExecutionContext * execution_context)171acac075bSDimitry Andric Status OptionParsingFinished(ExecutionContext *execution_context) override {
172acac075bSDimitry Andric if (!m_commands.empty())
173acac075bSDimitry Andric {
174acac075bSDimitry Andric if (!m_commands.empty())
175acac075bSDimitry Andric {
176acac075bSDimitry Andric auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
177acac075bSDimitry Andric
178acac075bSDimitry Andric for (std::string &str : m_commands)
179acac075bSDimitry Andric cmd_data->user_source.AppendString(str);
180acac075bSDimitry Andric
181acac075bSDimitry Andric cmd_data->stop_on_error = true;
182acac075bSDimitry Andric m_bp_opts.SetCommandDataCallback(cmd_data);
183acac075bSDimitry Andric }
184acac075bSDimitry Andric }
185acac075bSDimitry Andric return Status();
186acac075bSDimitry Andric }
187acac075bSDimitry Andric
GetBreakpointOptions()188acac075bSDimitry Andric const BreakpointOptions &GetBreakpointOptions()
189acac075bSDimitry Andric {
190acac075bSDimitry Andric return m_bp_opts;
191acac075bSDimitry Andric }
192acac075bSDimitry Andric
193acac075bSDimitry Andric std::vector<std::string> m_commands;
194acac075bSDimitry Andric BreakpointOptions m_bp_opts;
195acac075bSDimitry Andric
196acac075bSDimitry Andric };
197*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
198acac075bSDimitry Andric // clang-format off
199*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
200acac075bSDimitry Andric "which prime new targets." },
201acac075bSDimitry Andric // clang-format on
202acac075bSDimitry Andric };
203acac075bSDimitry Andric
204acac075bSDimitry Andric class BreakpointDummyOptionGroup : public OptionGroup
205acac075bSDimitry Andric {
206acac075bSDimitry Andric public:
BreakpointDummyOptionGroup()207acac075bSDimitry Andric BreakpointDummyOptionGroup() :
208acac075bSDimitry Andric OptionGroup() {}
209acac075bSDimitry Andric
210acac075bSDimitry Andric ~BreakpointDummyOptionGroup() override = default;
211acac075bSDimitry Andric
GetDefinitions()212acac075bSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
213acac075bSDimitry Andric return llvm::makeArrayRef(g_breakpoint_dummy_options);
214acac075bSDimitry Andric }
215acac075bSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)216acac075bSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
217acac075bSDimitry Andric ExecutionContext *execution_context) override {
218acac075bSDimitry Andric Status error;
219acac075bSDimitry Andric const int short_option = g_breakpoint_modify_options[option_idx].short_option;
220acac075bSDimitry Andric
221acac075bSDimitry Andric switch (short_option) {
222acac075bSDimitry Andric case 'D':
223acac075bSDimitry Andric m_use_dummy = true;
224acac075bSDimitry Andric break;
225acac075bSDimitry Andric default:
226acac075bSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
227acac075bSDimitry Andric short_option);
228acac075bSDimitry Andric break;
229acac075bSDimitry Andric }
230acac075bSDimitry Andric
231acac075bSDimitry Andric return error;
232acac075bSDimitry Andric }
233acac075bSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)234acac075bSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
235acac075bSDimitry Andric m_use_dummy = false;
236acac075bSDimitry Andric }
237acac075bSDimitry Andric
238acac075bSDimitry Andric bool m_use_dummy;
239acac075bSDimitry Andric
240acac075bSDimitry Andric };
241acac075bSDimitry Andric
242435933ddSDimitry Andric // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
243435933ddSDimitry Andric // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
244*b5893f02SDimitry Andric #define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
245435933ddSDimitry Andric #define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
246*b5893f02SDimitry Andric #define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
247*b5893f02SDimitry Andric #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
248435933ddSDimitry Andric #define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
249435933ddSDimitry Andric #define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
250435933ddSDimitry Andric
251*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_set_options[] = {
252435933ddSDimitry Andric // clang-format off
253*b5893f02SDimitry Andric { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
254435933ddSDimitry Andric "multiple times to specify multiple shared libraries." },
255*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
256*b5893f02SDimitry Andric { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
257435933ddSDimitry Andric "lldb only looks for files that are #included if they use the standard include "
258435933ddSDimitry Andric "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
259435933ddSDimitry Andric "#included, set target.inline-breakpoint-strategy to \"always\"." },
260*b5893f02SDimitry Andric { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
261435933ddSDimitry Andric
2624ba319b5SDimitry Andric // Comment out this option for the moment, as we don't actually use it, but
2634ba319b5SDimitry Andric // will in the future. This way users won't see it, but the infrastructure is
2644ba319b5SDimitry Andric // left in place.
265435933ddSDimitry Andric // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
266435933ddSDimitry Andric // "Set the breakpoint by source location at this particular column."},
267435933ddSDimitry Andric
268*b5893f02SDimitry Andric { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
269435933ddSDimitry Andric "a particular binary, then the address will be converted to a \"file\" "
270435933ddSDimitry Andric "address, so that the breakpoint will track that binary+offset no matter where "
271435933ddSDimitry Andric "the binary eventually loads. Alternately, if you also specify the module - "
272435933ddSDimitry Andric "with the -s option - then the address will be treated as a file address in "
273435933ddSDimitry Andric "that module, and resolved accordingly. Again, this will allow lldb to track "
274435933ddSDimitry Andric "that offset on subsequent reloads. The module need not have been loaded at "
275435933ddSDimitry Andric "the time you specify this breakpoint, and will get resolved when the module "
276435933ddSDimitry Andric "is loaded." },
277*b5893f02SDimitry Andric { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
278435933ddSDimitry Andric "one breakpoint for multiple names" },
279*b5893f02SDimitry Andric { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
280435933ddSDimitry Andric "functions. Can be repeated multiple times." },
281*b5893f02SDimitry Andric { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
2824ba319b5SDimitry Andric "namespaces and all arguments, and for Objective-C this means a full function "
283435933ddSDimitry Andric "prototype with class and selector. Can be repeated multiple times to make "
284435933ddSDimitry Andric "one breakpoint for multiple names." },
285*b5893f02SDimitry Andric { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
286435933ddSDimitry Andric "make one breakpoint for multiple Selectors." },
287*b5893f02SDimitry Andric { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
288435933ddSDimitry Andric "make one breakpoint for multiple methods." },
289*b5893f02SDimitry Andric { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
290435933ddSDimitry Andric "the function name(s)." },
291*b5893f02SDimitry Andric { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
292435933ddSDimitry Andric "ignored). Can be repeated multiple times to make one breakpoint for multiple "
293435933ddSDimitry Andric "symbols." },
294*b5893f02SDimitry Andric { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
295435933ddSDimitry Andric "against the source text in a source file or files specified with the -f "
296435933ddSDimitry Andric "option. The -f option can be specified more than once. If no source files "
297435933ddSDimitry Andric "are specified, uses the current \"default source file\". If you want to "
298435933ddSDimitry Andric "match against all source files, pass the \"--all-files\" option." },
299*b5893f02SDimitry Andric { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
300*b5893f02SDimitry Andric { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
301*b5893f02SDimitry Andric { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
302*b5893f02SDimitry Andric { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
303*b5893f02SDimitry Andric { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
304435933ddSDimitry Andric "options, on throw but not catch.)" },
305*b5893f02SDimitry Andric { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
306*b5893f02SDimitry Andric { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
307435933ddSDimitry Andric
308435933ddSDimitry Andric // Don't add this option till it actually does something useful...
309435933ddSDimitry Andric // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
310435933ddSDimitry Andric // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
311435933ddSDimitry Andric
312*b5893f02SDimitry Andric { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
313435933ddSDimitry Andric "(note: currently only implemented for setting breakpoints on identifiers). "
314435933ddSDimitry Andric "If not set the target.language setting is used." },
315*b5893f02SDimitry Andric { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
316435933ddSDimitry Andric "If not set the target.skip-prologue setting is used." },
317*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
318*b5893f02SDimitry Andric { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
319435933ddSDimitry Andric "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
320*b5893f02SDimitry Andric { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
321435933ddSDimitry Andric "setting is used." },
322435933ddSDimitry Andric // clang-format on
323435933ddSDimitry Andric };
324435933ddSDimitry Andric
325ac7ddfbfSEd Maste //-------------------------------------------------------------------------
326ac7ddfbfSEd Maste // CommandObjectBreakpointSet
327ac7ddfbfSEd Maste //-------------------------------------------------------------------------
328ac7ddfbfSEd Maste
329435933ddSDimitry Andric class CommandObjectBreakpointSet : public CommandObjectParsed {
330ac7ddfbfSEd Maste public:
331435933ddSDimitry Andric typedef enum BreakpointSetType {
332ac7ddfbfSEd Maste eSetTypeInvalid,
333ac7ddfbfSEd Maste eSetTypeFileAndLine,
334ac7ddfbfSEd Maste eSetTypeAddress,
335ac7ddfbfSEd Maste eSetTypeFunctionName,
336ac7ddfbfSEd Maste eSetTypeFunctionRegexp,
337ac7ddfbfSEd Maste eSetTypeSourceRegexp,
338*b5893f02SDimitry Andric eSetTypeException,
339*b5893f02SDimitry Andric eSetTypeScripted,
340ac7ddfbfSEd Maste } BreakpointSetType;
341ac7ddfbfSEd Maste
CommandObjectBreakpointSet(CommandInterpreter & interpreter)342435933ddSDimitry Andric CommandObjectBreakpointSet(CommandInterpreter &interpreter)
343435933ddSDimitry Andric : CommandObjectParsed(
344435933ddSDimitry Andric interpreter, "breakpoint set",
345ac7ddfbfSEd Maste "Sets a breakpoint or set of breakpoints in the executable.",
346ac7ddfbfSEd Maste "breakpoint set <cmd-options>"),
347acac075bSDimitry Andric m_bp_opts(), m_options() {
348acac075bSDimitry Andric // We're picking up all the normal options, commands and disable.
349acac075bSDimitry Andric m_all_options.Append(&m_bp_opts,
350acac075bSDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
351acac075bSDimitry Andric LLDB_OPT_SET_ALL);
352acac075bSDimitry Andric m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
353acac075bSDimitry Andric m_all_options.Append(&m_options);
354acac075bSDimitry Andric m_all_options.Finalize();
355acac075bSDimitry Andric }
356ac7ddfbfSEd Maste
3574bb0738eSEd Maste ~CommandObjectBreakpointSet() override = default;
358ac7ddfbfSEd Maste
GetOptions()359acac075bSDimitry Andric Options *GetOptions() override { return &m_all_options; }
360ac7ddfbfSEd Maste
361acac075bSDimitry Andric class CommandOptions : public OptionGroup {
362ac7ddfbfSEd Maste public:
CommandOptions()363435933ddSDimitry Andric CommandOptions()
364acac075bSDimitry Andric : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
365435933ddSDimitry Andric m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
366435933ddSDimitry Andric m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
367435933ddSDimitry Andric m_catch_bp(false), m_throw_bp(true), m_hardware(false),
3681c3bbb01SEd Maste m_exception_language(eLanguageTypeUnknown),
3699f2f44ceSEd Maste m_language(lldb::eLanguageTypeUnknown),
370acac075bSDimitry Andric m_skip_prologue(eLazyBoolCalculate),
371435933ddSDimitry Andric m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
372ac7ddfbfSEd Maste
3734bb0738eSEd Maste ~CommandOptions() override = default;
374ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)3755517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
376435933ddSDimitry Andric ExecutionContext *execution_context) override {
3775517e702SDimitry Andric Status error;
378acac075bSDimitry Andric const int short_option = g_breakpoint_set_options[option_idx].short_option;
379ac7ddfbfSEd Maste
380435933ddSDimitry Andric switch (short_option) {
381435933ddSDimitry Andric case 'a': {
3824ba319b5SDimitry Andric m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
383435933ddSDimitry Andric LLDB_INVALID_ADDRESS, &error);
384435933ddSDimitry Andric } break;
385ac7ddfbfSEd Maste
3861c3bbb01SEd Maste case 'A':
3871c3bbb01SEd Maste m_all_files = true;
3881c3bbb01SEd Maste break;
3891c3bbb01SEd Maste
390ac7ddfbfSEd Maste case 'b':
391ac7ddfbfSEd Maste m_func_names.push_back(option_arg);
392ac7ddfbfSEd Maste m_func_name_type_mask |= eFunctionNameTypeBase;
393ac7ddfbfSEd Maste break;
394ac7ddfbfSEd Maste
395ac7ddfbfSEd Maste case 'C':
396435933ddSDimitry Andric if (option_arg.getAsInteger(0, m_column))
397435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid column number: %s",
398435933ddSDimitry Andric option_arg.str().c_str());
399ac7ddfbfSEd Maste break;
4004bb0738eSEd Maste
401435933ddSDimitry Andric case 'E': {
4029f2f44ceSEd Maste LanguageType language = Language::GetLanguageTypeFromString(option_arg);
403ac7ddfbfSEd Maste
404435933ddSDimitry Andric switch (language) {
405ac7ddfbfSEd Maste case eLanguageTypeC89:
406ac7ddfbfSEd Maste case eLanguageTypeC:
407ac7ddfbfSEd Maste case eLanguageTypeC99:
4080127ef0fSEd Maste case eLanguageTypeC11:
4091c3bbb01SEd Maste m_exception_language = eLanguageTypeC;
410ac7ddfbfSEd Maste break;
411ac7ddfbfSEd Maste case eLanguageTypeC_plus_plus:
4120127ef0fSEd Maste case eLanguageTypeC_plus_plus_03:
4130127ef0fSEd Maste case eLanguageTypeC_plus_plus_11:
4141c3bbb01SEd Maste case eLanguageTypeC_plus_plus_14:
4151c3bbb01SEd Maste m_exception_language = eLanguageTypeC_plus_plus;
416ac7ddfbfSEd Maste break;
417ac7ddfbfSEd Maste case eLanguageTypeObjC:
4181c3bbb01SEd Maste m_exception_language = eLanguageTypeObjC;
419ac7ddfbfSEd Maste break;
420ac7ddfbfSEd Maste case eLanguageTypeObjC_plus_plus:
421435933ddSDimitry Andric error.SetErrorStringWithFormat(
422435933ddSDimitry Andric "Set exception breakpoints separately for c++ and objective-c");
423ac7ddfbfSEd Maste break;
424ac7ddfbfSEd Maste case eLanguageTypeUnknown:
425435933ddSDimitry Andric error.SetErrorStringWithFormat(
426435933ddSDimitry Andric "Unknown language type: '%s' for exception breakpoint",
427435933ddSDimitry Andric option_arg.str().c_str());
428ac7ddfbfSEd Maste break;
429ac7ddfbfSEd Maste default:
430435933ddSDimitry Andric error.SetErrorStringWithFormat(
431435933ddSDimitry Andric "Unsupported language type: '%s' for exception breakpoint",
432435933ddSDimitry Andric option_arg.str().c_str());
433ac7ddfbfSEd Maste }
434435933ddSDimitry Andric } break;
435ac7ddfbfSEd Maste
436ac7ddfbfSEd Maste case 'f':
437*b5893f02SDimitry Andric m_filenames.AppendIfUnique(FileSpec(option_arg));
438ac7ddfbfSEd Maste break;
439ac7ddfbfSEd Maste
440ac7ddfbfSEd Maste case 'F':
441ac7ddfbfSEd Maste m_func_names.push_back(option_arg);
442ac7ddfbfSEd Maste m_func_name_type_mask |= eFunctionNameTypeFull;
443ac7ddfbfSEd Maste break;
444ac7ddfbfSEd Maste
445435933ddSDimitry Andric case 'h': {
446ac7ddfbfSEd Maste bool success;
4474ba319b5SDimitry Andric m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
448ac7ddfbfSEd Maste if (!success)
449435933ddSDimitry Andric error.SetErrorStringWithFormat(
450435933ddSDimitry Andric "Invalid boolean value for on-catch option: '%s'",
451435933ddSDimitry Andric option_arg.str().c_str());
452435933ddSDimitry Andric } break;
45335617911SEd Maste
45435617911SEd Maste case 'H':
45535617911SEd Maste m_hardware = true;
45635617911SEd Maste break;
45735617911SEd Maste
458*b5893f02SDimitry Andric case 'k': {
459*b5893f02SDimitry Andric if (m_current_key.empty())
460*b5893f02SDimitry Andric m_current_key.assign(option_arg);
461*b5893f02SDimitry Andric else
462*b5893f02SDimitry Andric error.SetErrorStringWithFormat("Key: %s missing value.",
463*b5893f02SDimitry Andric m_current_key.c_str());
464*b5893f02SDimitry Andric
465*b5893f02SDimitry Andric } break;
466435933ddSDimitry Andric case 'K': {
467ac7ddfbfSEd Maste bool success;
468ac7ddfbfSEd Maste bool value;
4694ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, true, &success);
470ac7ddfbfSEd Maste if (value)
471ac7ddfbfSEd Maste m_skip_prologue = eLazyBoolYes;
472ac7ddfbfSEd Maste else
473ac7ddfbfSEd Maste m_skip_prologue = eLazyBoolNo;
474ac7ddfbfSEd Maste
475ac7ddfbfSEd Maste if (!success)
476435933ddSDimitry Andric error.SetErrorStringWithFormat(
477435933ddSDimitry Andric "Invalid boolean value for skip prologue option: '%s'",
478435933ddSDimitry Andric option_arg.str().c_str());
479435933ddSDimitry Andric } break;
480ac7ddfbfSEd Maste
481ac7ddfbfSEd Maste case 'l':
482435933ddSDimitry Andric if (option_arg.getAsInteger(0, m_line_num))
483435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid line number: %s.",
484435933ddSDimitry Andric option_arg.str().c_str());
485ac7ddfbfSEd Maste break;
4861c3bbb01SEd Maste
4879f2f44ceSEd Maste case 'L':
4889f2f44ceSEd Maste m_language = Language::GetLanguageTypeFromString(option_arg);
4899f2f44ceSEd Maste if (m_language == eLanguageTypeUnknown)
490435933ddSDimitry Andric error.SetErrorStringWithFormat(
491435933ddSDimitry Andric "Unknown language type: '%s' for breakpoint",
492435933ddSDimitry Andric option_arg.str().c_str());
4939f2f44ceSEd Maste break;
4949f2f44ceSEd Maste
495435933ddSDimitry Andric case 'm': {
4961c3bbb01SEd Maste bool success;
4971c3bbb01SEd Maste bool value;
4984ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, true, &success);
4991c3bbb01SEd Maste if (value)
5001c3bbb01SEd Maste m_move_to_nearest_code = eLazyBoolYes;
5011c3bbb01SEd Maste else
5021c3bbb01SEd Maste m_move_to_nearest_code = eLazyBoolNo;
5031c3bbb01SEd Maste
5041c3bbb01SEd Maste if (!success)
505435933ddSDimitry Andric error.SetErrorStringWithFormat(
506435933ddSDimitry Andric "Invalid boolean value for move-to-nearest-code option: '%s'",
507435933ddSDimitry Andric option_arg.str().c_str());
5081c3bbb01SEd Maste break;
5091c3bbb01SEd Maste }
510ac7ddfbfSEd Maste
511ac7ddfbfSEd Maste case 'M':
512ac7ddfbfSEd Maste m_func_names.push_back(option_arg);
513ac7ddfbfSEd Maste m_func_name_type_mask |= eFunctionNameTypeMethod;
514ac7ddfbfSEd Maste break;
515ac7ddfbfSEd Maste
516ac7ddfbfSEd Maste case 'n':
517ac7ddfbfSEd Maste m_func_names.push_back(option_arg);
518ac7ddfbfSEd Maste m_func_name_type_mask |= eFunctionNameTypeAuto;
519ac7ddfbfSEd Maste break;
520ac7ddfbfSEd Maste
521435933ddSDimitry Andric case 'N': {
5227aa51b79SEd Maste if (BreakpointID::StringIsBreakpointName(option_arg, error))
5237aa51b79SEd Maste m_breakpoint_names.push_back(option_arg);
524435933ddSDimitry Andric else
525435933ddSDimitry Andric error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
526435933ddSDimitry Andric option_arg.str().c_str());
5277aa51b79SEd Maste break;
528435933ddSDimitry Andric }
5297aa51b79SEd Maste
530435933ddSDimitry Andric case 'R': {
5314bb0738eSEd Maste lldb::addr_t tmp_offset_addr;
5324ba319b5SDimitry Andric tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
5334ba319b5SDimitry Andric option_arg, 0, &error);
5344bb0738eSEd Maste if (error.Success())
5354bb0738eSEd Maste m_offset_addr = tmp_offset_addr;
536435933ddSDimitry Andric } break;
5374bb0738eSEd Maste
5381c3bbb01SEd Maste case 'O':
5391c3bbb01SEd Maste m_exception_extra_args.AppendArgument("-O");
5401c3bbb01SEd Maste m_exception_extra_args.AppendArgument(option_arg);
5411c3bbb01SEd Maste break;
5421c3bbb01SEd Maste
543ac7ddfbfSEd Maste case 'p':
544ac7ddfbfSEd Maste m_source_text_regexp.assign(option_arg);
545ac7ddfbfSEd Maste break;
546ac7ddfbfSEd Maste
547*b5893f02SDimitry Andric case 'P':
548*b5893f02SDimitry Andric m_python_class.assign(option_arg);
549*b5893f02SDimitry Andric break;
550*b5893f02SDimitry Andric
551ac7ddfbfSEd Maste case 'r':
552ac7ddfbfSEd Maste m_func_regexp.assign(option_arg);
553ac7ddfbfSEd Maste break;
554ac7ddfbfSEd Maste
555ac7ddfbfSEd Maste case 's':
556*b5893f02SDimitry Andric m_modules.AppendIfUnique(FileSpec(option_arg));
557ac7ddfbfSEd Maste break;
558ac7ddfbfSEd Maste
559ac7ddfbfSEd Maste case 'S':
560ac7ddfbfSEd Maste m_func_names.push_back(option_arg);
561ac7ddfbfSEd Maste m_func_name_type_mask |= eFunctionNameTypeSelector;
562ac7ddfbfSEd Maste break;
563ac7ddfbfSEd Maste
564*b5893f02SDimitry Andric case 'v': {
565*b5893f02SDimitry Andric if (!m_current_key.empty()) {
566*b5893f02SDimitry Andric m_extra_args_sp->AddStringItem(m_current_key, option_arg);
567*b5893f02SDimitry Andric m_current_key.clear();
568*b5893f02SDimitry Andric }
569*b5893f02SDimitry Andric else
570*b5893f02SDimitry Andric error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
571*b5893f02SDimitry Andric option_arg.str().c_str());
572*b5893f02SDimitry Andric } break;
573*b5893f02SDimitry Andric
574435933ddSDimitry Andric case 'w': {
575ac7ddfbfSEd Maste bool success;
5764ba319b5SDimitry Andric m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
577ac7ddfbfSEd Maste if (!success)
578435933ddSDimitry Andric error.SetErrorStringWithFormat(
579435933ddSDimitry Andric "Invalid boolean value for on-throw option: '%s'",
580435933ddSDimitry Andric option_arg.str().c_str());
581435933ddSDimitry Andric } break;
582ac7ddfbfSEd Maste
5834bb0738eSEd Maste case 'X':
5844bb0738eSEd Maste m_source_regex_func_names.insert(option_arg);
585ac7ddfbfSEd Maste break;
586ac7ddfbfSEd Maste
587ac7ddfbfSEd Maste default:
588435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
589435933ddSDimitry Andric short_option);
590ac7ddfbfSEd Maste break;
591ac7ddfbfSEd Maste }
592ac7ddfbfSEd Maste
593ac7ddfbfSEd Maste return error;
594ac7ddfbfSEd Maste }
5954bb0738eSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)596435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
597ac7ddfbfSEd Maste m_filenames.Clear();
598ac7ddfbfSEd Maste m_line_num = 0;
599ac7ddfbfSEd Maste m_column = 0;
600ac7ddfbfSEd Maste m_func_names.clear();
601ac7ddfbfSEd Maste m_func_name_type_mask = eFunctionNameTypeNone;
602ac7ddfbfSEd Maste m_func_regexp.clear();
603ac7ddfbfSEd Maste m_source_text_regexp.clear();
604ac7ddfbfSEd Maste m_modules.Clear();
605ac7ddfbfSEd Maste m_load_addr = LLDB_INVALID_ADDRESS;
6064bb0738eSEd Maste m_offset_addr = 0;
607ac7ddfbfSEd Maste m_catch_bp = false;
608ac7ddfbfSEd Maste m_throw_bp = true;
60935617911SEd Maste m_hardware = false;
6101c3bbb01SEd Maste m_exception_language = eLanguageTypeUnknown;
6119f2f44ceSEd Maste m_language = lldb::eLanguageTypeUnknown;
612ac7ddfbfSEd Maste m_skip_prologue = eLazyBoolCalculate;
6137aa51b79SEd Maste m_breakpoint_names.clear();
6141c3bbb01SEd Maste m_all_files = false;
6151c3bbb01SEd Maste m_exception_extra_args.Clear();
6161c3bbb01SEd Maste m_move_to_nearest_code = eLazyBoolCalculate;
6174bb0738eSEd Maste m_source_regex_func_names.clear();
618*b5893f02SDimitry Andric m_python_class.clear();
619*b5893f02SDimitry Andric m_extra_args_sp.reset(new StructuredData::Dictionary());
620*b5893f02SDimitry Andric m_current_key.clear();
621ac7ddfbfSEd Maste }
622ac7ddfbfSEd Maste
GetDefinitions()623435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
624435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_set_options);
625ac7ddfbfSEd Maste }
626ac7ddfbfSEd Maste
627ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
628ac7ddfbfSEd Maste
629ac7ddfbfSEd Maste std::string m_condition;
630ac7ddfbfSEd Maste FileSpecList m_filenames;
631ac7ddfbfSEd Maste uint32_t m_line_num;
632ac7ddfbfSEd Maste uint32_t m_column;
633ac7ddfbfSEd Maste std::vector<std::string> m_func_names;
6347aa51b79SEd Maste std::vector<std::string> m_breakpoint_names;
635*b5893f02SDimitry Andric lldb::FunctionNameType m_func_name_type_mask;
636ac7ddfbfSEd Maste std::string m_func_regexp;
637ac7ddfbfSEd Maste std::string m_source_text_regexp;
638ac7ddfbfSEd Maste FileSpecList m_modules;
639ac7ddfbfSEd Maste lldb::addr_t m_load_addr;
6404bb0738eSEd Maste lldb::addr_t m_offset_addr;
641ac7ddfbfSEd Maste bool m_catch_bp;
642ac7ddfbfSEd Maste bool m_throw_bp;
64335617911SEd Maste bool m_hardware; // Request to use hardware breakpoints
6441c3bbb01SEd Maste lldb::LanguageType m_exception_language;
6459f2f44ceSEd Maste lldb::LanguageType m_language;
646ac7ddfbfSEd Maste LazyBool m_skip_prologue;
6471c3bbb01SEd Maste bool m_all_files;
6481c3bbb01SEd Maste Args m_exception_extra_args;
6491c3bbb01SEd Maste LazyBool m_move_to_nearest_code;
6504bb0738eSEd Maste std::unordered_set<std::string> m_source_regex_func_names;
651*b5893f02SDimitry Andric std::string m_python_class;
652*b5893f02SDimitry Andric StructuredData::DictionarySP m_extra_args_sp;
653*b5893f02SDimitry Andric std::string m_current_key;
654ac7ddfbfSEd Maste };
655ac7ddfbfSEd Maste
656ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)657435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
658acac075bSDimitry Andric Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
6597aa51b79SEd Maste
660435933ddSDimitry Andric if (target == nullptr) {
661435933ddSDimitry Andric result.AppendError("Invalid target. Must set target before setting "
662435933ddSDimitry Andric "breakpoints (see 'target create' command).");
663ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
664ac7ddfbfSEd Maste return false;
665ac7ddfbfSEd Maste }
666ac7ddfbfSEd Maste
667ac7ddfbfSEd Maste // The following are the various types of breakpoints that could be set:
668ac7ddfbfSEd Maste // 1). -f -l -p [-s -g] (setting breakpoint by source location)
669ac7ddfbfSEd Maste // 2). -a [-s -g] (setting breakpoint by address)
670ac7ddfbfSEd Maste // 3). -n [-s -g] (setting breakpoint by function name)
671435933ddSDimitry Andric // 4). -r [-s -g] (setting breakpoint by function name regular
672435933ddSDimitry Andric // expression)
673435933ddSDimitry Andric // 5). -p -f (setting a breakpoint by comparing a reg-exp
674435933ddSDimitry Andric // to source text)
675435933ddSDimitry Andric // 6). -E [-w -h] (setting a breakpoint for exceptions for a
676435933ddSDimitry Andric // given language.)
677ac7ddfbfSEd Maste
678ac7ddfbfSEd Maste BreakpointSetType break_type = eSetTypeInvalid;
679ac7ddfbfSEd Maste
680*b5893f02SDimitry Andric if (!m_options.m_python_class.empty())
681*b5893f02SDimitry Andric break_type = eSetTypeScripted;
682*b5893f02SDimitry Andric else if (m_options.m_line_num != 0)
683ac7ddfbfSEd Maste break_type = eSetTypeFileAndLine;
684ac7ddfbfSEd Maste else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
685ac7ddfbfSEd Maste break_type = eSetTypeAddress;
686ac7ddfbfSEd Maste else if (!m_options.m_func_names.empty())
687ac7ddfbfSEd Maste break_type = eSetTypeFunctionName;
688ac7ddfbfSEd Maste else if (!m_options.m_func_regexp.empty())
689ac7ddfbfSEd Maste break_type = eSetTypeFunctionRegexp;
690ac7ddfbfSEd Maste else if (!m_options.m_source_text_regexp.empty())
691ac7ddfbfSEd Maste break_type = eSetTypeSourceRegexp;
6921c3bbb01SEd Maste else if (m_options.m_exception_language != eLanguageTypeUnknown)
693ac7ddfbfSEd Maste break_type = eSetTypeException;
694ac7ddfbfSEd Maste
695acac075bSDimitry Andric BreakpointSP bp_sp = nullptr;
696ac7ddfbfSEd Maste FileSpec module_spec;
697ac7ddfbfSEd Maste const bool internal = false;
698ac7ddfbfSEd Maste
699435933ddSDimitry Andric // If the user didn't specify skip-prologue, having an offset should turn
700435933ddSDimitry Andric // that off.
701435933ddSDimitry Andric if (m_options.m_offset_addr != 0 &&
702435933ddSDimitry Andric m_options.m_skip_prologue == eLazyBoolCalculate)
7034bb0738eSEd Maste m_options.m_skip_prologue = eLazyBoolNo;
7044bb0738eSEd Maste
705435933ddSDimitry Andric switch (break_type) {
706ac7ddfbfSEd Maste case eSetTypeFileAndLine: // Breakpoint by source position
707ac7ddfbfSEd Maste {
708ac7ddfbfSEd Maste FileSpec file;
709ac7ddfbfSEd Maste const size_t num_files = m_options.m_filenames.GetSize();
710435933ddSDimitry Andric if (num_files == 0) {
711435933ddSDimitry Andric if (!GetDefaultFile(target, file, result)) {
712ac7ddfbfSEd Maste result.AppendError("No file supplied and no default file available.");
713ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
714ac7ddfbfSEd Maste return false;
715ac7ddfbfSEd Maste }
716435933ddSDimitry Andric } else if (num_files > 1) {
717435933ddSDimitry Andric result.AppendError("Only one file at a time is allowed for file and "
718435933ddSDimitry Andric "line breakpoints.");
719ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
720ac7ddfbfSEd Maste return false;
721435933ddSDimitry Andric } else
722ac7ddfbfSEd Maste file = m_options.m_filenames.GetFileSpecAtIndex(0);
723ac7ddfbfSEd Maste
724ac7ddfbfSEd Maste // Only check for inline functions if
725ac7ddfbfSEd Maste LazyBool check_inlines = eLazyBoolCalculate;
726ac7ddfbfSEd Maste
727acac075bSDimitry Andric bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
728acac075bSDimitry Andric file,
729acac075bSDimitry Andric m_options.m_line_num,
730*b5893f02SDimitry Andric m_options.m_column,
731acac075bSDimitry Andric m_options.m_offset_addr,
732acac075bSDimitry Andric check_inlines,
733acac075bSDimitry Andric m_options.m_skip_prologue,
734acac075bSDimitry Andric internal,
735acac075bSDimitry Andric m_options.m_hardware,
736acac075bSDimitry Andric m_options.m_move_to_nearest_code);
737435933ddSDimitry Andric } break;
738ac7ddfbfSEd Maste
739ac7ddfbfSEd Maste case eSetTypeAddress: // Breakpoint by address
7409f2f44ceSEd Maste {
741435933ddSDimitry Andric // If a shared library has been specified, make an lldb_private::Address
742acac075bSDimitry Andric // with the library, and use that. That way the address breakpoint
743acac075bSDimitry Andric // will track the load location of the library.
7449f2f44ceSEd Maste size_t num_modules_specified = m_options.m_modules.GetSize();
745435933ddSDimitry Andric if (num_modules_specified == 1) {
746435933ddSDimitry Andric const FileSpec *file_spec =
747435933ddSDimitry Andric m_options.m_modules.GetFileSpecPointerAtIndex(0);
748acac075bSDimitry Andric bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
749435933ddSDimitry Andric internal, file_spec,
750acac075bSDimitry Andric m_options.m_hardware);
751435933ddSDimitry Andric } else if (num_modules_specified == 0) {
752acac075bSDimitry Andric bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
753acac075bSDimitry Andric m_options.m_hardware);
754435933ddSDimitry Andric } else {
755435933ddSDimitry Andric result.AppendError("Only one shared library can be specified for "
756435933ddSDimitry Andric "address breakpoints.");
7579f2f44ceSEd Maste result.SetStatus(eReturnStatusFailed);
7589f2f44ceSEd Maste return false;
7599f2f44ceSEd Maste }
760ac7ddfbfSEd Maste break;
7619f2f44ceSEd Maste }
762ac7ddfbfSEd Maste case eSetTypeFunctionName: // Breakpoint by function name
763ac7ddfbfSEd Maste {
764*b5893f02SDimitry Andric FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
765ac7ddfbfSEd Maste
766ac7ddfbfSEd Maste if (name_type_mask == 0)
767ac7ddfbfSEd Maste name_type_mask = eFunctionNameTypeAuto;
768ac7ddfbfSEd Maste
769acac075bSDimitry Andric bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
770acac075bSDimitry Andric &(m_options.m_filenames),
771acac075bSDimitry Andric m_options.m_func_names,
772acac075bSDimitry Andric name_type_mask,
773acac075bSDimitry Andric m_options.m_language,
774acac075bSDimitry Andric m_options.m_offset_addr,
775acac075bSDimitry Andric m_options.m_skip_prologue,
776acac075bSDimitry Andric internal,
777acac075bSDimitry Andric m_options.m_hardware);
778435933ddSDimitry Andric } break;
779ac7ddfbfSEd Maste
780435933ddSDimitry Andric case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
781435933ddSDimitry Andric // name
782ac7ddfbfSEd Maste {
783435933ddSDimitry Andric RegularExpression regexp(m_options.m_func_regexp);
784435933ddSDimitry Andric if (!regexp.IsValid()) {
785ac7ddfbfSEd Maste char err_str[1024];
786ac7ddfbfSEd Maste regexp.GetErrorAsCString(err_str, sizeof(err_str));
787435933ddSDimitry Andric result.AppendErrorWithFormat(
788435933ddSDimitry Andric "Function name regular expression could not be compiled: \"%s\"",
789ac7ddfbfSEd Maste err_str);
790ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
791ac7ddfbfSEd Maste return false;
792ac7ddfbfSEd Maste }
793ac7ddfbfSEd Maste
794acac075bSDimitry Andric bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
795acac075bSDimitry Andric &(m_options.m_filenames),
796acac075bSDimitry Andric regexp,
797acac075bSDimitry Andric m_options.m_language,
798acac075bSDimitry Andric m_options.m_skip_prologue,
799acac075bSDimitry Andric internal,
800acac075bSDimitry Andric m_options.m_hardware);
801ac7ddfbfSEd Maste }
802ac7ddfbfSEd Maste break;
803ac7ddfbfSEd Maste case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
804ac7ddfbfSEd Maste {
805ac7ddfbfSEd Maste const size_t num_files = m_options.m_filenames.GetSize();
806ac7ddfbfSEd Maste
807435933ddSDimitry Andric if (num_files == 0 && !m_options.m_all_files) {
808ac7ddfbfSEd Maste FileSpec file;
809435933ddSDimitry Andric if (!GetDefaultFile(target, file, result)) {
810435933ddSDimitry Andric result.AppendError(
811435933ddSDimitry Andric "No files provided and could not find default file.");
812ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
813ac7ddfbfSEd Maste return false;
814435933ddSDimitry Andric } else {
815ac7ddfbfSEd Maste m_options.m_filenames.Append(file);
816ac7ddfbfSEd Maste }
817ac7ddfbfSEd Maste }
818ac7ddfbfSEd Maste
819435933ddSDimitry Andric RegularExpression regexp(m_options.m_source_text_regexp);
820435933ddSDimitry Andric if (!regexp.IsValid()) {
821ac7ddfbfSEd Maste char err_str[1024];
822ac7ddfbfSEd Maste regexp.GetErrorAsCString(err_str, sizeof(err_str));
823435933ddSDimitry Andric result.AppendErrorWithFormat(
824435933ddSDimitry Andric "Source text regular expression could not be compiled: \"%s\"",
825ac7ddfbfSEd Maste err_str);
826ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
827ac7ddfbfSEd Maste return false;
828ac7ddfbfSEd Maste }
829acac075bSDimitry Andric bp_sp =
830acac075bSDimitry Andric target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
831acac075bSDimitry Andric &(m_options.m_filenames),
832acac075bSDimitry Andric m_options
833acac075bSDimitry Andric .m_source_regex_func_names,
834acac075bSDimitry Andric regexp,
835acac075bSDimitry Andric internal,
836acac075bSDimitry Andric m_options.m_hardware,
837acac075bSDimitry Andric m_options.m_move_to_nearest_code);
838435933ddSDimitry Andric } break;
839435933ddSDimitry Andric case eSetTypeException: {
8405517e702SDimitry Andric Status precond_error;
841acac075bSDimitry Andric bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
842acac075bSDimitry Andric m_options.m_catch_bp,
843acac075bSDimitry Andric m_options.m_throw_bp,
844acac075bSDimitry Andric internal,
845acac075bSDimitry Andric &m_options
846acac075bSDimitry Andric .m_exception_extra_args,
847acac075bSDimitry Andric &precond_error);
848435933ddSDimitry Andric if (precond_error.Fail()) {
849435933ddSDimitry Andric result.AppendErrorWithFormat(
850435933ddSDimitry Andric "Error setting extra exception arguments: %s",
8511c3bbb01SEd Maste precond_error.AsCString());
852acac075bSDimitry Andric target->RemoveBreakpointByID(bp_sp->GetID());
8531c3bbb01SEd Maste result.SetStatus(eReturnStatusFailed);
8541c3bbb01SEd Maste return false;
8551c3bbb01SEd Maste }
856435933ddSDimitry Andric } break;
857*b5893f02SDimitry Andric case eSetTypeScripted: {
858*b5893f02SDimitry Andric
859*b5893f02SDimitry Andric Status error;
860*b5893f02SDimitry Andric bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
861*b5893f02SDimitry Andric &(m_options.m_modules),
862*b5893f02SDimitry Andric &(m_options.m_filenames),
863*b5893f02SDimitry Andric false,
864*b5893f02SDimitry Andric m_options.m_hardware,
865*b5893f02SDimitry Andric m_options.m_extra_args_sp,
866*b5893f02SDimitry Andric &error);
867*b5893f02SDimitry Andric if (error.Fail()) {
868*b5893f02SDimitry Andric result.AppendErrorWithFormat(
869*b5893f02SDimitry Andric "Error setting extra exception arguments: %s",
870*b5893f02SDimitry Andric error.AsCString());
871*b5893f02SDimitry Andric target->RemoveBreakpointByID(bp_sp->GetID());
872*b5893f02SDimitry Andric result.SetStatus(eReturnStatusFailed);
873*b5893f02SDimitry Andric return false;
874*b5893f02SDimitry Andric }
875*b5893f02SDimitry Andric } break;
876ac7ddfbfSEd Maste default:
877ac7ddfbfSEd Maste break;
878ac7ddfbfSEd Maste }
879ac7ddfbfSEd Maste
880ac7ddfbfSEd Maste // Now set the various options that were passed in:
881acac075bSDimitry Andric if (bp_sp) {
882acac075bSDimitry Andric bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
883ac7ddfbfSEd Maste
884435933ddSDimitry Andric if (!m_options.m_breakpoint_names.empty()) {
8855517e702SDimitry Andric Status name_error;
886435933ddSDimitry Andric for (auto name : m_options.m_breakpoint_names) {
887acac075bSDimitry Andric target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
888435933ddSDimitry Andric if (name_error.Fail()) {
889435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid breakpoint name: %s",
890435933ddSDimitry Andric name.c_str());
891acac075bSDimitry Andric target->RemoveBreakpointByID(bp_sp->GetID());
892435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
893435933ddSDimitry Andric return false;
894435933ddSDimitry Andric }
895435933ddSDimitry Andric }
8967aa51b79SEd Maste }
897ac7ddfbfSEd Maste }
898ac7ddfbfSEd Maste
899acac075bSDimitry Andric if (bp_sp) {
900ac7ddfbfSEd Maste Stream &output_stream = result.GetOutputStream();
901ac7ddfbfSEd Maste const bool show_locations = false;
902acac075bSDimitry Andric bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
903435933ddSDimitry Andric show_locations);
9047aa51b79SEd Maste if (target == m_interpreter.GetDebugger().GetDummyTarget())
905435933ddSDimitry Andric output_stream.Printf("Breakpoint set in dummy target, will get copied "
906435933ddSDimitry Andric "into future targets.\n");
907435933ddSDimitry Andric else {
9084ba319b5SDimitry Andric // Don't print out this warning for exception breakpoints. They can
9094ba319b5SDimitry Andric // get set before the target is set, but we won't know how to actually
9104ba319b5SDimitry Andric // set the breakpoint till we run.
911acac075bSDimitry Andric if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
912435933ddSDimitry Andric output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
913435933ddSDimitry Andric "actual locations.\n");
9147aa51b79SEd Maste }
9157aa51b79SEd Maste }
916ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
917acac075bSDimitry Andric } else if (!bp_sp) {
918ac7ddfbfSEd Maste result.AppendError("Breakpoint creation failed: No breakpoint created.");
919ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
920ac7ddfbfSEd Maste }
921ac7ddfbfSEd Maste
922ac7ddfbfSEd Maste return result.Succeeded();
923ac7ddfbfSEd Maste }
924ac7ddfbfSEd Maste
925ac7ddfbfSEd Maste private:
GetDefaultFile(Target * target,FileSpec & file,CommandReturnObject & result)926435933ddSDimitry Andric bool GetDefaultFile(Target *target, FileSpec &file,
927435933ddSDimitry Andric CommandReturnObject &result) {
928ac7ddfbfSEd Maste uint32_t default_line;
9294ba319b5SDimitry Andric // First use the Source Manager's default file. Then use the current stack
9304ba319b5SDimitry Andric // frame's file.
931435933ddSDimitry Andric if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
932ac7ddfbfSEd Maste StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
933435933ddSDimitry Andric if (cur_frame == nullptr) {
934435933ddSDimitry Andric result.AppendError(
935435933ddSDimitry Andric "No selected frame to use to find the default file.");
936ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
937ac7ddfbfSEd Maste return false;
938435933ddSDimitry Andric } else if (!cur_frame->HasDebugInformation()) {
939435933ddSDimitry Andric result.AppendError("Cannot use the selected frame to find the default "
940435933ddSDimitry Andric "file, it has no debug info.");
941ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
942ac7ddfbfSEd Maste return false;
943435933ddSDimitry Andric } else {
944435933ddSDimitry Andric const SymbolContext &sc =
945435933ddSDimitry Andric cur_frame->GetSymbolContext(eSymbolContextLineEntry);
946435933ddSDimitry Andric if (sc.line_entry.file) {
947ac7ddfbfSEd Maste file = sc.line_entry.file;
948435933ddSDimitry Andric } else {
949435933ddSDimitry Andric result.AppendError("Can't find the file for the selected frame to "
950435933ddSDimitry Andric "use as the default file.");
951ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
952ac7ddfbfSEd Maste return false;
953ac7ddfbfSEd Maste }
954ac7ddfbfSEd Maste }
955ac7ddfbfSEd Maste }
956ac7ddfbfSEd Maste return true;
957ac7ddfbfSEd Maste }
958ac7ddfbfSEd Maste
959acac075bSDimitry Andric BreakpointOptionGroup m_bp_opts;
960acac075bSDimitry Andric BreakpointDummyOptionGroup m_dummy_options;
961ac7ddfbfSEd Maste CommandOptions m_options;
962acac075bSDimitry Andric OptionGroupOptions m_all_options;
963ac7ddfbfSEd Maste };
9644bb0738eSEd Maste
965ac7ddfbfSEd Maste //-------------------------------------------------------------------------
966ac7ddfbfSEd Maste // CommandObjectBreakpointModify
967ac7ddfbfSEd Maste //-------------------------------------------------------------------------
968ac7ddfbfSEd Maste #pragma mark Modify
969ac7ddfbfSEd Maste
970435933ddSDimitry Andric class CommandObjectBreakpointModify : public CommandObjectParsed {
971ac7ddfbfSEd Maste public:
CommandObjectBreakpointModify(CommandInterpreter & interpreter)972435933ddSDimitry Andric CommandObjectBreakpointModify(CommandInterpreter &interpreter)
973435933ddSDimitry Andric : CommandObjectParsed(interpreter, "breakpoint modify",
974435933ddSDimitry Andric "Modify the options on a breakpoint or set of "
975435933ddSDimitry Andric "breakpoints in the executable. "
976435933ddSDimitry Andric "If no breakpoint is specified, acts on the last "
977435933ddSDimitry Andric "created breakpoint. "
978435933ddSDimitry Andric "With the exception of -e, -d and -i, passing an "
979435933ddSDimitry Andric "empty argument clears the modification.",
9804bb0738eSEd Maste nullptr),
981435933ddSDimitry Andric m_options() {
982ac7ddfbfSEd Maste CommandArgumentEntry arg;
983435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
984435933ddSDimitry Andric eArgTypeBreakpointIDRange);
985435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
986435933ddSDimitry Andric // arguments vector.
987ac7ddfbfSEd Maste m_arguments.push_back(arg);
988acac075bSDimitry Andric
989acac075bSDimitry Andric m_options.Append(&m_bp_opts,
990acac075bSDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
991acac075bSDimitry Andric LLDB_OPT_SET_ALL);
992acac075bSDimitry Andric m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
993acac075bSDimitry Andric m_options.Finalize();
994ac7ddfbfSEd Maste }
995ac7ddfbfSEd Maste
9964bb0738eSEd Maste ~CommandObjectBreakpointModify() override = default;
997ac7ddfbfSEd Maste
GetOptions()998435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
999ac7ddfbfSEd Maste
1000ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1001435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1002acac075bSDimitry Andric Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
1003435933ddSDimitry Andric if (target == nullptr) {
1004ac7ddfbfSEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
1005ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1006ac7ddfbfSEd Maste return false;
1007ac7ddfbfSEd Maste }
1008ac7ddfbfSEd Maste
10094bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
10104bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
1011ac7ddfbfSEd Maste
1012ac7ddfbfSEd Maste BreakpointIDList valid_bp_ids;
1013ac7ddfbfSEd Maste
1014435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1015acac075bSDimitry Andric command, target, result, &valid_bp_ids,
1016acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
1017ac7ddfbfSEd Maste
1018435933ddSDimitry Andric if (result.Succeeded()) {
1019ac7ddfbfSEd Maste const size_t count = valid_bp_ids.GetSize();
1020435933ddSDimitry Andric for (size_t i = 0; i < count; ++i) {
1021ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1022ac7ddfbfSEd Maste
1023435933ddSDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1024435933ddSDimitry Andric Breakpoint *bp =
1025435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1026435933ddSDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1027435933ddSDimitry Andric BreakpointLocation *location =
1028435933ddSDimitry Andric bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1029acac075bSDimitry Andric if (location)
1030acac075bSDimitry Andric location->GetLocationOptions()
1031acac075bSDimitry Andric ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1032435933ddSDimitry Andric } else {
1033acac075bSDimitry Andric bp->GetOptions()
1034acac075bSDimitry Andric ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
1035ac7ddfbfSEd Maste }
1036ac7ddfbfSEd Maste }
1037ac7ddfbfSEd Maste }
1038ac7ddfbfSEd Maste }
1039ac7ddfbfSEd Maste
1040ac7ddfbfSEd Maste return result.Succeeded();
1041ac7ddfbfSEd Maste }
1042ac7ddfbfSEd Maste
1043ac7ddfbfSEd Maste private:
1044acac075bSDimitry Andric BreakpointOptionGroup m_bp_opts;
1045acac075bSDimitry Andric BreakpointDummyOptionGroup m_dummy_opts;
1046acac075bSDimitry Andric OptionGroupOptions m_options;
1047ac7ddfbfSEd Maste };
1048ac7ddfbfSEd Maste
1049ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1050ac7ddfbfSEd Maste // CommandObjectBreakpointEnable
1051ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1052ac7ddfbfSEd Maste #pragma mark Enable
1053ac7ddfbfSEd Maste
1054435933ddSDimitry Andric class CommandObjectBreakpointEnable : public CommandObjectParsed {
1055ac7ddfbfSEd Maste public:
CommandObjectBreakpointEnable(CommandInterpreter & interpreter)1056435933ddSDimitry Andric CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1057435933ddSDimitry Andric : CommandObjectParsed(interpreter, "enable",
1058435933ddSDimitry Andric "Enable the specified disabled breakpoint(s). If "
1059435933ddSDimitry Andric "no breakpoints are specified, enable all of them.",
1060435933ddSDimitry Andric nullptr) {
1061ac7ddfbfSEd Maste CommandArgumentEntry arg;
1062435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1063435933ddSDimitry Andric eArgTypeBreakpointIDRange);
1064435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
1065435933ddSDimitry Andric // arguments vector.
1066ac7ddfbfSEd Maste m_arguments.push_back(arg);
1067ac7ddfbfSEd Maste }
1068ac7ddfbfSEd Maste
10694bb0738eSEd Maste ~CommandObjectBreakpointEnable() override = default;
1070ac7ddfbfSEd Maste
1071ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1072435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
10737aa51b79SEd Maste Target *target = GetSelectedOrDummyTarget();
1074435933ddSDimitry Andric if (target == nullptr) {
1075ac7ddfbfSEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
1076ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1077ac7ddfbfSEd Maste return false;
1078ac7ddfbfSEd Maste }
1079ac7ddfbfSEd Maste
10804bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
10814bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
1082ac7ddfbfSEd Maste
1083ac7ddfbfSEd Maste const BreakpointList &breakpoints = target->GetBreakpointList();
1084ac7ddfbfSEd Maste
1085ac7ddfbfSEd Maste size_t num_breakpoints = breakpoints.GetSize();
1086ac7ddfbfSEd Maste
1087435933ddSDimitry Andric if (num_breakpoints == 0) {
1088ac7ddfbfSEd Maste result.AppendError("No breakpoints exist to be enabled.");
1089ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1090ac7ddfbfSEd Maste return false;
1091ac7ddfbfSEd Maste }
1092ac7ddfbfSEd Maste
1093435933ddSDimitry Andric if (command.empty()) {
1094ac7ddfbfSEd Maste // No breakpoint selected; enable all currently set breakpoints.
1095acac075bSDimitry Andric target->EnableAllowedBreakpoints();
1096435933ddSDimitry Andric result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1097435933ddSDimitry Andric " breakpoints)\n",
1098435933ddSDimitry Andric (uint64_t)num_breakpoints);
1099ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1100435933ddSDimitry Andric } else {
1101ac7ddfbfSEd Maste // Particular breakpoint selected; enable that breakpoint.
1102ac7ddfbfSEd Maste BreakpointIDList valid_bp_ids;
1103435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1104acac075bSDimitry Andric command, target, result, &valid_bp_ids,
1105acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
1106ac7ddfbfSEd Maste
1107435933ddSDimitry Andric if (result.Succeeded()) {
1108ac7ddfbfSEd Maste int enable_count = 0;
1109ac7ddfbfSEd Maste int loc_count = 0;
1110ac7ddfbfSEd Maste const size_t count = valid_bp_ids.GetSize();
1111435933ddSDimitry Andric for (size_t i = 0; i < count; ++i) {
1112ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1113ac7ddfbfSEd Maste
1114435933ddSDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1115435933ddSDimitry Andric Breakpoint *breakpoint =
1116435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1117435933ddSDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1118435933ddSDimitry Andric BreakpointLocation *location =
1119435933ddSDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1120435933ddSDimitry Andric if (location) {
1121ac7ddfbfSEd Maste location->SetEnabled(true);
1122ac7ddfbfSEd Maste ++loc_count;
1123ac7ddfbfSEd Maste }
1124435933ddSDimitry Andric } else {
1125ac7ddfbfSEd Maste breakpoint->SetEnabled(true);
1126ac7ddfbfSEd Maste ++enable_count;
1127ac7ddfbfSEd Maste }
1128ac7ddfbfSEd Maste }
1129ac7ddfbfSEd Maste }
1130435933ddSDimitry Andric result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1131435933ddSDimitry Andric enable_count + loc_count);
1132ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1133ac7ddfbfSEd Maste }
1134ac7ddfbfSEd Maste }
1135ac7ddfbfSEd Maste
1136ac7ddfbfSEd Maste return result.Succeeded();
1137ac7ddfbfSEd Maste }
1138ac7ddfbfSEd Maste };
1139ac7ddfbfSEd Maste
1140ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1141ac7ddfbfSEd Maste // CommandObjectBreakpointDisable
1142ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1143ac7ddfbfSEd Maste #pragma mark Disable
1144ac7ddfbfSEd Maste
1145435933ddSDimitry Andric class CommandObjectBreakpointDisable : public CommandObjectParsed {
1146ac7ddfbfSEd Maste public:
CommandObjectBreakpointDisable(CommandInterpreter & interpreter)11474bb0738eSEd Maste CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1148435933ddSDimitry Andric : CommandObjectParsed(
1149435933ddSDimitry Andric interpreter, "breakpoint disable",
1150435933ddSDimitry Andric "Disable the specified breakpoint(s) without deleting "
11514bb0738eSEd Maste "them. If none are specified, disable all "
11524bb0738eSEd Maste "breakpoints.",
1153435933ddSDimitry Andric nullptr) {
1154435933ddSDimitry Andric SetHelpLong(
1155435933ddSDimitry Andric "Disable the specified breakpoint(s) without deleting them. \
11564bb0738eSEd Maste If none are specified, disable all breakpoints."
11574bb0738eSEd Maste R"(
1158b91a7dfcSDimitry Andric
11594bb0738eSEd Maste )"
11604bb0738eSEd Maste "Note: disabling a breakpoint will cause none of its locations to be hit \
11614bb0738eSEd Maste regardless of whether individual locations are enabled or disabled. After the sequence:"
11624bb0738eSEd Maste R"(
1163b91a7dfcSDimitry Andric
1164b91a7dfcSDimitry Andric (lldb) break disable 1
1165b91a7dfcSDimitry Andric (lldb) break enable 1.1
1166b91a7dfcSDimitry Andric
1167b91a7dfcSDimitry Andric execution will NOT stop at location 1.1. To achieve that, type:
1168b91a7dfcSDimitry Andric
1169b91a7dfcSDimitry Andric (lldb) break disable 1.*
1170b91a7dfcSDimitry Andric (lldb) break enable 1.1
1171b91a7dfcSDimitry Andric
11724bb0738eSEd Maste )"
11734bb0738eSEd Maste "The first command disables all locations for breakpoint 1, \
11744bb0738eSEd Maste the second re-enables the first location.");
1175ac7ddfbfSEd Maste
1176ac7ddfbfSEd Maste CommandArgumentEntry arg;
1177435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1178435933ddSDimitry Andric eArgTypeBreakpointIDRange);
1179435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
1180435933ddSDimitry Andric // arguments vector.
1181ac7ddfbfSEd Maste m_arguments.push_back(arg);
1182ac7ddfbfSEd Maste }
1183ac7ddfbfSEd Maste
11844bb0738eSEd Maste ~CommandObjectBreakpointDisable() override = default;
1185ac7ddfbfSEd Maste
1186ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1187435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
11887aa51b79SEd Maste Target *target = GetSelectedOrDummyTarget();
1189435933ddSDimitry Andric if (target == nullptr) {
1190ac7ddfbfSEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
1191ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1192ac7ddfbfSEd Maste return false;
1193ac7ddfbfSEd Maste }
1194ac7ddfbfSEd Maste
11954bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
11964bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
1197ac7ddfbfSEd Maste
1198ac7ddfbfSEd Maste const BreakpointList &breakpoints = target->GetBreakpointList();
1199ac7ddfbfSEd Maste size_t num_breakpoints = breakpoints.GetSize();
1200ac7ddfbfSEd Maste
1201435933ddSDimitry Andric if (num_breakpoints == 0) {
1202ac7ddfbfSEd Maste result.AppendError("No breakpoints exist to be disabled.");
1203ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1204ac7ddfbfSEd Maste return false;
1205ac7ddfbfSEd Maste }
1206ac7ddfbfSEd Maste
1207435933ddSDimitry Andric if (command.empty()) {
1208ac7ddfbfSEd Maste // No breakpoint selected; disable all currently set breakpoints.
1209acac075bSDimitry Andric target->DisableAllowedBreakpoints();
1210435933ddSDimitry Andric result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1211435933ddSDimitry Andric " breakpoints)\n",
1212435933ddSDimitry Andric (uint64_t)num_breakpoints);
1213ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1214435933ddSDimitry Andric } else {
1215ac7ddfbfSEd Maste // Particular breakpoint selected; disable that breakpoint.
1216ac7ddfbfSEd Maste BreakpointIDList valid_bp_ids;
1217ac7ddfbfSEd Maste
1218435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1219acac075bSDimitry Andric command, target, result, &valid_bp_ids,
1220acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::disablePerm);
1221ac7ddfbfSEd Maste
1222435933ddSDimitry Andric if (result.Succeeded()) {
1223ac7ddfbfSEd Maste int disable_count = 0;
1224ac7ddfbfSEd Maste int loc_count = 0;
1225ac7ddfbfSEd Maste const size_t count = valid_bp_ids.GetSize();
1226435933ddSDimitry Andric for (size_t i = 0; i < count; ++i) {
1227ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1228ac7ddfbfSEd Maste
1229435933ddSDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1230435933ddSDimitry Andric Breakpoint *breakpoint =
1231435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1232435933ddSDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1233435933ddSDimitry Andric BreakpointLocation *location =
1234435933ddSDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1235435933ddSDimitry Andric if (location) {
1236ac7ddfbfSEd Maste location->SetEnabled(false);
1237ac7ddfbfSEd Maste ++loc_count;
1238ac7ddfbfSEd Maste }
1239435933ddSDimitry Andric } else {
1240ac7ddfbfSEd Maste breakpoint->SetEnabled(false);
1241ac7ddfbfSEd Maste ++disable_count;
1242ac7ddfbfSEd Maste }
1243ac7ddfbfSEd Maste }
1244ac7ddfbfSEd Maste }
1245435933ddSDimitry Andric result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1246435933ddSDimitry Andric disable_count + loc_count);
1247ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1248ac7ddfbfSEd Maste }
1249ac7ddfbfSEd Maste }
1250ac7ddfbfSEd Maste
1251ac7ddfbfSEd Maste return result.Succeeded();
1252ac7ddfbfSEd Maste }
1253ac7ddfbfSEd Maste };
1254ac7ddfbfSEd Maste
1255ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1256ac7ddfbfSEd Maste // CommandObjectBreakpointList
1257ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1258435933ddSDimitry Andric
1259435933ddSDimitry Andric #pragma mark List::CommandOptions
1260*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_list_options[] = {
1261435933ddSDimitry Andric // clang-format off
1262*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1263*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1264435933ddSDimitry Andric // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1265435933ddSDimitry Andric // But I need to see it for now, and don't want to wait.
1266*b5893f02SDimitry Andric { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1267*b5893f02SDimitry Andric { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1268*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1269435933ddSDimitry Andric // clang-format on
1270435933ddSDimitry Andric };
1271435933ddSDimitry Andric
1272ac7ddfbfSEd Maste #pragma mark List
1273ac7ddfbfSEd Maste
1274435933ddSDimitry Andric class CommandObjectBreakpointList : public CommandObjectParsed {
1275ac7ddfbfSEd Maste public:
CommandObjectBreakpointList(CommandInterpreter & interpreter)1276435933ddSDimitry Andric CommandObjectBreakpointList(CommandInterpreter &interpreter)
1277435933ddSDimitry Andric : CommandObjectParsed(
1278435933ddSDimitry Andric interpreter, "breakpoint list",
1279ac7ddfbfSEd Maste "List some or all breakpoints at configurable levels of detail.",
12804bb0738eSEd Maste nullptr),
1281435933ddSDimitry Andric m_options() {
1282ac7ddfbfSEd Maste CommandArgumentEntry arg;
1283ac7ddfbfSEd Maste CommandArgumentData bp_id_arg;
1284ac7ddfbfSEd Maste
1285ac7ddfbfSEd Maste // Define the first (and only) variant of this arg.
1286ac7ddfbfSEd Maste bp_id_arg.arg_type = eArgTypeBreakpointID;
1287ac7ddfbfSEd Maste bp_id_arg.arg_repetition = eArgRepeatOptional;
1288ac7ddfbfSEd Maste
1289435933ddSDimitry Andric // There is only one variant this argument could be; put it into the
1290435933ddSDimitry Andric // argument entry.
1291ac7ddfbfSEd Maste arg.push_back(bp_id_arg);
1292ac7ddfbfSEd Maste
1293ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector.
1294ac7ddfbfSEd Maste m_arguments.push_back(arg);
1295ac7ddfbfSEd Maste }
1296ac7ddfbfSEd Maste
12974bb0738eSEd Maste ~CommandObjectBreakpointList() override = default;
1298ac7ddfbfSEd Maste
GetOptions()1299435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
1300ac7ddfbfSEd Maste
1301435933ddSDimitry Andric class CommandOptions : public Options {
1302ac7ddfbfSEd Maste public:
CommandOptions()1303435933ddSDimitry Andric CommandOptions()
1304435933ddSDimitry Andric : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
1305ac7ddfbfSEd Maste }
1306ac7ddfbfSEd Maste
13074bb0738eSEd Maste ~CommandOptions() override = default;
1308ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13095517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1310435933ddSDimitry Andric ExecutionContext *execution_context) override {
13115517e702SDimitry Andric Status error;
1312ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
1313ac7ddfbfSEd Maste
1314435933ddSDimitry Andric switch (short_option) {
1315ac7ddfbfSEd Maste case 'b':
1316ac7ddfbfSEd Maste m_level = lldb::eDescriptionLevelBrief;
1317ac7ddfbfSEd Maste break;
13187aa51b79SEd Maste case 'D':
13197aa51b79SEd Maste m_use_dummy = true;
13207aa51b79SEd Maste break;
1321ac7ddfbfSEd Maste case 'f':
1322ac7ddfbfSEd Maste m_level = lldb::eDescriptionLevelFull;
1323ac7ddfbfSEd Maste break;
1324ac7ddfbfSEd Maste case 'v':
1325ac7ddfbfSEd Maste m_level = lldb::eDescriptionLevelVerbose;
1326ac7ddfbfSEd Maste break;
1327ac7ddfbfSEd Maste case 'i':
1328ac7ddfbfSEd Maste m_internal = true;
1329ac7ddfbfSEd Maste break;
1330ac7ddfbfSEd Maste default:
1331435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
1332435933ddSDimitry Andric short_option);
1333ac7ddfbfSEd Maste break;
1334ac7ddfbfSEd Maste }
1335ac7ddfbfSEd Maste
1336ac7ddfbfSEd Maste return error;
1337ac7ddfbfSEd Maste }
1338ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)1339435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1340ac7ddfbfSEd Maste m_level = lldb::eDescriptionLevelFull;
1341ac7ddfbfSEd Maste m_internal = false;
13427aa51b79SEd Maste m_use_dummy = false;
1343ac7ddfbfSEd Maste }
1344ac7ddfbfSEd Maste
GetDefinitions()1345435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1346435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_list_options);
1347ac7ddfbfSEd Maste }
1348ac7ddfbfSEd Maste
1349ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
1350ac7ddfbfSEd Maste
1351ac7ddfbfSEd Maste lldb::DescriptionLevel m_level;
1352ac7ddfbfSEd Maste
1353ac7ddfbfSEd Maste bool m_internal;
13547aa51b79SEd Maste bool m_use_dummy;
1355ac7ddfbfSEd Maste };
1356ac7ddfbfSEd Maste
1357ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1358435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
13597aa51b79SEd Maste Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
13607aa51b79SEd Maste
1361435933ddSDimitry Andric if (target == nullptr) {
1362ac7ddfbfSEd Maste result.AppendError("Invalid target. No current target or breakpoints.");
1363ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1364ac7ddfbfSEd Maste return true;
1365ac7ddfbfSEd Maste }
1366ac7ddfbfSEd Maste
1367435933ddSDimitry Andric const BreakpointList &breakpoints =
1368435933ddSDimitry Andric target->GetBreakpointList(m_options.m_internal);
13694bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
13704bb0738eSEd Maste target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1371ac7ddfbfSEd Maste
1372ac7ddfbfSEd Maste size_t num_breakpoints = breakpoints.GetSize();
1373ac7ddfbfSEd Maste
1374435933ddSDimitry Andric if (num_breakpoints == 0) {
1375ac7ddfbfSEd Maste result.AppendMessage("No breakpoints currently set.");
1376ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1377ac7ddfbfSEd Maste return true;
1378ac7ddfbfSEd Maste }
1379ac7ddfbfSEd Maste
1380ac7ddfbfSEd Maste Stream &output_stream = result.GetOutputStream();
1381ac7ddfbfSEd Maste
1382435933ddSDimitry Andric if (command.empty()) {
1383ac7ddfbfSEd Maste // No breakpoint selected; show info about all currently set breakpoints.
1384ac7ddfbfSEd Maste result.AppendMessage("Current breakpoints:");
1385435933ddSDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
1386ac7ddfbfSEd Maste Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1387acac075bSDimitry Andric if (breakpoint->AllowList())
1388acac075bSDimitry Andric AddBreakpointDescription(&output_stream, breakpoint,
1389acac075bSDimitry Andric m_options.m_level);
1390ac7ddfbfSEd Maste }
1391ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1392435933ddSDimitry Andric } else {
1393ac7ddfbfSEd Maste // Particular breakpoints selected; show info about that breakpoint.
1394ac7ddfbfSEd Maste BreakpointIDList valid_bp_ids;
1395435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1396acac075bSDimitry Andric command, target, result, &valid_bp_ids,
1397acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
1398ac7ddfbfSEd Maste
1399435933ddSDimitry Andric if (result.Succeeded()) {
1400435933ddSDimitry Andric for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1401ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1402435933ddSDimitry Andric Breakpoint *breakpoint =
1403435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1404435933ddSDimitry Andric AddBreakpointDescription(&output_stream, breakpoint,
1405435933ddSDimitry Andric m_options.m_level);
1406ac7ddfbfSEd Maste }
1407ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1408435933ddSDimitry Andric } else {
14094bb0738eSEd Maste result.AppendError("Invalid breakpoint ID.");
1410ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1411ac7ddfbfSEd Maste }
1412ac7ddfbfSEd Maste }
1413ac7ddfbfSEd Maste
1414ac7ddfbfSEd Maste return result.Succeeded();
1415ac7ddfbfSEd Maste }
1416ac7ddfbfSEd Maste
1417ac7ddfbfSEd Maste private:
1418ac7ddfbfSEd Maste CommandOptions m_options;
1419ac7ddfbfSEd Maste };
1420ac7ddfbfSEd Maste
1421ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1422ac7ddfbfSEd Maste // CommandObjectBreakpointClear
1423ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1424435933ddSDimitry Andric #pragma mark Clear::CommandOptions
1425435933ddSDimitry Andric
1426*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_clear_options[] = {
1427435933ddSDimitry Andric // clang-format off
1428*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1429*b5893f02SDimitry Andric { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1430435933ddSDimitry Andric // clang-format on
1431435933ddSDimitry Andric };
1432435933ddSDimitry Andric
1433ac7ddfbfSEd Maste #pragma mark Clear
1434ac7ddfbfSEd Maste
1435435933ddSDimitry Andric class CommandObjectBreakpointClear : public CommandObjectParsed {
1436ac7ddfbfSEd Maste public:
1437435933ddSDimitry Andric typedef enum BreakpointClearType {
1438ac7ddfbfSEd Maste eClearTypeInvalid,
1439ac7ddfbfSEd Maste eClearTypeFileAndLine
1440ac7ddfbfSEd Maste } BreakpointClearType;
1441ac7ddfbfSEd Maste
CommandObjectBreakpointClear(CommandInterpreter & interpreter)14424bb0738eSEd Maste CommandObjectBreakpointClear(CommandInterpreter &interpreter)
14434bb0738eSEd Maste : CommandObjectParsed(interpreter, "breakpoint clear",
1444435933ddSDimitry Andric "Delete or disable breakpoints matching the "
1445435933ddSDimitry Andric "specified source file and line.",
1446ac7ddfbfSEd Maste "breakpoint clear <cmd-options>"),
1447435933ddSDimitry Andric m_options() {}
1448ac7ddfbfSEd Maste
14494bb0738eSEd Maste ~CommandObjectBreakpointClear() override = default;
1450ac7ddfbfSEd Maste
GetOptions()1451435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
1452ac7ddfbfSEd Maste
1453435933ddSDimitry Andric class CommandOptions : public Options {
1454ac7ddfbfSEd Maste public:
CommandOptions()1455435933ddSDimitry Andric CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1456ac7ddfbfSEd Maste
14574bb0738eSEd Maste ~CommandOptions() override = default;
1458ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14595517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1460435933ddSDimitry Andric ExecutionContext *execution_context) override {
14615517e702SDimitry Andric Status error;
1462ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
1463ac7ddfbfSEd Maste
1464435933ddSDimitry Andric switch (short_option) {
1465ac7ddfbfSEd Maste case 'f':
1466ac7ddfbfSEd Maste m_filename.assign(option_arg);
1467ac7ddfbfSEd Maste break;
1468ac7ddfbfSEd Maste
1469ac7ddfbfSEd Maste case 'l':
1470435933ddSDimitry Andric option_arg.getAsInteger(0, m_line_num);
1471ac7ddfbfSEd Maste break;
1472ac7ddfbfSEd Maste
1473ac7ddfbfSEd Maste default:
1474435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
1475435933ddSDimitry Andric short_option);
1476ac7ddfbfSEd Maste break;
1477ac7ddfbfSEd Maste }
1478ac7ddfbfSEd Maste
1479ac7ddfbfSEd Maste return error;
1480ac7ddfbfSEd Maste }
1481ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)1482435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1483ac7ddfbfSEd Maste m_filename.clear();
1484ac7ddfbfSEd Maste m_line_num = 0;
1485ac7ddfbfSEd Maste }
1486ac7ddfbfSEd Maste
GetDefinitions()1487435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1488435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_clear_options);
1489ac7ddfbfSEd Maste }
1490ac7ddfbfSEd Maste
1491ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
1492ac7ddfbfSEd Maste
1493ac7ddfbfSEd Maste std::string m_filename;
1494ac7ddfbfSEd Maste uint32_t m_line_num;
1495ac7ddfbfSEd Maste };
1496ac7ddfbfSEd Maste
1497ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1498435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
14997aa51b79SEd Maste Target *target = GetSelectedOrDummyTarget();
1500435933ddSDimitry Andric if (target == nullptr) {
1501ac7ddfbfSEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
1502ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1503ac7ddfbfSEd Maste return false;
1504ac7ddfbfSEd Maste }
1505ac7ddfbfSEd Maste
15064ba319b5SDimitry Andric // The following are the various types of breakpoints that could be
15074ba319b5SDimitry Andric // cleared:
1508ac7ddfbfSEd Maste // 1). -f -l (clearing breakpoint by source location)
1509ac7ddfbfSEd Maste
1510ac7ddfbfSEd Maste BreakpointClearType break_type = eClearTypeInvalid;
1511ac7ddfbfSEd Maste
1512ac7ddfbfSEd Maste if (m_options.m_line_num != 0)
1513ac7ddfbfSEd Maste break_type = eClearTypeFileAndLine;
1514ac7ddfbfSEd Maste
15154bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
15164bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
1517ac7ddfbfSEd Maste
1518ac7ddfbfSEd Maste BreakpointList &breakpoints = target->GetBreakpointList();
1519ac7ddfbfSEd Maste size_t num_breakpoints = breakpoints.GetSize();
1520ac7ddfbfSEd Maste
1521ac7ddfbfSEd Maste // Early return if there's no breakpoint at all.
1522435933ddSDimitry Andric if (num_breakpoints == 0) {
1523ac7ddfbfSEd Maste result.AppendError("Breakpoint clear: No breakpoint cleared.");
1524ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1525ac7ddfbfSEd Maste return result.Succeeded();
1526ac7ddfbfSEd Maste }
1527ac7ddfbfSEd Maste
1528ac7ddfbfSEd Maste // Find matching breakpoints and delete them.
1529ac7ddfbfSEd Maste
1530ac7ddfbfSEd Maste // First create a copy of all the IDs.
1531ac7ddfbfSEd Maste std::vector<break_id_t> BreakIDs;
1532ac7ddfbfSEd Maste for (size_t i = 0; i < num_breakpoints; ++i)
15334bb0738eSEd Maste BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1534ac7ddfbfSEd Maste
1535ac7ddfbfSEd Maste int num_cleared = 0;
1536ac7ddfbfSEd Maste StreamString ss;
1537435933ddSDimitry Andric switch (break_type) {
1538ac7ddfbfSEd Maste case eClearTypeFileAndLine: // Breakpoint by source position
1539ac7ddfbfSEd Maste {
1540ac7ddfbfSEd Maste const ConstString filename(m_options.m_filename.c_str());
1541ac7ddfbfSEd Maste BreakpointLocationCollection loc_coll;
1542ac7ddfbfSEd Maste
1543435933ddSDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
1544ac7ddfbfSEd Maste Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1545ac7ddfbfSEd Maste
1546435933ddSDimitry Andric if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1547435933ddSDimitry Andric // If the collection size is 0, it's a full match and we can just
1548435933ddSDimitry Andric // remove the breakpoint.
1549435933ddSDimitry Andric if (loc_coll.GetSize() == 0) {
1550ac7ddfbfSEd Maste bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1551ac7ddfbfSEd Maste ss.EOL();
1552ac7ddfbfSEd Maste target->RemoveBreakpointByID(bp->GetID());
1553ac7ddfbfSEd Maste ++num_cleared;
1554ac7ddfbfSEd Maste }
1555ac7ddfbfSEd Maste }
1556ac7ddfbfSEd Maste }
1557435933ddSDimitry Andric } break;
1558ac7ddfbfSEd Maste
1559ac7ddfbfSEd Maste default:
1560ac7ddfbfSEd Maste break;
1561ac7ddfbfSEd Maste }
1562ac7ddfbfSEd Maste
1563435933ddSDimitry Andric if (num_cleared > 0) {
1564ac7ddfbfSEd Maste Stream &output_stream = result.GetOutputStream();
1565ac7ddfbfSEd Maste output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1566435933ddSDimitry Andric output_stream << ss.GetString();
1567ac7ddfbfSEd Maste output_stream.EOL();
1568ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1569435933ddSDimitry Andric } else {
1570ac7ddfbfSEd Maste result.AppendError("Breakpoint clear: No breakpoint cleared.");
1571ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1572ac7ddfbfSEd Maste }
1573ac7ddfbfSEd Maste
1574ac7ddfbfSEd Maste return result.Succeeded();
1575ac7ddfbfSEd Maste }
1576ac7ddfbfSEd Maste
1577ac7ddfbfSEd Maste private:
1578ac7ddfbfSEd Maste CommandOptions m_options;
1579ac7ddfbfSEd Maste };
1580ac7ddfbfSEd Maste
1581ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1582ac7ddfbfSEd Maste // CommandObjectBreakpointDelete
1583ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1584*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_delete_options[] = {
1585435933ddSDimitry Andric // clang-format off
1586*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1587*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1588435933ddSDimitry Andric // clang-format on
1589435933ddSDimitry Andric };
1590435933ddSDimitry Andric
1591ac7ddfbfSEd Maste #pragma mark Delete
1592ac7ddfbfSEd Maste
1593435933ddSDimitry Andric class CommandObjectBreakpointDelete : public CommandObjectParsed {
1594ac7ddfbfSEd Maste public:
CommandObjectBreakpointDelete(CommandInterpreter & interpreter)1595435933ddSDimitry Andric CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1596435933ddSDimitry Andric : CommandObjectParsed(interpreter, "breakpoint delete",
1597435933ddSDimitry Andric "Delete the specified breakpoint(s). If no "
1598435933ddSDimitry Andric "breakpoints are specified, delete them all.",
15994bb0738eSEd Maste nullptr),
1600435933ddSDimitry Andric m_options() {
1601ac7ddfbfSEd Maste CommandArgumentEntry arg;
1602435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1603435933ddSDimitry Andric eArgTypeBreakpointIDRange);
1604435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
1605435933ddSDimitry Andric // arguments vector.
1606ac7ddfbfSEd Maste m_arguments.push_back(arg);
1607ac7ddfbfSEd Maste }
1608ac7ddfbfSEd Maste
16094bb0738eSEd Maste ~CommandObjectBreakpointDelete() override = default;
1610ac7ddfbfSEd Maste
GetOptions()1611435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
16127aa51b79SEd Maste
1613435933ddSDimitry Andric class CommandOptions : public Options {
16147aa51b79SEd Maste public:
CommandOptions()1615435933ddSDimitry Andric CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
16167aa51b79SEd Maste
16174bb0738eSEd Maste ~CommandOptions() override = default;
16187aa51b79SEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)16195517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1620435933ddSDimitry Andric ExecutionContext *execution_context) override {
16215517e702SDimitry Andric Status error;
16227aa51b79SEd Maste const int short_option = m_getopt_table[option_idx].val;
16237aa51b79SEd Maste
1624435933ddSDimitry Andric switch (short_option) {
16257aa51b79SEd Maste case 'f':
16267aa51b79SEd Maste m_force = true;
16277aa51b79SEd Maste break;
16287aa51b79SEd Maste
16297aa51b79SEd Maste case 'D':
16307aa51b79SEd Maste m_use_dummy = true;
16317aa51b79SEd Maste break;
16327aa51b79SEd Maste
16337aa51b79SEd Maste default:
1634435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
1635435933ddSDimitry Andric short_option);
16367aa51b79SEd Maste break;
16377aa51b79SEd Maste }
16387aa51b79SEd Maste
16397aa51b79SEd Maste return error;
16407aa51b79SEd Maste }
16417aa51b79SEd Maste
OptionParsingStarting(ExecutionContext * execution_context)1642435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
16437aa51b79SEd Maste m_use_dummy = false;
16447aa51b79SEd Maste m_force = false;
16457aa51b79SEd Maste }
16467aa51b79SEd Maste
GetDefinitions()1647435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1648435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_delete_options);
16497aa51b79SEd Maste }
16507aa51b79SEd Maste
16517aa51b79SEd Maste // Instance variables to hold the values for command options.
16527aa51b79SEd Maste bool m_use_dummy;
16537aa51b79SEd Maste bool m_force;
16547aa51b79SEd Maste };
16557aa51b79SEd Maste
1656ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1657435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
16587aa51b79SEd Maste Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
16597aa51b79SEd Maste
1660435933ddSDimitry Andric if (target == nullptr) {
1661ac7ddfbfSEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
1662ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1663ac7ddfbfSEd Maste return false;
1664ac7ddfbfSEd Maste }
1665ac7ddfbfSEd Maste
16664bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
16674bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
1668ac7ddfbfSEd Maste
1669ac7ddfbfSEd Maste const BreakpointList &breakpoints = target->GetBreakpointList();
1670ac7ddfbfSEd Maste
1671ac7ddfbfSEd Maste size_t num_breakpoints = breakpoints.GetSize();
1672ac7ddfbfSEd Maste
1673435933ddSDimitry Andric if (num_breakpoints == 0) {
1674ac7ddfbfSEd Maste result.AppendError("No breakpoints exist to be deleted.");
1675ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1676ac7ddfbfSEd Maste return false;
1677ac7ddfbfSEd Maste }
1678ac7ddfbfSEd Maste
1679435933ddSDimitry Andric if (command.empty()) {
1680435933ddSDimitry Andric if (!m_options.m_force &&
1681435933ddSDimitry Andric !m_interpreter.Confirm(
1682435933ddSDimitry Andric "About to delete all breakpoints, do you want to do that?",
1683435933ddSDimitry Andric true)) {
1684ac7ddfbfSEd Maste result.AppendMessage("Operation cancelled...");
1685435933ddSDimitry Andric } else {
1686acac075bSDimitry Andric target->RemoveAllowedBreakpoints();
1687435933ddSDimitry Andric result.AppendMessageWithFormat(
1688435933ddSDimitry Andric "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1689435933ddSDimitry Andric (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1690ac7ddfbfSEd Maste }
1691ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1692435933ddSDimitry Andric } else {
1693ac7ddfbfSEd Maste // Particular breakpoint selected; disable that breakpoint.
1694ac7ddfbfSEd Maste BreakpointIDList valid_bp_ids;
1695435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1696acac075bSDimitry Andric command, target, result, &valid_bp_ids,
1697acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::deletePerm);
1698ac7ddfbfSEd Maste
1699435933ddSDimitry Andric if (result.Succeeded()) {
1700ac7ddfbfSEd Maste int delete_count = 0;
1701ac7ddfbfSEd Maste int disable_count = 0;
1702ac7ddfbfSEd Maste const size_t count = valid_bp_ids.GetSize();
1703435933ddSDimitry Andric for (size_t i = 0; i < count; ++i) {
1704ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1705ac7ddfbfSEd Maste
1706435933ddSDimitry Andric if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1707435933ddSDimitry Andric if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1708435933ddSDimitry Andric Breakpoint *breakpoint =
1709435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1710435933ddSDimitry Andric BreakpointLocation *location =
1711435933ddSDimitry Andric breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1712435933ddSDimitry Andric // It makes no sense to try to delete individual locations, so we
1713435933ddSDimitry Andric // disable them instead.
1714435933ddSDimitry Andric if (location) {
1715ac7ddfbfSEd Maste location->SetEnabled(false);
1716ac7ddfbfSEd Maste ++disable_count;
1717ac7ddfbfSEd Maste }
1718435933ddSDimitry Andric } else {
1719ac7ddfbfSEd Maste target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1720ac7ddfbfSEd Maste ++delete_count;
1721ac7ddfbfSEd Maste }
1722ac7ddfbfSEd Maste }
1723ac7ddfbfSEd Maste }
1724435933ddSDimitry Andric result.AppendMessageWithFormat(
1725435933ddSDimitry Andric "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1726ac7ddfbfSEd Maste delete_count, disable_count);
1727ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1728ac7ddfbfSEd Maste }
1729ac7ddfbfSEd Maste }
1730ac7ddfbfSEd Maste return result.Succeeded();
1731ac7ddfbfSEd Maste }
17324bb0738eSEd Maste
17337aa51b79SEd Maste private:
17347aa51b79SEd Maste CommandOptions m_options;
1735ac7ddfbfSEd Maste };
1736ac7ddfbfSEd Maste
17377aa51b79SEd Maste //-------------------------------------------------------------------------
17387aa51b79SEd Maste // CommandObjectBreakpointName
17397aa51b79SEd Maste //-------------------------------------------------------------------------
17407aa51b79SEd Maste
1741*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_name_options[] = {
1742435933ddSDimitry Andric // clang-format off
1743*b5893f02SDimitry Andric {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1744*b5893f02SDimitry Andric {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1745*b5893f02SDimitry Andric {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1746*b5893f02SDimitry Andric {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
1747435933ddSDimitry Andric // clang-format on
17487aa51b79SEd Maste };
1749435933ddSDimitry Andric class BreakpointNameOptionGroup : public OptionGroup {
17507aa51b79SEd Maste public:
BreakpointNameOptionGroup()1751435933ddSDimitry Andric BreakpointNameOptionGroup()
1752435933ddSDimitry Andric : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
17537aa51b79SEd Maste }
17547aa51b79SEd Maste
17554bb0738eSEd Maste ~BreakpointNameOptionGroup() override = default;
17567aa51b79SEd Maste
GetDefinitions()1757435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1758435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_name_options);
17597aa51b79SEd Maste }
17607aa51b79SEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)17615517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1762435933ddSDimitry Andric ExecutionContext *execution_context) override {
17635517e702SDimitry Andric Status error;
17647aa51b79SEd Maste const int short_option = g_breakpoint_name_options[option_idx].short_option;
17657aa51b79SEd Maste
1766435933ddSDimitry Andric switch (short_option) {
17677aa51b79SEd Maste case 'N':
1768435933ddSDimitry Andric if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1769435933ddSDimitry Andric error.Success())
1770435933ddSDimitry Andric m_name.SetValueFromString(option_arg);
17717aa51b79SEd Maste break;
17727aa51b79SEd Maste case 'B':
1773435933ddSDimitry Andric if (m_breakpoint.SetValueFromString(option_arg).Fail())
1774435933ddSDimitry Andric error.SetErrorStringWithFormat(
1775435933ddSDimitry Andric "unrecognized value \"%s\" for breakpoint",
1776435933ddSDimitry Andric option_arg.str().c_str());
17777aa51b79SEd Maste break;
17787aa51b79SEd Maste case 'D':
1779435933ddSDimitry Andric if (m_use_dummy.SetValueFromString(option_arg).Fail())
1780435933ddSDimitry Andric error.SetErrorStringWithFormat(
1781435933ddSDimitry Andric "unrecognized value \"%s\" for use-dummy",
1782435933ddSDimitry Andric option_arg.str().c_str());
17837aa51b79SEd Maste break;
1784acac075bSDimitry Andric case 'H':
1785acac075bSDimitry Andric m_help_string.SetValueFromString(option_arg);
1786acac075bSDimitry Andric break;
17877aa51b79SEd Maste
17887aa51b79SEd Maste default:
1789435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized short option '%c'",
1790435933ddSDimitry Andric short_option);
17917aa51b79SEd Maste break;
17927aa51b79SEd Maste }
17937aa51b79SEd Maste return error;
17947aa51b79SEd Maste }
17957aa51b79SEd Maste
OptionParsingStarting(ExecutionContext * execution_context)1796435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
17977aa51b79SEd Maste m_name.Clear();
17987aa51b79SEd Maste m_breakpoint.Clear();
17997aa51b79SEd Maste m_use_dummy.Clear();
18007aa51b79SEd Maste m_use_dummy.SetDefaultValue(false);
1801acac075bSDimitry Andric m_help_string.Clear();
18027aa51b79SEd Maste }
18037aa51b79SEd Maste
18047aa51b79SEd Maste OptionValueString m_name;
18057aa51b79SEd Maste OptionValueUInt64 m_breakpoint;
18067aa51b79SEd Maste OptionValueBoolean m_use_dummy;
1807acac075bSDimitry Andric OptionValueString m_help_string;
1808acac075bSDimitry Andric };
1809acac075bSDimitry Andric
1810*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_access_options[] = {
1811acac075bSDimitry Andric // clang-format off
1812*b5893f02SDimitry Andric {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
1813*b5893f02SDimitry Andric {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
1814*b5893f02SDimitry Andric {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
1815acac075bSDimitry Andric // clang-format on
1816acac075bSDimitry Andric };
1817acac075bSDimitry Andric
1818*b5893f02SDimitry Andric class BreakpointAccessOptionGroup : public OptionGroup {
1819acac075bSDimitry Andric public:
BreakpointAccessOptionGroup()1820*b5893f02SDimitry Andric BreakpointAccessOptionGroup() : OptionGroup() {}
1821acac075bSDimitry Andric
1822acac075bSDimitry Andric ~BreakpointAccessOptionGroup() override = default;
1823acac075bSDimitry Andric
GetDefinitions()1824acac075bSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1825acac075bSDimitry Andric return llvm::makeArrayRef(g_breakpoint_access_options);
1826acac075bSDimitry Andric }
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1827acac075bSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1828acac075bSDimitry Andric ExecutionContext *execution_context) override {
1829acac075bSDimitry Andric Status error;
1830acac075bSDimitry Andric const int short_option
1831acac075bSDimitry Andric = g_breakpoint_access_options[option_idx].short_option;
1832acac075bSDimitry Andric
1833acac075bSDimitry Andric switch (short_option) {
1834acac075bSDimitry Andric case 'L': {
1835acac075bSDimitry Andric bool value, success;
18364ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
1837acac075bSDimitry Andric if (success) {
1838acac075bSDimitry Andric m_permissions.SetAllowList(value);
1839acac075bSDimitry Andric } else
1840acac075bSDimitry Andric error.SetErrorStringWithFormat(
1841acac075bSDimitry Andric "invalid boolean value '%s' passed for -L option",
1842acac075bSDimitry Andric option_arg.str().c_str());
1843acac075bSDimitry Andric } break;
1844acac075bSDimitry Andric case 'A': {
1845acac075bSDimitry Andric bool value, success;
18464ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
1847acac075bSDimitry Andric if (success) {
1848acac075bSDimitry Andric m_permissions.SetAllowDisable(value);
1849acac075bSDimitry Andric } else
1850acac075bSDimitry Andric error.SetErrorStringWithFormat(
1851acac075bSDimitry Andric "invalid boolean value '%s' passed for -L option",
1852acac075bSDimitry Andric option_arg.str().c_str());
1853acac075bSDimitry Andric } break;
1854acac075bSDimitry Andric case 'D': {
1855acac075bSDimitry Andric bool value, success;
18564ba319b5SDimitry Andric value = OptionArgParser::ToBoolean(option_arg, false, &success);
1857acac075bSDimitry Andric if (success) {
1858acac075bSDimitry Andric m_permissions.SetAllowDelete(value);
1859acac075bSDimitry Andric } else
1860acac075bSDimitry Andric error.SetErrorStringWithFormat(
1861acac075bSDimitry Andric "invalid boolean value '%s' passed for -L option",
1862acac075bSDimitry Andric option_arg.str().c_str());
1863acac075bSDimitry Andric } break;
1864acac075bSDimitry Andric
1865acac075bSDimitry Andric }
1866acac075bSDimitry Andric
1867acac075bSDimitry Andric return error;
1868acac075bSDimitry Andric }
1869acac075bSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1870acac075bSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1871acac075bSDimitry Andric }
1872acac075bSDimitry Andric
GetPermissions() const1873acac075bSDimitry Andric const BreakpointName::Permissions &GetPermissions() const
1874acac075bSDimitry Andric {
1875acac075bSDimitry Andric return m_permissions;
1876acac075bSDimitry Andric }
1877acac075bSDimitry Andric BreakpointName::Permissions m_permissions;
1878acac075bSDimitry Andric };
1879acac075bSDimitry Andric
1880acac075bSDimitry Andric class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1881acac075bSDimitry Andric public:
CommandObjectBreakpointNameConfigure(CommandInterpreter & interpreter)1882acac075bSDimitry Andric CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1883acac075bSDimitry Andric : CommandObjectParsed(
1884acac075bSDimitry Andric interpreter, "configure", "Configure the options for the breakpoint"
1885acac075bSDimitry Andric " name provided. "
1886acac075bSDimitry Andric "If you provide a breakpoint id, the options will be copied from "
1887acac075bSDimitry Andric "the breakpoint, otherwise only the options specified will be set "
1888acac075bSDimitry Andric "on the name.",
1889acac075bSDimitry Andric "breakpoint name configure <command-options> "
1890acac075bSDimitry Andric "<breakpoint-name-list>"),
1891acac075bSDimitry Andric m_bp_opts(), m_option_group() {
1892acac075bSDimitry Andric // Create the first variant for the first (and only) argument for this
1893acac075bSDimitry Andric // command.
1894acac075bSDimitry Andric CommandArgumentEntry arg1;
1895acac075bSDimitry Andric CommandArgumentData id_arg;
1896acac075bSDimitry Andric id_arg.arg_type = eArgTypeBreakpointName;
1897acac075bSDimitry Andric id_arg.arg_repetition = eArgRepeatOptional;
1898acac075bSDimitry Andric arg1.push_back(id_arg);
1899acac075bSDimitry Andric m_arguments.push_back(arg1);
1900acac075bSDimitry Andric
1901acac075bSDimitry Andric m_option_group.Append(&m_bp_opts,
1902acac075bSDimitry Andric LLDB_OPT_SET_ALL,
1903acac075bSDimitry Andric LLDB_OPT_SET_1);
1904acac075bSDimitry Andric m_option_group.Append(&m_access_options,
1905acac075bSDimitry Andric LLDB_OPT_SET_ALL,
1906acac075bSDimitry Andric LLDB_OPT_SET_ALL);
1907acac075bSDimitry Andric m_option_group.Append(&m_bp_id,
1908acac075bSDimitry Andric LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1909acac075bSDimitry Andric LLDB_OPT_SET_ALL);
1910acac075bSDimitry Andric m_option_group.Finalize();
1911acac075bSDimitry Andric }
1912acac075bSDimitry Andric
1913acac075bSDimitry Andric ~CommandObjectBreakpointNameConfigure() override = default;
1914acac075bSDimitry Andric
GetOptions()1915acac075bSDimitry Andric Options *GetOptions() override { return &m_option_group; }
1916acac075bSDimitry Andric
1917acac075bSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1918acac075bSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1919acac075bSDimitry Andric
1920acac075bSDimitry Andric const size_t argc = command.GetArgumentCount();
1921acac075bSDimitry Andric if (argc == 0) {
1922acac075bSDimitry Andric result.AppendError("No names provided.");
1923acac075bSDimitry Andric result.SetStatus(eReturnStatusFailed);
1924acac075bSDimitry Andric return false;
1925acac075bSDimitry Andric }
1926acac075bSDimitry Andric
1927acac075bSDimitry Andric Target *target =
1928acac075bSDimitry Andric GetSelectedOrDummyTarget(false);
1929acac075bSDimitry Andric
1930acac075bSDimitry Andric if (target == nullptr) {
1931acac075bSDimitry Andric result.AppendError("Invalid target. No existing target or breakpoints.");
1932acac075bSDimitry Andric result.SetStatus(eReturnStatusFailed);
1933acac075bSDimitry Andric return false;
1934acac075bSDimitry Andric }
1935acac075bSDimitry Andric
1936acac075bSDimitry Andric std::unique_lock<std::recursive_mutex> lock;
1937acac075bSDimitry Andric target->GetBreakpointList().GetListMutex(lock);
1938acac075bSDimitry Andric
1939acac075bSDimitry Andric // Make a pass through first to see that all the names are legal.
1940acac075bSDimitry Andric for (auto &entry : command.entries()) {
1941acac075bSDimitry Andric Status error;
1942acac075bSDimitry Andric if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1943acac075bSDimitry Andric {
1944acac075bSDimitry Andric result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1945acac075bSDimitry Andric entry.c_str(), error.AsCString());
1946acac075bSDimitry Andric result.SetStatus(eReturnStatusFailed);
1947acac075bSDimitry Andric return false;
1948acac075bSDimitry Andric }
1949acac075bSDimitry Andric }
19504ba319b5SDimitry Andric // Now configure them, we already pre-checked the names so we don't need to
19514ba319b5SDimitry Andric // check the error:
1952acac075bSDimitry Andric BreakpointSP bp_sp;
1953acac075bSDimitry Andric if (m_bp_id.m_breakpoint.OptionWasSet())
1954acac075bSDimitry Andric {
1955acac075bSDimitry Andric lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1956acac075bSDimitry Andric bp_sp = target->GetBreakpointByID(bp_id);
1957acac075bSDimitry Andric if (!bp_sp)
1958acac075bSDimitry Andric {
1959acac075bSDimitry Andric result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1960acac075bSDimitry Andric bp_id);
1961acac075bSDimitry Andric result.SetStatus(eReturnStatusFailed);
1962acac075bSDimitry Andric return false;
1963acac075bSDimitry Andric }
1964acac075bSDimitry Andric }
1965acac075bSDimitry Andric
1966acac075bSDimitry Andric Status error;
1967acac075bSDimitry Andric for (auto &entry : command.entries()) {
1968acac075bSDimitry Andric ConstString name(entry.c_str());
1969acac075bSDimitry Andric BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1970acac075bSDimitry Andric if (!bp_name)
1971acac075bSDimitry Andric continue;
1972acac075bSDimitry Andric if (m_bp_id.m_help_string.OptionWasSet())
1973acac075bSDimitry Andric bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1974acac075bSDimitry Andric
1975acac075bSDimitry Andric if (bp_sp)
1976acac075bSDimitry Andric target->ConfigureBreakpointName(*bp_name,
1977acac075bSDimitry Andric *bp_sp->GetOptions(),
1978acac075bSDimitry Andric m_access_options.GetPermissions());
1979acac075bSDimitry Andric else
1980acac075bSDimitry Andric target->ConfigureBreakpointName(*bp_name,
1981acac075bSDimitry Andric m_bp_opts.GetBreakpointOptions(),
1982acac075bSDimitry Andric m_access_options.GetPermissions());
1983acac075bSDimitry Andric }
1984acac075bSDimitry Andric return true;
1985acac075bSDimitry Andric }
1986acac075bSDimitry Andric
1987acac075bSDimitry Andric private:
1988acac075bSDimitry Andric BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1989acac075bSDimitry Andric BreakpointOptionGroup m_bp_opts;
1990acac075bSDimitry Andric BreakpointAccessOptionGroup m_access_options;
1991acac075bSDimitry Andric OptionGroupOptions m_option_group;
19927aa51b79SEd Maste };
19937aa51b79SEd Maste
1994435933ddSDimitry Andric class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
19957aa51b79SEd Maste public:
CommandObjectBreakpointNameAdd(CommandInterpreter & interpreter)1996435933ddSDimitry Andric CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1997435933ddSDimitry Andric : CommandObjectParsed(
1998435933ddSDimitry Andric interpreter, "add", "Add a name to the breakpoints provided.",
19997aa51b79SEd Maste "breakpoint name add <command-options> <breakpoint-id-list>"),
2000435933ddSDimitry Andric m_name_options(), m_option_group() {
2001435933ddSDimitry Andric // Create the first variant for the first (and only) argument for this
2002435933ddSDimitry Andric // command.
20037aa51b79SEd Maste CommandArgumentEntry arg1;
20047aa51b79SEd Maste CommandArgumentData id_arg;
20057aa51b79SEd Maste id_arg.arg_type = eArgTypeBreakpointID;
20067aa51b79SEd Maste id_arg.arg_repetition = eArgRepeatOptional;
20077aa51b79SEd Maste arg1.push_back(id_arg);
20087aa51b79SEd Maste m_arguments.push_back(arg1);
20097aa51b79SEd Maste
20107aa51b79SEd Maste m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
20117aa51b79SEd Maste m_option_group.Finalize();
20127aa51b79SEd Maste }
20137aa51b79SEd Maste
20144bb0738eSEd Maste ~CommandObjectBreakpointNameAdd() override = default;
20157aa51b79SEd Maste
GetOptions()2016435933ddSDimitry Andric Options *GetOptions() override { return &m_option_group; }
20177aa51b79SEd Maste
20187aa51b79SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2019435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
2020435933ddSDimitry Andric if (!m_name_options.m_name.OptionWasSet()) {
20217aa51b79SEd Maste result.SetError("No name option provided.");
20227aa51b79SEd Maste return false;
20237aa51b79SEd Maste }
20247aa51b79SEd Maste
2025435933ddSDimitry Andric Target *target =
2026435933ddSDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
20277aa51b79SEd Maste
2028435933ddSDimitry Andric if (target == nullptr) {
20297aa51b79SEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
20307aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
20317aa51b79SEd Maste return false;
20327aa51b79SEd Maste }
20337aa51b79SEd Maste
20344bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
20354bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
20367aa51b79SEd Maste
20377aa51b79SEd Maste const BreakpointList &breakpoints = target->GetBreakpointList();
20387aa51b79SEd Maste
20397aa51b79SEd Maste size_t num_breakpoints = breakpoints.GetSize();
2040435933ddSDimitry Andric if (num_breakpoints == 0) {
20417aa51b79SEd Maste result.SetError("No breakpoints, cannot add names.");
20427aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
20437aa51b79SEd Maste return false;
20447aa51b79SEd Maste }
20457aa51b79SEd Maste
20467aa51b79SEd Maste // Particular breakpoint selected; disable that breakpoint.
20477aa51b79SEd Maste BreakpointIDList valid_bp_ids;
2048435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2049acac075bSDimitry Andric command, target, result, &valid_bp_ids,
2050acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
20517aa51b79SEd Maste
2052435933ddSDimitry Andric if (result.Succeeded()) {
2053435933ddSDimitry Andric if (valid_bp_ids.GetSize() == 0) {
20547aa51b79SEd Maste result.SetError("No breakpoints specified, cannot add names.");
20557aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
20567aa51b79SEd Maste return false;
20577aa51b79SEd Maste }
20587aa51b79SEd Maste size_t num_valid_ids = valid_bp_ids.GetSize();
2059acac075bSDimitry Andric const char *bp_name = m_name_options.m_name.GetCurrentValue();
2060acac075bSDimitry Andric Status error; // This error reports illegal names, but we've already
2061acac075bSDimitry Andric // checked that, so we don't need to check it again here.
2062435933ddSDimitry Andric for (size_t index = 0; index < num_valid_ids; index++) {
2063435933ddSDimitry Andric lldb::break_id_t bp_id =
2064435933ddSDimitry Andric valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
20657aa51b79SEd Maste BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2066acac075bSDimitry Andric target->AddNameToBreakpoint(bp_sp, bp_name, error);
20677aa51b79SEd Maste }
20687aa51b79SEd Maste }
20697aa51b79SEd Maste
20707aa51b79SEd Maste return true;
20717aa51b79SEd Maste }
20727aa51b79SEd Maste
20737aa51b79SEd Maste private:
20747aa51b79SEd Maste BreakpointNameOptionGroup m_name_options;
20757aa51b79SEd Maste OptionGroupOptions m_option_group;
20767aa51b79SEd Maste };
20777aa51b79SEd Maste
2078435933ddSDimitry Andric class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
20797aa51b79SEd Maste public:
CommandObjectBreakpointNameDelete(CommandInterpreter & interpreter)2080435933ddSDimitry Andric CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2081435933ddSDimitry Andric : CommandObjectParsed(
2082435933ddSDimitry Andric interpreter, "delete",
20837aa51b79SEd Maste "Delete a name from the breakpoints provided.",
20847aa51b79SEd Maste "breakpoint name delete <command-options> <breakpoint-id-list>"),
2085435933ddSDimitry Andric m_name_options(), m_option_group() {
2086435933ddSDimitry Andric // Create the first variant for the first (and only) argument for this
2087435933ddSDimitry Andric // command.
20887aa51b79SEd Maste CommandArgumentEntry arg1;
20897aa51b79SEd Maste CommandArgumentData id_arg;
20907aa51b79SEd Maste id_arg.arg_type = eArgTypeBreakpointID;
20917aa51b79SEd Maste id_arg.arg_repetition = eArgRepeatOptional;
20927aa51b79SEd Maste arg1.push_back(id_arg);
20937aa51b79SEd Maste m_arguments.push_back(arg1);
20947aa51b79SEd Maste
20957aa51b79SEd Maste m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
20967aa51b79SEd Maste m_option_group.Finalize();
20977aa51b79SEd Maste }
20987aa51b79SEd Maste
20994bb0738eSEd Maste ~CommandObjectBreakpointNameDelete() override = default;
21007aa51b79SEd Maste
GetOptions()2101435933ddSDimitry Andric Options *GetOptions() override { return &m_option_group; }
21027aa51b79SEd Maste
21037aa51b79SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2104435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
2105435933ddSDimitry Andric if (!m_name_options.m_name.OptionWasSet()) {
21067aa51b79SEd Maste result.SetError("No name option provided.");
21077aa51b79SEd Maste return false;
21087aa51b79SEd Maste }
21097aa51b79SEd Maste
2110435933ddSDimitry Andric Target *target =
2111435933ddSDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
21127aa51b79SEd Maste
2113435933ddSDimitry Andric if (target == nullptr) {
21147aa51b79SEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
21157aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
21167aa51b79SEd Maste return false;
21177aa51b79SEd Maste }
21187aa51b79SEd Maste
21194bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
21204bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
21217aa51b79SEd Maste
21227aa51b79SEd Maste const BreakpointList &breakpoints = target->GetBreakpointList();
21237aa51b79SEd Maste
21247aa51b79SEd Maste size_t num_breakpoints = breakpoints.GetSize();
2125435933ddSDimitry Andric if (num_breakpoints == 0) {
21267aa51b79SEd Maste result.SetError("No breakpoints, cannot delete names.");
21277aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
21287aa51b79SEd Maste return false;
21297aa51b79SEd Maste }
21307aa51b79SEd Maste
21317aa51b79SEd Maste // Particular breakpoint selected; disable that breakpoint.
21327aa51b79SEd Maste BreakpointIDList valid_bp_ids;
2133435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2134acac075bSDimitry Andric command, target, result, &valid_bp_ids,
2135acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::deletePerm);
21367aa51b79SEd Maste
2137435933ddSDimitry Andric if (result.Succeeded()) {
2138435933ddSDimitry Andric if (valid_bp_ids.GetSize() == 0) {
21397aa51b79SEd Maste result.SetError("No breakpoints specified, cannot delete names.");
21407aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
21417aa51b79SEd Maste return false;
21427aa51b79SEd Maste }
2143acac075bSDimitry Andric ConstString bp_name(m_name_options.m_name.GetCurrentValue());
21447aa51b79SEd Maste size_t num_valid_ids = valid_bp_ids.GetSize();
2145435933ddSDimitry Andric for (size_t index = 0; index < num_valid_ids; index++) {
2146435933ddSDimitry Andric lldb::break_id_t bp_id =
2147435933ddSDimitry Andric valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
21487aa51b79SEd Maste BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
2149acac075bSDimitry Andric target->RemoveNameFromBreakpoint(bp_sp, bp_name);
21507aa51b79SEd Maste }
21517aa51b79SEd Maste }
21527aa51b79SEd Maste
21537aa51b79SEd Maste return true;
21547aa51b79SEd Maste }
21557aa51b79SEd Maste
21567aa51b79SEd Maste private:
21577aa51b79SEd Maste BreakpointNameOptionGroup m_name_options;
21587aa51b79SEd Maste OptionGroupOptions m_option_group;
21597aa51b79SEd Maste };
21607aa51b79SEd Maste
2161435933ddSDimitry Andric class CommandObjectBreakpointNameList : public CommandObjectParsed {
21627aa51b79SEd Maste public:
CommandObjectBreakpointNameList(CommandInterpreter & interpreter)2163435933ddSDimitry Andric CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2164435933ddSDimitry Andric : CommandObjectParsed(interpreter, "list",
2165acac075bSDimitry Andric "List either the names for a breakpoint or info "
2166acac075bSDimitry Andric "about a given name. With no arguments, lists all "
2167acac075bSDimitry Andric "names",
21687aa51b79SEd Maste "breakpoint name list <command-options>"),
2169435933ddSDimitry Andric m_name_options(), m_option_group() {
2170acac075bSDimitry Andric m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
21717aa51b79SEd Maste m_option_group.Finalize();
21727aa51b79SEd Maste }
21737aa51b79SEd Maste
21744bb0738eSEd Maste ~CommandObjectBreakpointNameList() override = default;
21757aa51b79SEd Maste
GetOptions()2176435933ddSDimitry Andric Options *GetOptions() override { return &m_option_group; }
21777aa51b79SEd Maste
21787aa51b79SEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2179435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
2180435933ddSDimitry Andric Target *target =
2181435933ddSDimitry Andric GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
21827aa51b79SEd Maste
2183435933ddSDimitry Andric if (target == nullptr) {
21847aa51b79SEd Maste result.AppendError("Invalid target. No existing target or breakpoints.");
21857aa51b79SEd Maste result.SetStatus(eReturnStatusFailed);
21867aa51b79SEd Maste return false;
21877aa51b79SEd Maste }
21887aa51b79SEd Maste
2189acac075bSDimitry Andric
2190acac075bSDimitry Andric std::vector<std::string> name_list;
2191acac075bSDimitry Andric if (command.empty()) {
2192acac075bSDimitry Andric target->GetBreakpointNames(name_list);
2193acac075bSDimitry Andric } else {
2194acac075bSDimitry Andric for (const Args::ArgEntry &arg : command)
2195acac075bSDimitry Andric {
2196acac075bSDimitry Andric name_list.push_back(arg.c_str());
2197acac075bSDimitry Andric }
2198acac075bSDimitry Andric }
2199acac075bSDimitry Andric
2200acac075bSDimitry Andric if (name_list.empty()) {
2201acac075bSDimitry Andric result.AppendMessage("No breakpoint names found.");
2202acac075bSDimitry Andric } else {
2203acac075bSDimitry Andric for (const std::string &name_str : name_list) {
2204acac075bSDimitry Andric const char *name = name_str.c_str();
2205acac075bSDimitry Andric // First print out the options for the name:
2206acac075bSDimitry Andric Status error;
2207acac075bSDimitry Andric BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2208acac075bSDimitry Andric false,
2209acac075bSDimitry Andric error);
2210acac075bSDimitry Andric if (bp_name)
2211acac075bSDimitry Andric {
2212acac075bSDimitry Andric StreamString s;
2213acac075bSDimitry Andric result.AppendMessageWithFormat("Name: %s\n", name);
2214acac075bSDimitry Andric if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2215acac075bSDimitry Andric {
2216acac075bSDimitry Andric result.AppendMessage(s.GetString());
2217acac075bSDimitry Andric }
2218acac075bSDimitry Andric
22194bb0738eSEd Maste std::unique_lock<std::recursive_mutex> lock;
22204bb0738eSEd Maste target->GetBreakpointList().GetListMutex(lock);
22217aa51b79SEd Maste
22227aa51b79SEd Maste BreakpointList &breakpoints = target->GetBreakpointList();
2223acac075bSDimitry Andric bool any_set = false;
2224435933ddSDimitry Andric for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2225435933ddSDimitry Andric if (bp_sp->MatchesName(name)) {
22267aa51b79SEd Maste StreamString s;
2227acac075bSDimitry Andric any_set = true;
22287aa51b79SEd Maste bp_sp->GetDescription(&s, eDescriptionLevelBrief);
22297aa51b79SEd Maste s.EOL();
2230435933ddSDimitry Andric result.AppendMessage(s.GetString());
22317aa51b79SEd Maste }
22327aa51b79SEd Maste }
2233acac075bSDimitry Andric if (!any_set)
2234acac075bSDimitry Andric result.AppendMessage("No breakpoints using this name.");
2235435933ddSDimitry Andric } else {
2236acac075bSDimitry Andric result.AppendMessageWithFormat("Name: %s not found.\n", name);
22377aa51b79SEd Maste }
2238acac075bSDimitry Andric }
22397aa51b79SEd Maste }
22407aa51b79SEd Maste return true;
22417aa51b79SEd Maste }
22427aa51b79SEd Maste
22437aa51b79SEd Maste private:
22447aa51b79SEd Maste BreakpointNameOptionGroup m_name_options;
22457aa51b79SEd Maste OptionGroupOptions m_option_group;
22467aa51b79SEd Maste };
22477aa51b79SEd Maste
22487aa51b79SEd Maste //-------------------------------------------------------------------------
2249435933ddSDimitry Andric // CommandObjectBreakpointName
22507aa51b79SEd Maste //-------------------------------------------------------------------------
2251435933ddSDimitry Andric class CommandObjectBreakpointName : public CommandObjectMultiword {
22527aa51b79SEd Maste public:
CommandObjectBreakpointName(CommandInterpreter & interpreter)22534bb0738eSEd Maste CommandObjectBreakpointName(CommandInterpreter &interpreter)
2254435933ddSDimitry Andric : CommandObjectMultiword(
2255435933ddSDimitry Andric interpreter, "name", "Commands to manage name tags for breakpoints",
2256435933ddSDimitry Andric "breakpoint name <subcommand> [<command-options>]") {
2257435933ddSDimitry Andric CommandObjectSP add_command_object(
2258435933ddSDimitry Andric new CommandObjectBreakpointNameAdd(interpreter));
2259435933ddSDimitry Andric CommandObjectSP delete_command_object(
2260435933ddSDimitry Andric new CommandObjectBreakpointNameDelete(interpreter));
2261435933ddSDimitry Andric CommandObjectSP list_command_object(
2262435933ddSDimitry Andric new CommandObjectBreakpointNameList(interpreter));
2263acac075bSDimitry Andric CommandObjectSP configure_command_object(
2264acac075bSDimitry Andric new CommandObjectBreakpointNameConfigure(interpreter));
22657aa51b79SEd Maste
22667aa51b79SEd Maste LoadSubCommand("add", add_command_object);
22677aa51b79SEd Maste LoadSubCommand("delete", delete_command_object);
22687aa51b79SEd Maste LoadSubCommand("list", list_command_object);
2269acac075bSDimitry Andric LoadSubCommand("configure", configure_command_object);
22707aa51b79SEd Maste }
22717aa51b79SEd Maste
22724bb0738eSEd Maste ~CommandObjectBreakpointName() override = default;
22737aa51b79SEd Maste };
22747aa51b79SEd Maste
2275ac7ddfbfSEd Maste //-------------------------------------------------------------------------
2276435933ddSDimitry Andric // CommandObjectBreakpointRead
2277435933ddSDimitry Andric //-------------------------------------------------------------------------
2278435933ddSDimitry Andric #pragma mark Read::CommandOptions
2279*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_read_options[] = {
2280435933ddSDimitry Andric // clang-format off
2281*b5893f02SDimitry Andric {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2282*b5893f02SDimitry Andric {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
2283435933ddSDimitry Andric // clang-format on
2284435933ddSDimitry Andric };
2285435933ddSDimitry Andric
2286435933ddSDimitry Andric #pragma mark Read
2287435933ddSDimitry Andric
2288435933ddSDimitry Andric class CommandObjectBreakpointRead : public CommandObjectParsed {
2289435933ddSDimitry Andric public:
CommandObjectBreakpointRead(CommandInterpreter & interpreter)2290435933ddSDimitry Andric CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2291435933ddSDimitry Andric : CommandObjectParsed(interpreter, "breakpoint read",
2292435933ddSDimitry Andric "Read and set the breakpoints previously saved to "
2293435933ddSDimitry Andric "a file with \"breakpoint write\". ",
2294435933ddSDimitry Andric nullptr),
2295435933ddSDimitry Andric m_options() {
2296435933ddSDimitry Andric CommandArgumentEntry arg;
2297435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2298435933ddSDimitry Andric eArgTypeBreakpointIDRange);
2299435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
2300435933ddSDimitry Andric // arguments vector.
2301435933ddSDimitry Andric m_arguments.push_back(arg);
2302435933ddSDimitry Andric }
2303435933ddSDimitry Andric
2304435933ddSDimitry Andric ~CommandObjectBreakpointRead() override = default;
2305435933ddSDimitry Andric
GetOptions()2306435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
2307435933ddSDimitry Andric
2308435933ddSDimitry Andric class CommandOptions : public Options {
2309435933ddSDimitry Andric public:
CommandOptions()2310435933ddSDimitry Andric CommandOptions() : Options() {}
2311435933ddSDimitry Andric
2312435933ddSDimitry Andric ~CommandOptions() override = default;
2313435933ddSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)23145517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2315435933ddSDimitry Andric ExecutionContext *execution_context) override {
23165517e702SDimitry Andric Status error;
2317435933ddSDimitry Andric const int short_option = m_getopt_table[option_idx].val;
2318435933ddSDimitry Andric
2319435933ddSDimitry Andric switch (short_option) {
2320435933ddSDimitry Andric case 'f':
2321435933ddSDimitry Andric m_filename.assign(option_arg);
2322435933ddSDimitry Andric break;
2323435933ddSDimitry Andric case 'N': {
23245517e702SDimitry Andric Status name_error;
2325435933ddSDimitry Andric if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2326435933ddSDimitry Andric name_error)) {
2327435933ddSDimitry Andric error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2328435933ddSDimitry Andric name_error.AsCString());
2329435933ddSDimitry Andric }
2330435933ddSDimitry Andric m_names.push_back(option_arg);
2331435933ddSDimitry Andric break;
2332435933ddSDimitry Andric }
2333435933ddSDimitry Andric default:
2334435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
2335435933ddSDimitry Andric short_option);
2336435933ddSDimitry Andric break;
2337435933ddSDimitry Andric }
2338435933ddSDimitry Andric
2339435933ddSDimitry Andric return error;
2340435933ddSDimitry Andric }
2341435933ddSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)2342435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
2343435933ddSDimitry Andric m_filename.clear();
2344435933ddSDimitry Andric m_names.clear();
2345435933ddSDimitry Andric }
2346435933ddSDimitry Andric
GetDefinitions()2347435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2348435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_read_options);
2349435933ddSDimitry Andric }
2350435933ddSDimitry Andric
2351435933ddSDimitry Andric // Instance variables to hold the values for command options.
2352435933ddSDimitry Andric
2353435933ddSDimitry Andric std::string m_filename;
2354435933ddSDimitry Andric std::vector<std::string> m_names;
2355435933ddSDimitry Andric };
2356435933ddSDimitry Andric
2357435933ddSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2358435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
2359435933ddSDimitry Andric Target *target = GetSelectedOrDummyTarget();
2360435933ddSDimitry Andric if (target == nullptr) {
2361435933ddSDimitry Andric result.AppendError("Invalid target. No existing target or breakpoints.");
2362435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
2363435933ddSDimitry Andric return false;
2364435933ddSDimitry Andric }
2365435933ddSDimitry Andric
2366435933ddSDimitry Andric std::unique_lock<std::recursive_mutex> lock;
2367435933ddSDimitry Andric target->GetBreakpointList().GetListMutex(lock);
2368435933ddSDimitry Andric
2369*b5893f02SDimitry Andric FileSpec input_spec(m_options.m_filename);
2370*b5893f02SDimitry Andric FileSystem::Instance().Resolve(input_spec);
2371435933ddSDimitry Andric BreakpointIDList new_bps;
23725517e702SDimitry Andric Status error = target->CreateBreakpointsFromFile(
23735517e702SDimitry Andric input_spec, m_options.m_names, new_bps);
2374435933ddSDimitry Andric
2375435933ddSDimitry Andric if (!error.Success()) {
2376435933ddSDimitry Andric result.AppendError(error.AsCString());
2377435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
2378435933ddSDimitry Andric return false;
2379435933ddSDimitry Andric }
2380435933ddSDimitry Andric
2381435933ddSDimitry Andric Stream &output_stream = result.GetOutputStream();
2382435933ddSDimitry Andric
2383435933ddSDimitry Andric size_t num_breakpoints = new_bps.GetSize();
2384435933ddSDimitry Andric if (num_breakpoints == 0) {
2385435933ddSDimitry Andric result.AppendMessage("No breakpoints added.");
2386435933ddSDimitry Andric } else {
2387435933ddSDimitry Andric // No breakpoint selected; show info about all currently set breakpoints.
2388435933ddSDimitry Andric result.AppendMessage("New breakpoints:");
2389435933ddSDimitry Andric for (size_t i = 0; i < num_breakpoints; ++i) {
2390435933ddSDimitry Andric BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2391435933ddSDimitry Andric Breakpoint *bp = target->GetBreakpointList()
2392435933ddSDimitry Andric .FindBreakpointByID(bp_id.GetBreakpointID())
2393435933ddSDimitry Andric .get();
2394435933ddSDimitry Andric if (bp)
2395435933ddSDimitry Andric bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2396435933ddSDimitry Andric false);
2397435933ddSDimitry Andric }
2398435933ddSDimitry Andric }
2399435933ddSDimitry Andric return result.Succeeded();
2400435933ddSDimitry Andric }
2401435933ddSDimitry Andric
2402435933ddSDimitry Andric private:
2403435933ddSDimitry Andric CommandOptions m_options;
2404435933ddSDimitry Andric };
2405435933ddSDimitry Andric
2406435933ddSDimitry Andric //-------------------------------------------------------------------------
2407435933ddSDimitry Andric // CommandObjectBreakpointWrite
2408435933ddSDimitry Andric //-------------------------------------------------------------------------
2409435933ddSDimitry Andric #pragma mark Write::CommandOptions
2410*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_write_options[] = {
2411435933ddSDimitry Andric // clang-format off
2412*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2413*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
2414435933ddSDimitry Andric // clang-format on
2415435933ddSDimitry Andric };
2416435933ddSDimitry Andric
2417435933ddSDimitry Andric #pragma mark Write
2418435933ddSDimitry Andric class CommandObjectBreakpointWrite : public CommandObjectParsed {
2419435933ddSDimitry Andric public:
CommandObjectBreakpointWrite(CommandInterpreter & interpreter)2420435933ddSDimitry Andric CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2421435933ddSDimitry Andric : CommandObjectParsed(interpreter, "breakpoint write",
2422435933ddSDimitry Andric "Write the breakpoints listed to a file that can "
2423435933ddSDimitry Andric "be read in with \"breakpoint read\". "
2424435933ddSDimitry Andric "If given no arguments, writes all breakpoints.",
2425435933ddSDimitry Andric nullptr),
2426435933ddSDimitry Andric m_options() {
2427435933ddSDimitry Andric CommandArgumentEntry arg;
2428435933ddSDimitry Andric CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2429435933ddSDimitry Andric eArgTypeBreakpointIDRange);
2430435933ddSDimitry Andric // Add the entry for the first argument for this command to the object's
2431435933ddSDimitry Andric // arguments vector.
2432435933ddSDimitry Andric m_arguments.push_back(arg);
2433435933ddSDimitry Andric }
2434435933ddSDimitry Andric
2435435933ddSDimitry Andric ~CommandObjectBreakpointWrite() override = default;
2436435933ddSDimitry Andric
GetOptions()2437435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
2438435933ddSDimitry Andric
2439435933ddSDimitry Andric class CommandOptions : public Options {
2440435933ddSDimitry Andric public:
CommandOptions()2441435933ddSDimitry Andric CommandOptions() : Options() {}
2442435933ddSDimitry Andric
2443435933ddSDimitry Andric ~CommandOptions() override = default;
2444435933ddSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)24455517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2446435933ddSDimitry Andric ExecutionContext *execution_context) override {
24475517e702SDimitry Andric Status error;
2448435933ddSDimitry Andric const int short_option = m_getopt_table[option_idx].val;
2449435933ddSDimitry Andric
2450435933ddSDimitry Andric switch (short_option) {
2451435933ddSDimitry Andric case 'f':
2452435933ddSDimitry Andric m_filename.assign(option_arg);
2453435933ddSDimitry Andric break;
2454435933ddSDimitry Andric case 'a':
2455435933ddSDimitry Andric m_append = true;
2456435933ddSDimitry Andric break;
2457435933ddSDimitry Andric default:
2458435933ddSDimitry Andric error.SetErrorStringWithFormat("unrecognized option '%c'",
2459435933ddSDimitry Andric short_option);
2460435933ddSDimitry Andric break;
2461435933ddSDimitry Andric }
2462435933ddSDimitry Andric
2463435933ddSDimitry Andric return error;
2464435933ddSDimitry Andric }
2465435933ddSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)2466435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
2467435933ddSDimitry Andric m_filename.clear();
2468435933ddSDimitry Andric m_append = false;
2469435933ddSDimitry Andric }
2470435933ddSDimitry Andric
GetDefinitions()2471435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2472435933ddSDimitry Andric return llvm::makeArrayRef(g_breakpoint_write_options);
2473435933ddSDimitry Andric }
2474435933ddSDimitry Andric
2475435933ddSDimitry Andric // Instance variables to hold the values for command options.
2476435933ddSDimitry Andric
2477435933ddSDimitry Andric std::string m_filename;
2478435933ddSDimitry Andric bool m_append = false;
2479435933ddSDimitry Andric };
2480435933ddSDimitry Andric
2481435933ddSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2482435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
2483435933ddSDimitry Andric Target *target = GetSelectedOrDummyTarget();
2484435933ddSDimitry Andric if (target == nullptr) {
2485435933ddSDimitry Andric result.AppendError("Invalid target. No existing target or breakpoints.");
2486435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
2487435933ddSDimitry Andric return false;
2488435933ddSDimitry Andric }
2489435933ddSDimitry Andric
2490435933ddSDimitry Andric std::unique_lock<std::recursive_mutex> lock;
2491435933ddSDimitry Andric target->GetBreakpointList().GetListMutex(lock);
2492435933ddSDimitry Andric
2493435933ddSDimitry Andric BreakpointIDList valid_bp_ids;
2494435933ddSDimitry Andric if (!command.empty()) {
2495435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2496acac075bSDimitry Andric command, target, result, &valid_bp_ids,
2497acac075bSDimitry Andric BreakpointName::Permissions::PermissionKinds::listPerm);
2498435933ddSDimitry Andric
2499435933ddSDimitry Andric if (!result.Succeeded()) {
2500435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
2501435933ddSDimitry Andric return false;
2502435933ddSDimitry Andric }
2503435933ddSDimitry Andric }
2504*b5893f02SDimitry Andric FileSpec file_spec(m_options.m_filename);
2505*b5893f02SDimitry Andric FileSystem::Instance().Resolve(file_spec);
2506*b5893f02SDimitry Andric Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2507*b5893f02SDimitry Andric m_options.m_append);
2508435933ddSDimitry Andric if (!error.Success()) {
2509435933ddSDimitry Andric result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2510435933ddSDimitry Andric error.AsCString());
2511435933ddSDimitry Andric result.SetStatus(eReturnStatusFailed);
2512435933ddSDimitry Andric }
2513435933ddSDimitry Andric return result.Succeeded();
2514435933ddSDimitry Andric }
2515435933ddSDimitry Andric
2516435933ddSDimitry Andric private:
2517435933ddSDimitry Andric CommandOptions m_options;
2518435933ddSDimitry Andric };
2519435933ddSDimitry Andric
2520435933ddSDimitry Andric //-------------------------------------------------------------------------
2521ac7ddfbfSEd Maste // CommandObjectMultiwordBreakpoint
2522ac7ddfbfSEd Maste //-------------------------------------------------------------------------
2523ac7ddfbfSEd Maste #pragma mark MultiwordBreakpoint
2524ac7ddfbfSEd Maste
CommandObjectMultiwordBreakpoint(CommandInterpreter & interpreter)2525435933ddSDimitry Andric CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2526435933ddSDimitry Andric CommandInterpreter &interpreter)
2527435933ddSDimitry Andric : CommandObjectMultiword(
2528435933ddSDimitry Andric interpreter, "breakpoint",
25294bb0738eSEd Maste "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2530435933ddSDimitry Andric "breakpoint <subcommand> [<command-options>]") {
2531435933ddSDimitry Andric CommandObjectSP list_command_object(
2532435933ddSDimitry Andric new CommandObjectBreakpointList(interpreter));
2533435933ddSDimitry Andric CommandObjectSP enable_command_object(
2534435933ddSDimitry Andric new CommandObjectBreakpointEnable(interpreter));
2535435933ddSDimitry Andric CommandObjectSP disable_command_object(
2536435933ddSDimitry Andric new CommandObjectBreakpointDisable(interpreter));
2537435933ddSDimitry Andric CommandObjectSP clear_command_object(
2538435933ddSDimitry Andric new CommandObjectBreakpointClear(interpreter));
2539435933ddSDimitry Andric CommandObjectSP delete_command_object(
2540435933ddSDimitry Andric new CommandObjectBreakpointDelete(interpreter));
2541435933ddSDimitry Andric CommandObjectSP set_command_object(
2542435933ddSDimitry Andric new CommandObjectBreakpointSet(interpreter));
2543435933ddSDimitry Andric CommandObjectSP command_command_object(
2544435933ddSDimitry Andric new CommandObjectBreakpointCommand(interpreter));
2545435933ddSDimitry Andric CommandObjectSP modify_command_object(
2546435933ddSDimitry Andric new CommandObjectBreakpointModify(interpreter));
2547435933ddSDimitry Andric CommandObjectSP name_command_object(
2548435933ddSDimitry Andric new CommandObjectBreakpointName(interpreter));
2549435933ddSDimitry Andric CommandObjectSP write_command_object(
2550435933ddSDimitry Andric new CommandObjectBreakpointWrite(interpreter));
2551435933ddSDimitry Andric CommandObjectSP read_command_object(
2552435933ddSDimitry Andric new CommandObjectBreakpointRead(interpreter));
2553ac7ddfbfSEd Maste
2554ac7ddfbfSEd Maste list_command_object->SetCommandName("breakpoint list");
2555ac7ddfbfSEd Maste enable_command_object->SetCommandName("breakpoint enable");
2556ac7ddfbfSEd Maste disable_command_object->SetCommandName("breakpoint disable");
2557ac7ddfbfSEd Maste clear_command_object->SetCommandName("breakpoint clear");
2558ac7ddfbfSEd Maste delete_command_object->SetCommandName("breakpoint delete");
2559ac7ddfbfSEd Maste set_command_object->SetCommandName("breakpoint set");
2560ac7ddfbfSEd Maste command_command_object->SetCommandName("breakpoint command");
2561ac7ddfbfSEd Maste modify_command_object->SetCommandName("breakpoint modify");
25627aa51b79SEd Maste name_command_object->SetCommandName("breakpoint name");
2563435933ddSDimitry Andric write_command_object->SetCommandName("breakpoint write");
2564435933ddSDimitry Andric read_command_object->SetCommandName("breakpoint read");
2565ac7ddfbfSEd Maste
2566ac7ddfbfSEd Maste LoadSubCommand("list", list_command_object);
2567ac7ddfbfSEd Maste LoadSubCommand("enable", enable_command_object);
2568ac7ddfbfSEd Maste LoadSubCommand("disable", disable_command_object);
2569ac7ddfbfSEd Maste LoadSubCommand("clear", clear_command_object);
2570ac7ddfbfSEd Maste LoadSubCommand("delete", delete_command_object);
2571ac7ddfbfSEd Maste LoadSubCommand("set", set_command_object);
2572ac7ddfbfSEd Maste LoadSubCommand("command", command_command_object);
2573ac7ddfbfSEd Maste LoadSubCommand("modify", modify_command_object);
25747aa51b79SEd Maste LoadSubCommand("name", name_command_object);
2575435933ddSDimitry Andric LoadSubCommand("write", write_command_object);
2576435933ddSDimitry Andric LoadSubCommand("read", read_command_object);
2577ac7ddfbfSEd Maste }
2578ac7ddfbfSEd Maste
25794bb0738eSEd Maste CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2580ac7ddfbfSEd Maste
VerifyIDs(Args & args,Target * target,bool allow_locations,CommandReturnObject & result,BreakpointIDList * valid_ids,BreakpointName::Permissions::PermissionKinds purpose)2581435933ddSDimitry Andric void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
25827aa51b79SEd Maste bool allow_locations,
25837aa51b79SEd Maste CommandReturnObject &result,
2584acac075bSDimitry Andric BreakpointIDList *valid_ids,
2585acac075bSDimitry Andric BreakpointName::Permissions
2586acac075bSDimitry Andric ::PermissionKinds
2587acac075bSDimitry Andric purpose) {
2588ac7ddfbfSEd Maste // args can be strings representing 1). integers (for breakpoint ids)
2589435933ddSDimitry Andric // 2). the full breakpoint & location
2590435933ddSDimitry Andric // canonical representation
2591435933ddSDimitry Andric // 3). the word "to" or a hyphen,
2592435933ddSDimitry Andric // representing a range (in which case there
2593435933ddSDimitry Andric // had *better* be an entry both before &
2594435933ddSDimitry Andric // after of one of the first two types.
25957aa51b79SEd Maste // 4). A breakpoint name
2596435933ddSDimitry Andric // If args is empty, we will use the last created breakpoint (if there is
2597435933ddSDimitry Andric // one.)
2598ac7ddfbfSEd Maste
2599ac7ddfbfSEd Maste Args temp_args;
2600ac7ddfbfSEd Maste
2601435933ddSDimitry Andric if (args.empty()) {
2602435933ddSDimitry Andric if (target->GetLastCreatedBreakpoint()) {
2603435933ddSDimitry Andric valid_ids->AddBreakpointID(BreakpointID(
2604435933ddSDimitry Andric target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2605ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
2606435933ddSDimitry Andric } else {
2607435933ddSDimitry Andric result.AppendError(
2608435933ddSDimitry Andric "No breakpoint specified and no last created breakpoint.");
2609ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
2610ac7ddfbfSEd Maste }
2611ac7ddfbfSEd Maste return;
2612ac7ddfbfSEd Maste }
2613ac7ddfbfSEd Maste
2614435933ddSDimitry Andric // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
26154ba319b5SDimitry Andric // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
26164ba319b5SDimitry Andric // id range strings over; instead generate a list of strings for all the
26174ba319b5SDimitry Andric // breakpoint ids in the range, and shove all of those breakpoint id strings
26184ba319b5SDimitry Andric // into TEMP_ARGS.
2619ac7ddfbfSEd Maste
2620435933ddSDimitry Andric BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2621acac075bSDimitry Andric purpose, result, temp_args);
2622ac7ddfbfSEd Maste
2623435933ddSDimitry Andric // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2624435933ddSDimitry Andric // BreakpointIDList:
2625ac7ddfbfSEd Maste
26264ba319b5SDimitry Andric valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
2627ac7ddfbfSEd Maste
26284ba319b5SDimitry Andric // At this point, all of the breakpoint ids that the user passed in have
26294ba319b5SDimitry Andric // been converted to breakpoint IDs and put into valid_ids.
2630ac7ddfbfSEd Maste
2631435933ddSDimitry Andric if (result.Succeeded()) {
2632435933ddSDimitry Andric // Now that we've converted everything from args into a list of breakpoint
26334ba319b5SDimitry Andric // ids, go through our tentative list of breakpoint id's and verify that
26344ba319b5SDimitry Andric // they correspond to valid/currently set breakpoints.
2635ac7ddfbfSEd Maste
2636ac7ddfbfSEd Maste const size_t count = valid_ids->GetSize();
2637435933ddSDimitry Andric for (size_t i = 0; i < count; ++i) {
2638ac7ddfbfSEd Maste BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2639435933ddSDimitry Andric Breakpoint *breakpoint =
2640435933ddSDimitry Andric target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2641435933ddSDimitry Andric if (breakpoint != nullptr) {
2642ac7ddfbfSEd Maste const size_t num_locations = breakpoint->GetNumLocations();
2643435933ddSDimitry Andric if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2644ac7ddfbfSEd Maste StreamString id_str;
2645435933ddSDimitry Andric BreakpointID::GetCanonicalReference(
2646435933ddSDimitry Andric &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2647ac7ddfbfSEd Maste i = valid_ids->GetSize() + 1;
2648435933ddSDimitry Andric result.AppendErrorWithFormat(
2649435933ddSDimitry Andric "'%s' is not a currently valid breakpoint/location id.\n",
2650ac7ddfbfSEd Maste id_str.GetData());
2651ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
2652ac7ddfbfSEd Maste }
2653435933ddSDimitry Andric } else {
2654ac7ddfbfSEd Maste i = valid_ids->GetSize() + 1;
2655435933ddSDimitry Andric result.AppendErrorWithFormat(
2656435933ddSDimitry Andric "'%d' is not a currently valid breakpoint ID.\n",
26574bb0738eSEd Maste cur_bp_id.GetBreakpointID());
2658ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
2659ac7ddfbfSEd Maste }
2660ac7ddfbfSEd Maste }
2661ac7ddfbfSEd Maste }
2662ac7ddfbfSEd Maste }
2663