blob: a4f558e7f81ba5739ab4d6223160b0dbf46cf544 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00009#include "CommandObjectBreakpoint.h"
10#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Breakpoint/Breakpoint.h"
12#include "lldb/Breakpoint/BreakpointIDList.h"
13#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000014#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000015#include "lldb/Interpreter/CommandCompletions.h"
16#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000018#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000019#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000020#include "lldb/Interpreter/OptionValueString.h"
21#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000023#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000024#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000025#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000026#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000028#include "lldb/Utility/RegularExpression.h"
29#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
Jonas Devlieghere796ac802019-02-11 23:13:08 +000031#include <memory>
32#include <vector>
33
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
39 s->IndentMore();
40 bp->GetDescription(s, level, true);
41 s->IndentLess();
42 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Jim Inghamb842f2e2017-09-14 20:22:49 +000045// Modifiable Breakpoint Options
Jim Inghamb842f2e2017-09-14 20:22:49 +000046#pragma mark Modify::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000047static constexpr OptionDefinition g_breakpoint_modify_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +000048 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000049 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
50 { 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." },
51 { 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." },
52 { 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." },
53 { 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." },
54 { 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." },
55 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
56 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
57 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
58 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
59 { 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." },
Jim Inghamb842f2e2017-09-14 20:22:49 +000060 // clang-format on
61};
62class lldb_private::BreakpointOptionGroup : public OptionGroup
63{
64public:
65 BreakpointOptionGroup() :
66 OptionGroup(),
67 m_bp_opts(false) {}
68
69 ~BreakpointOptionGroup() override = default;
70
71 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
72 return llvm::makeArrayRef(g_breakpoint_modify_options);
73 }
74
75 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76 ExecutionContext *execution_context) override {
77 Status error;
78 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
79
80 switch (short_option) {
81 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000082 // Normally an empty breakpoint condition marks is as unset. But we need
83 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000084 m_bp_opts.SetCondition(option_arg.str().c_str());
85 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
86 break;
87 case 'C':
88 m_commands.push_back(option_arg);
89 break;
90 case 'd':
91 m_bp_opts.SetEnabled(false);
92 break;
93 case 'e':
94 m_bp_opts.SetEnabled(true);
95 break;
96 case 'G': {
97 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +000098 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +000099 if (success) {
100 m_bp_opts.SetAutoContinue(value);
101 } else
102 error.SetErrorStringWithFormat(
103 "invalid boolean value '%s' passed for -G option",
104 option_arg.str().c_str());
105 }
106 break;
107 case 'i':
108 {
109 uint32_t ignore_count;
110 if (option_arg.getAsInteger(0, ignore_count))
111 error.SetErrorStringWithFormat("invalid ignore count '%s'",
112 option_arg.str().c_str());
113 else
114 m_bp_opts.SetIgnoreCount(ignore_count);
115 }
116 break;
117 case 'o': {
118 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000119 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000120 if (success) {
121 m_bp_opts.SetOneShot(value);
122 } else
123 error.SetErrorStringWithFormat(
124 "invalid boolean value '%s' passed for -o option",
125 option_arg.str().c_str());
126 } break;
127 case 't':
128 {
129 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
130 if (option_arg[0] != '\0') {
131 if (option_arg.getAsInteger(0, thread_id))
132 error.SetErrorStringWithFormat("invalid thread id string '%s'",
133 option_arg.str().c_str());
134 }
135 m_bp_opts.SetThreadID(thread_id);
136 }
137 break;
138 case 'T':
139 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
140 break;
141 case 'q':
142 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
143 break;
144 case 'x':
145 {
146 uint32_t thread_index = UINT32_MAX;
147 if (option_arg[0] != '\n') {
148 if (option_arg.getAsInteger(0, thread_index))
149 error.SetErrorStringWithFormat("invalid thread index string '%s'",
150 option_arg.str().c_str());
151 }
152 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
153 }
154 break;
155 default:
156 error.SetErrorStringWithFormat("unrecognized option '%c'",
157 short_option);
158 break;
159 }
160
161 return error;
162 }
163
164 void OptionParsingStarting(ExecutionContext *execution_context) override {
165 m_bp_opts.Clear();
166 m_commands.clear();
167 }
168
169 Status OptionParsingFinished(ExecutionContext *execution_context) override {
170 if (!m_commands.empty())
171 {
172 if (!m_commands.empty())
173 {
174 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
175
176 for (std::string &str : m_commands)
177 cmd_data->user_source.AppendString(str);
178
179 cmd_data->stop_on_error = true;
180 m_bp_opts.SetCommandDataCallback(cmd_data);
181 }
182 }
183 return Status();
184 }
185
186 const BreakpointOptions &GetBreakpointOptions()
187 {
188 return m_bp_opts;
189 }
190
191 std::vector<std::string> m_commands;
192 BreakpointOptions m_bp_opts;
193
194};
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000195static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000196 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000197 { 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, "
Jim Inghamb842f2e2017-09-14 20:22:49 +0000198 "which prime new targets." },
199 // clang-format on
200};
201
202class BreakpointDummyOptionGroup : public OptionGroup
203{
204public:
205 BreakpointDummyOptionGroup() :
206 OptionGroup() {}
207
208 ~BreakpointDummyOptionGroup() override = default;
209
210 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
211 return llvm::makeArrayRef(g_breakpoint_dummy_options);
212 }
213
214 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
215 ExecutionContext *execution_context) override {
216 Status error;
217 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
218
219 switch (short_option) {
220 case 'D':
221 m_use_dummy = true;
222 break;
223 default:
224 error.SetErrorStringWithFormat("unrecognized option '%c'",
225 short_option);
226 break;
227 }
228
229 return error;
230 }
231
232 void OptionParsingStarting(ExecutionContext *execution_context) override {
233 m_use_dummy = false;
234 }
235
236 bool m_use_dummy;
237
238};
239
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000240// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
241// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Jim Ingham3815e702018-09-13 21:35:32 +0000242#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000243#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham3815e702018-09-13 21:35:32 +0000244#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
245#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000246#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
247#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
248
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000249static constexpr OptionDefinition g_breakpoint_set_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000250 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000251 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000252 "multiple times to specify multiple shared libraries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000253 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
254 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000255 "lldb only looks for files that are #included if they use the standard include "
256 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
257 "#included, set target.inline-breakpoint-strategy to \"always\"." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000258 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000259
Adrian Prantl05097242018-04-30 16:49:04 +0000260 // Comment out this option for the moment, as we don't actually use it, but
261 // will in the future. This way users won't see it, but the infrastructure is
262 // left in place.
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000263 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
264 // "Set the breakpoint by source location at this particular column."},
265
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000266 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000267 "a particular binary, then the address will be converted to a \"file\" "
268 "address, so that the breakpoint will track that binary+offset no matter where "
269 "the binary eventually loads. Alternately, if you also specify the module - "
270 "with the -s option - then the address will be treated as a file address in "
271 "that module, and resolved accordingly. Again, this will allow lldb to track "
272 "that offset on subsequent reloads. The module need not have been loaded at "
273 "the time you specify this breakpoint, and will get resolved when the module "
274 "is loaded." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000275 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000276 "one breakpoint for multiple names" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000277 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000278 "functions. Can be repeated multiple times." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000279 { 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 "
Adrian Prantl4e8be2c2018-06-13 16:21:24 +0000280 "namespaces and all arguments, and for Objective-C this means a full function "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000281 "prototype with class and selector. Can be repeated multiple times to make "
282 "one breakpoint for multiple names." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000283 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000284 "make one breakpoint for multiple Selectors." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000285 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000286 "make one breakpoint for multiple methods." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000287 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000288 "the function name(s)." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000289 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000290 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
291 "symbols." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000292 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000293 "against the source text in a source file or files specified with the -f "
294 "option. The -f option can be specified more than once. If no source files "
295 "are specified, uses the current \"default source file\". If you want to "
296 "match against all source files, pass the \"--all-files\" option." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000297 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
298 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
299 { 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." },
300 { 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." },
301 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000302 "options, on throw but not catch.)" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000303 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
304 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000305
306 // Don't add this option till it actually does something useful...
307 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
308 // "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" },
309
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000310 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000311 "(note: currently only implemented for setting breakpoints on identifiers). "
312 "If not set the target.language setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000313 { 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. "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000314 "If not set the target.skip-prologue setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000315 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
316 { 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. "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000317 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000318 { 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 "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000319 "setting is used." },
320 // clang-format on
321};
322
Jim Ingham5a988412012-06-08 21:56:10 +0000323// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000326public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000327 enum BreakpointSetType {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000328 eSetTypeInvalid,
329 eSetTypeFileAndLine,
330 eSetTypeAddress,
331 eSetTypeFunctionName,
332 eSetTypeFunctionRegexp,
333 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000334 eSetTypeException,
335 eSetTypeScripted,
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000336 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
339 : CommandObjectParsed(
340 interpreter, "breakpoint set",
341 "Sets a breakpoint or set of breakpoints in the executable.",
342 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000343 m_bp_opts(), m_options() {
344 // We're picking up all the normal options, commands and disable.
345 m_all_options.Append(&m_bp_opts,
346 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
347 LLDB_OPT_SET_ALL);
348 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
349 m_all_options.Append(&m_options);
350 m_all_options.Finalize();
351 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352
353 ~CommandObjectBreakpointSet() override = default;
354
Jim Inghamb842f2e2017-09-14 20:22:49 +0000355 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356
Jim Inghamb842f2e2017-09-14 20:22:49 +0000357 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 public:
359 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000360 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
362 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
364 m_exception_language(eLanguageTypeUnknown),
365 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000366 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
368
369 ~CommandOptions() override = default;
370
Zachary Turner97206d52017-05-12 04:51:55 +0000371 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
372 ExecutionContext *execution_context) override {
373 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000374 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375
376 switch (short_option) {
377 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000378 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
379 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 } break;
381
382 case 'A':
383 m_all_files = true;
384 break;
385
386 case 'b':
387 m_func_names.push_back(option_arg);
388 m_func_name_type_mask |= eFunctionNameTypeBase;
389 break;
390
Zachary Turnerfe114832016-11-12 16:56:47 +0000391 case 'C':
392 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000393 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000394 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000398 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399
400 switch (language) {
401 case eLanguageTypeC89:
402 case eLanguageTypeC:
403 case eLanguageTypeC99:
404 case eLanguageTypeC11:
405 m_exception_language = eLanguageTypeC;
406 break;
407 case eLanguageTypeC_plus_plus:
408 case eLanguageTypeC_plus_plus_03:
409 case eLanguageTypeC_plus_plus_11:
410 case eLanguageTypeC_plus_plus_14:
411 m_exception_language = eLanguageTypeC_plus_plus;
412 break;
413 case eLanguageTypeObjC:
414 m_exception_language = eLanguageTypeObjC;
415 break;
416 case eLanguageTypeObjC_plus_plus:
417 error.SetErrorStringWithFormat(
418 "Set exception breakpoints separately for c++ and objective-c");
419 break;
420 case eLanguageTypeUnknown:
421 error.SetErrorStringWithFormat(
422 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000423 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 break;
425 default:
426 error.SetErrorStringWithFormat(
427 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000428 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 }
430 } break;
431
432 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000433 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 break;
435
436 case 'F':
437 m_func_names.push_back(option_arg);
438 m_func_name_type_mask |= eFunctionNameTypeFull;
439 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441 case 'h': {
442 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000443 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444 if (!success)
445 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000446 "Invalid boolean value for on-catch option: '%s'",
447 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 } break;
449
450 case 'H':
451 m_hardware = true;
452 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000453
454 case 'k': {
455 if (m_current_key.empty())
456 m_current_key.assign(option_arg);
457 else
458 error.SetErrorStringWithFormat("Key: %s missing value.",
459 m_current_key.c_str());
460
461 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 case 'K': {
463 bool success;
464 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000465 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 if (value)
467 m_skip_prologue = eLazyBoolYes;
468 else
469 m_skip_prologue = eLazyBoolNo;
470
471 if (!success)
472 error.SetErrorStringWithFormat(
473 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000474 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 } break;
476
Zachary Turnerfe114832016-11-12 16:56:47 +0000477 case 'l':
478 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000480 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482
483 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000484 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 if (m_language == eLanguageTypeUnknown)
486 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000487 "Unknown language type: '%s' for breakpoint",
488 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489 break;
490
491 case 'm': {
492 bool success;
493 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000494 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 if (value)
496 m_move_to_nearest_code = eLazyBoolYes;
497 else
498 m_move_to_nearest_code = eLazyBoolNo;
499
500 if (!success)
501 error.SetErrorStringWithFormat(
502 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000503 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504 break;
505 }
506
507 case 'M':
508 m_func_names.push_back(option_arg);
509 m_func_name_type_mask |= eFunctionNameTypeMethod;
510 break;
511
512 case 'n':
513 m_func_names.push_back(option_arg);
514 m_func_name_type_mask |= eFunctionNameTypeAuto;
515 break;
516
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000517 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000518 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000520 else
521 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000522 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000524 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525
526 case 'R': {
527 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000528 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
529 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 if (error.Success())
531 m_offset_addr = tmp_offset_addr;
532 } break;
533
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000535 m_exception_extra_args.AppendArgument("-O");
536 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537 break;
538
539 case 'p':
540 m_source_text_regexp.assign(option_arg);
541 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000542
543 case 'P':
544 m_python_class.assign(option_arg);
545 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 case 'r':
548 m_func_regexp.assign(option_arg);
549 break;
550
551 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000552 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000553 break;
554
555 case 'S':
556 m_func_names.push_back(option_arg);
557 m_func_name_type_mask |= eFunctionNameTypeSelector;
558 break;
559
Jim Ingham3815e702018-09-13 21:35:32 +0000560 case 'v': {
561 if (!m_current_key.empty()) {
562 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
563 m_current_key.clear();
564 }
565 else
566 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
567 option_arg.str().c_str());
568 } break;
569
Kate Stoneb9c1b512016-09-06 20:57:50 +0000570 case 'w': {
571 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000572 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573 if (!success)
574 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000575 "Invalid boolean value for on-throw option: '%s'",
576 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000577 } break;
578
Kate Stoneb9c1b512016-09-06 20:57:50 +0000579 case 'X':
580 m_source_regex_func_names.insert(option_arg);
581 break;
582
583 default:
584 error.SetErrorStringWithFormat("unrecognized option '%c'",
585 short_option);
586 break;
587 }
588
589 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000590 }
591
Kate Stoneb9c1b512016-09-06 20:57:50 +0000592 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000593 m_filenames.Clear();
594 m_line_num = 0;
595 m_column = 0;
596 m_func_names.clear();
597 m_func_name_type_mask = eFunctionNameTypeNone;
598 m_func_regexp.clear();
599 m_source_text_regexp.clear();
600 m_modules.Clear();
601 m_load_addr = LLDB_INVALID_ADDRESS;
602 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000603 m_catch_bp = false;
604 m_throw_bp = true;
605 m_hardware = false;
606 m_exception_language = eLanguageTypeUnknown;
607 m_language = lldb::eLanguageTypeUnknown;
608 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000609 m_breakpoint_names.clear();
610 m_all_files = false;
611 m_exception_extra_args.Clear();
612 m_move_to_nearest_code = eLazyBoolCalculate;
613 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000614 m_python_class.clear();
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000615 m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
Jim Ingham3815e702018-09-13 21:35:32 +0000616 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000617 }
618
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000619 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000620 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000621 }
Jim Ingham5a988412012-06-08 21:56:10 +0000622
Kate Stoneb9c1b512016-09-06 20:57:50 +0000623 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000624
Kate Stoneb9c1b512016-09-06 20:57:50 +0000625 std::string m_condition;
626 FileSpecList m_filenames;
627 uint32_t m_line_num;
628 uint32_t m_column;
629 std::vector<std::string> m_func_names;
630 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000631 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000632 std::string m_func_regexp;
633 std::string m_source_text_regexp;
634 FileSpecList m_modules;
635 lldb::addr_t m_load_addr;
636 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000637 bool m_catch_bp;
638 bool m_throw_bp;
639 bool m_hardware; // Request to use hardware breakpoints
640 lldb::LanguageType m_exception_language;
641 lldb::LanguageType m_language;
642 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000643 bool m_all_files;
644 Args m_exception_extra_args;
645 LazyBool m_move_to_nearest_code;
646 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000647 std::string m_python_class;
648 StructuredData::DictionarySP m_extra_args_sp;
649 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000650 };
Jim Ingham5a988412012-06-08 21:56:10 +0000651
652protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000653 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000654 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000655
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 if (target == nullptr) {
657 result.AppendError("Invalid target. Must set target before setting "
658 "breakpoints (see 'target create' command).");
659 result.SetStatus(eReturnStatusFailed);
660 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000661 }
662
Kate Stoneb9c1b512016-09-06 20:57:50 +0000663 // The following are the various types of breakpoints that could be set:
664 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
665 // 2). -a [-s -g] (setting breakpoint by address)
666 // 3). -n [-s -g] (setting breakpoint by function name)
667 // 4). -r [-s -g] (setting breakpoint by function name regular
668 // expression)
669 // 5). -p -f (setting a breakpoint by comparing a reg-exp
670 // to source text)
671 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
672 // given language.)
673
674 BreakpointSetType break_type = eSetTypeInvalid;
675
Jim Ingham3815e702018-09-13 21:35:32 +0000676 if (!m_options.m_python_class.empty())
677 break_type = eSetTypeScripted;
678 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000679 break_type = eSetTypeFileAndLine;
680 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
681 break_type = eSetTypeAddress;
682 else if (!m_options.m_func_names.empty())
683 break_type = eSetTypeFunctionName;
684 else if (!m_options.m_func_regexp.empty())
685 break_type = eSetTypeFunctionRegexp;
686 else if (!m_options.m_source_text_regexp.empty())
687 break_type = eSetTypeSourceRegexp;
688 else if (m_options.m_exception_language != eLanguageTypeUnknown)
689 break_type = eSetTypeException;
690
Jim Inghamb842f2e2017-09-14 20:22:49 +0000691 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000692 FileSpec module_spec;
693 const bool internal = false;
694
695 // If the user didn't specify skip-prologue, having an offset should turn
696 // that off.
697 if (m_options.m_offset_addr != 0 &&
698 m_options.m_skip_prologue == eLazyBoolCalculate)
699 m_options.m_skip_prologue = eLazyBoolNo;
700
701 switch (break_type) {
702 case eSetTypeFileAndLine: // Breakpoint by source position
703 {
704 FileSpec file;
705 const size_t num_files = m_options.m_filenames.GetSize();
706 if (num_files == 0) {
707 if (!GetDefaultFile(target, file, result)) {
708 result.AppendError("No file supplied and no default file available.");
709 result.SetStatus(eReturnStatusFailed);
710 return false;
711 }
712 } else if (num_files > 1) {
713 result.AppendError("Only one file at a time is allowed for file and "
714 "line breakpoints.");
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 } else
718 file = m_options.m_filenames.GetFileSpecAtIndex(0);
719
720 // Only check for inline functions if
721 LazyBool check_inlines = eLazyBoolCalculate;
722
Jim Inghamb842f2e2017-09-14 20:22:49 +0000723 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
724 file,
Adrian Prantl431b1582018-08-30 15:11:00 +0000725 m_options.m_line_num,
726 m_options.m_column,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000727 m_options.m_offset_addr,
728 check_inlines,
729 m_options.m_skip_prologue,
730 internal,
731 m_options.m_hardware,
732 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000733 } break;
734
735 case eSetTypeAddress: // Breakpoint by address
736 {
737 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000738 // with the library, and use that. That way the address breakpoint
739 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000740 size_t num_modules_specified = m_options.m_modules.GetSize();
741 if (num_modules_specified == 1) {
742 const FileSpec *file_spec =
743 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000744 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
745 internal, file_spec,
746 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000747 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000748 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
749 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000750 } else {
751 result.AppendError("Only one shared library can be specified for "
752 "address breakpoints.");
753 result.SetStatus(eReturnStatusFailed);
754 return false;
755 }
756 break;
757 }
758 case eSetTypeFunctionName: // Breakpoint by function name
759 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000760 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000761
762 if (name_type_mask == 0)
763 name_type_mask = eFunctionNameTypeAuto;
764
Jim Inghamb842f2e2017-09-14 20:22:49 +0000765 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
766 &(m_options.m_filenames),
767 m_options.m_func_names,
768 name_type_mask,
769 m_options.m_language,
770 m_options.m_offset_addr,
771 m_options.m_skip_prologue,
772 internal,
773 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000774 } break;
775
776 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
777 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000778 {
Zachary Turner95eae422016-09-21 16:01:28 +0000779 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000780 if (!regexp.IsValid()) {
781 char err_str[1024];
782 regexp.GetErrorAsCString(err_str, sizeof(err_str));
783 result.AppendErrorWithFormat(
784 "Function name regular expression could not be compiled: \"%s\"",
785 err_str);
786 result.SetStatus(eReturnStatusFailed);
787 return false;
788 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000789
Jim Inghamb842f2e2017-09-14 20:22:49 +0000790 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
791 &(m_options.m_filenames),
792 regexp,
793 m_options.m_language,
794 m_options.m_skip_prologue,
795 internal,
796 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000797 }
798 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000799 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
800 {
801 const size_t num_files = m_options.m_filenames.GetSize();
802
803 if (num_files == 0 && !m_options.m_all_files) {
804 FileSpec file;
805 if (!GetDefaultFile(target, file, result)) {
806 result.AppendError(
807 "No files provided and could not find default file.");
808 result.SetStatus(eReturnStatusFailed);
809 return false;
810 } else {
811 m_options.m_filenames.Append(file);
812 }
813 }
814
Zachary Turner95eae422016-09-21 16:01:28 +0000815 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816 if (!regexp.IsValid()) {
817 char err_str[1024];
818 regexp.GetErrorAsCString(err_str, sizeof(err_str));
819 result.AppendErrorWithFormat(
820 "Source text regular expression could not be compiled: \"%s\"",
821 err_str);
822 result.SetStatus(eReturnStatusFailed);
823 return false;
824 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000825 bp_sp =
826 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
827 &(m_options.m_filenames),
828 m_options
829 .m_source_regex_func_names,
830 regexp,
831 internal,
832 m_options.m_hardware,
833 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000834 } break;
835 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000836 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000837 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
838 m_options.m_catch_bp,
839 m_options.m_throw_bp,
840 internal,
841 &m_options
842 .m_exception_extra_args,
843 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000844 if (precond_error.Fail()) {
845 result.AppendErrorWithFormat(
846 "Error setting extra exception arguments: %s",
847 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000848 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000849 result.SetStatus(eReturnStatusFailed);
850 return false;
851 }
852 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000853 case eSetTypeScripted: {
854
855 Status error;
856 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
857 &(m_options.m_modules),
858 &(m_options.m_filenames),
859 false,
860 m_options.m_hardware,
861 m_options.m_extra_args_sp,
862 &error);
863 if (error.Fail()) {
864 result.AppendErrorWithFormat(
865 "Error setting extra exception arguments: %s",
866 error.AsCString());
867 target->RemoveBreakpointByID(bp_sp->GetID());
868 result.SetStatus(eReturnStatusFailed);
869 return false;
870 }
871 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000872 default:
873 break;
874 }
875
876 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000877 if (bp_sp) {
878 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879
880 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000881 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000882 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000883 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000884 if (name_error.Fail()) {
885 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
886 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000887 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000888 result.SetStatus(eReturnStatusFailed);
889 return false;
890 }
891 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000892 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000893 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000894
895 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000896 Stream &output_stream = result.GetOutputStream();
897 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000898 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000899 show_locations);
Jonas Devlieghere57179862019-04-27 06:19:42 +0000900 if (target == GetDebugger().GetDummyTarget())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000901 output_stream.Printf("Breakpoint set in dummy target, will get copied "
902 "into future targets.\n");
903 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000904 // Don't print out this warning for exception breakpoints. They can
905 // get set before the target is set, but we won't know how to actually
906 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000907 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000908 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
909 "actual locations.\n");
910 }
911 }
912 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000913 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000914 result.AppendError("Breakpoint creation failed: No breakpoint created.");
915 result.SetStatus(eReturnStatusFailed);
916 }
917
918 return result.Succeeded();
919 }
920
Jim Ingham5a988412012-06-08 21:56:10 +0000921private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922 bool GetDefaultFile(Target *target, FileSpec &file,
923 CommandReturnObject &result) {
924 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000925 // First use the Source Manager's default file. Then use the current stack
926 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000927 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
928 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
929 if (cur_frame == nullptr) {
930 result.AppendError(
931 "No selected frame to use to find the default file.");
932 result.SetStatus(eReturnStatusFailed);
933 return false;
934 } else if (!cur_frame->HasDebugInformation()) {
935 result.AppendError("Cannot use the selected frame to find the default "
936 "file, it has no debug info.");
937 result.SetStatus(eReturnStatusFailed);
938 return false;
939 } else {
940 const SymbolContext &sc =
941 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
942 if (sc.line_entry.file) {
943 file = sc.line_entry.file;
944 } else {
945 result.AppendError("Can't find the file for the selected frame to "
946 "use as the default file.");
947 result.SetStatus(eReturnStatusFailed);
948 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000949 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000950 }
Jim Ingham5a988412012-06-08 21:56:10 +0000951 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000952 return true;
953 }
954
Jim Inghamb842f2e2017-09-14 20:22:49 +0000955 BreakpointOptionGroup m_bp_opts;
956 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000957 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000958 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000959};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000960
Jim Ingham5a988412012-06-08 21:56:10 +0000961// CommandObjectBreakpointModify
Jim Ingham5a988412012-06-08 21:56:10 +0000962#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000963
Kate Stoneb9c1b512016-09-06 20:57:50 +0000964class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000965public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000966 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
967 : CommandObjectParsed(interpreter, "breakpoint modify",
968 "Modify the options on a breakpoint or set of "
969 "breakpoints in the executable. "
970 "If no breakpoint is specified, acts on the last "
971 "created breakpoint. "
972 "With the exception of -e, -d and -i, passing an "
973 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000974 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000975 m_options() {
976 CommandArgumentEntry arg;
977 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
978 eArgTypeBreakpointIDRange);
979 // Add the entry for the first argument for this command to the object's
980 // arguments vector.
981 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000982
983 m_options.Append(&m_bp_opts,
984 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
985 LLDB_OPT_SET_ALL);
986 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
987 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000988 }
989
990 ~CommandObjectBreakpointModify() override = default;
991
992 Options *GetOptions() override { return &m_options; }
993
Jim Ingham5a988412012-06-08 21:56:10 +0000994protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000995 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000996 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997 if (target == nullptr) {
998 result.AppendError("Invalid target. No existing target or breakpoints.");
999 result.SetStatus(eReturnStatusFailed);
1000 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001001 }
1002
Kate Stoneb9c1b512016-09-06 20:57:50 +00001003 std::unique_lock<std::recursive_mutex> lock;
1004 target->GetBreakpointList().GetListMutex(lock);
1005
1006 BreakpointIDList valid_bp_ids;
1007
1008 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001009 command, target, result, &valid_bp_ids,
1010 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011
1012 if (result.Succeeded()) {
1013 const size_t count = valid_bp_ids.GetSize();
1014 for (size_t i = 0; i < count; ++i) {
1015 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1016
1017 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1018 Breakpoint *bp =
1019 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1020 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1021 BreakpointLocation *location =
1022 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001023 if (location)
1024 location->GetLocationOptions()
1025 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001026 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001027 bp->GetOptions()
1028 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001029 }
1030 }
1031 }
1032 }
1033
1034 return result.Succeeded();
1035 }
1036
Jim Ingham5a988412012-06-08 21:56:10 +00001037private:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001038 BreakpointOptionGroup m_bp_opts;
1039 BreakpointDummyOptionGroup m_dummy_opts;
1040 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001041};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001042
Jim Ingham5a988412012-06-08 21:56:10 +00001043// CommandObjectBreakpointEnable
Jim Ingham5a988412012-06-08 21:56:10 +00001044#pragma mark Enable
1045
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001047public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001048 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1049 : CommandObjectParsed(interpreter, "enable",
1050 "Enable the specified disabled breakpoint(s). If "
1051 "no breakpoints are specified, enable all of them.",
1052 nullptr) {
1053 CommandArgumentEntry arg;
1054 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1055 eArgTypeBreakpointIDRange);
1056 // Add the entry for the first argument for this command to the object's
1057 // arguments vector.
1058 m_arguments.push_back(arg);
1059 }
Jim Ingham5a988412012-06-08 21:56:10 +00001060
Kate Stoneb9c1b512016-09-06 20:57:50 +00001061 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001062
1063protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001064 bool DoExecute(Args &command, CommandReturnObject &result) override {
1065 Target *target = GetSelectedOrDummyTarget();
1066 if (target == nullptr) {
1067 result.AppendError("Invalid target. No existing target or breakpoints.");
1068 result.SetStatus(eReturnStatusFailed);
1069 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001070 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001071
1072 std::unique_lock<std::recursive_mutex> lock;
1073 target->GetBreakpointList().GetListMutex(lock);
1074
1075 const BreakpointList &breakpoints = target->GetBreakpointList();
1076
1077 size_t num_breakpoints = breakpoints.GetSize();
1078
1079 if (num_breakpoints == 0) {
1080 result.AppendError("No breakpoints exist to be enabled.");
1081 result.SetStatus(eReturnStatusFailed);
1082 return false;
1083 }
1084
Zachary Turner11eb9c62016-10-05 20:03:37 +00001085 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001086 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001087 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1089 " breakpoints)\n",
1090 (uint64_t)num_breakpoints);
1091 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1092 } else {
1093 // Particular breakpoint selected; enable that breakpoint.
1094 BreakpointIDList valid_bp_ids;
1095 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001096 command, target, result, &valid_bp_ids,
1097 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001098
1099 if (result.Succeeded()) {
1100 int enable_count = 0;
1101 int loc_count = 0;
1102 const size_t count = valid_bp_ids.GetSize();
1103 for (size_t i = 0; i < count; ++i) {
1104 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1105
1106 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1107 Breakpoint *breakpoint =
1108 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1109 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1110 BreakpointLocation *location =
1111 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1112 if (location) {
1113 location->SetEnabled(true);
1114 ++loc_count;
1115 }
1116 } else {
1117 breakpoint->SetEnabled(true);
1118 ++enable_count;
1119 }
1120 }
1121 }
1122 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1123 enable_count + loc_count);
1124 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1125 }
1126 }
1127
1128 return result.Succeeded();
1129 }
Jim Ingham5a988412012-06-08 21:56:10 +00001130};
1131
Jim Ingham5a988412012-06-08 21:56:10 +00001132// CommandObjectBreakpointDisable
Jim Ingham5a988412012-06-08 21:56:10 +00001133#pragma mark Disable
1134
Kate Stoneb9c1b512016-09-06 20:57:50 +00001135class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001136public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001137 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1138 : CommandObjectParsed(
1139 interpreter, "breakpoint disable",
1140 "Disable the specified breakpoint(s) without deleting "
1141 "them. If none are specified, disable all "
1142 "breakpoints.",
1143 nullptr) {
1144 SetHelpLong(
1145 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001146If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001147 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001148
Kate Stone7428a182016-07-14 22:03:10 +00001149)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001150 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001151regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001152 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001153
1154 (lldb) break disable 1
1155 (lldb) break enable 1.1
1156
1157execution will NOT stop at location 1.1. To achieve that, type:
1158
1159 (lldb) break disable 1.*
1160 (lldb) break enable 1.1
1161
Kate Stone7428a182016-07-14 22:03:10 +00001162)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001163 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001164the second re-enables the first location.");
1165
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166 CommandArgumentEntry arg;
1167 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1168 eArgTypeBreakpointIDRange);
1169 // Add the entry for the first argument for this command to the object's
1170 // arguments vector.
1171 m_arguments.push_back(arg);
1172 }
Jim Ingham5a988412012-06-08 21:56:10 +00001173
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001175
1176protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001177 bool DoExecute(Args &command, CommandReturnObject &result) override {
1178 Target *target = GetSelectedOrDummyTarget();
1179 if (target == nullptr) {
1180 result.AppendError("Invalid target. No existing target or breakpoints.");
1181 result.SetStatus(eReturnStatusFailed);
1182 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001183 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184
1185 std::unique_lock<std::recursive_mutex> lock;
1186 target->GetBreakpointList().GetListMutex(lock);
1187
1188 const BreakpointList &breakpoints = target->GetBreakpointList();
1189 size_t num_breakpoints = breakpoints.GetSize();
1190
1191 if (num_breakpoints == 0) {
1192 result.AppendError("No breakpoints exist to be disabled.");
1193 result.SetStatus(eReturnStatusFailed);
1194 return false;
1195 }
1196
Zachary Turner11eb9c62016-10-05 20:03:37 +00001197 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001199 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001200 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1201 " breakpoints)\n",
1202 (uint64_t)num_breakpoints);
1203 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1204 } else {
1205 // Particular breakpoint selected; disable that breakpoint.
1206 BreakpointIDList valid_bp_ids;
1207
1208 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001209 command, target, result, &valid_bp_ids,
1210 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001211
1212 if (result.Succeeded()) {
1213 int disable_count = 0;
1214 int loc_count = 0;
1215 const size_t count = valid_bp_ids.GetSize();
1216 for (size_t i = 0; i < count; ++i) {
1217 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1218
1219 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1220 Breakpoint *breakpoint =
1221 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1222 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1223 BreakpointLocation *location =
1224 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1225 if (location) {
1226 location->SetEnabled(false);
1227 ++loc_count;
1228 }
1229 } else {
1230 breakpoint->SetEnabled(false);
1231 ++disable_count;
1232 }
1233 }
1234 }
1235 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1236 disable_count + loc_count);
1237 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1238 }
1239 }
1240
1241 return result.Succeeded();
1242 }
Jim Ingham5a988412012-06-08 21:56:10 +00001243};
1244
Jim Ingham5a988412012-06-08 21:56:10 +00001245// CommandObjectBreakpointList
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001246
1247#pragma mark List::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001248static constexpr OptionDefinition g_breakpoint_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001249 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001250 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1251 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001252 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1253 // But I need to see it for now, and don't want to wait.
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001254 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1255 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1256 { 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." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001257 // clang-format on
1258};
1259
Jim Ingham5a988412012-06-08 21:56:10 +00001260#pragma mark List
1261
Kate Stoneb9c1b512016-09-06 20:57:50 +00001262class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001263public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001264 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1265 : CommandObjectParsed(
1266 interpreter, "breakpoint list",
1267 "List some or all breakpoints at configurable levels of detail.",
1268 nullptr),
1269 m_options() {
1270 CommandArgumentEntry arg;
1271 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001272
Kate Stoneb9c1b512016-09-06 20:57:50 +00001273 // Define the first (and only) variant of this arg.
1274 bp_id_arg.arg_type = eArgTypeBreakpointID;
1275 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001276
Kate Stoneb9c1b512016-09-06 20:57:50 +00001277 // There is only one variant this argument could be; put it into the
1278 // argument entry.
1279 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001280
Kate Stoneb9c1b512016-09-06 20:57:50 +00001281 // Push the data for the first argument into the m_arguments vector.
1282 m_arguments.push_back(arg);
1283 }
1284
1285 ~CommandObjectBreakpointList() override = default;
1286
1287 Options *GetOptions() override { return &m_options; }
1288
1289 class CommandOptions : public Options {
1290 public:
1291 CommandOptions()
1292 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001293 }
1294
Kate Stoneb9c1b512016-09-06 20:57:50 +00001295 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001296
Zachary Turner97206d52017-05-12 04:51:55 +00001297 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1298 ExecutionContext *execution_context) override {
1299 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001300 const int short_option = m_getopt_table[option_idx].val;
1301
1302 switch (short_option) {
1303 case 'b':
1304 m_level = lldb::eDescriptionLevelBrief;
1305 break;
1306 case 'D':
1307 m_use_dummy = true;
1308 break;
1309 case 'f':
1310 m_level = lldb::eDescriptionLevelFull;
1311 break;
1312 case 'v':
1313 m_level = lldb::eDescriptionLevelVerbose;
1314 break;
1315 case 'i':
1316 m_internal = true;
1317 break;
1318 default:
1319 error.SetErrorStringWithFormat("unrecognized option '%c'",
1320 short_option);
1321 break;
1322 }
1323
1324 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001325 }
Jim Ingham5a988412012-06-08 21:56:10 +00001326
Kate Stoneb9c1b512016-09-06 20:57:50 +00001327 void OptionParsingStarting(ExecutionContext *execution_context) override {
1328 m_level = lldb::eDescriptionLevelFull;
1329 m_internal = false;
1330 m_use_dummy = false;
1331 }
Jim Ingham5a988412012-06-08 21:56:10 +00001332
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001333 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001334 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001335 }
Jim Ingham5a988412012-06-08 21:56:10 +00001336
Kate Stoneb9c1b512016-09-06 20:57:50 +00001337 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001338
Kate Stoneb9c1b512016-09-06 20:57:50 +00001339 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001340
Kate Stoneb9c1b512016-09-06 20:57:50 +00001341 bool m_internal;
1342 bool m_use_dummy;
1343 };
Jim Ingham5a988412012-06-08 21:56:10 +00001344
1345protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001346 bool DoExecute(Args &command, CommandReturnObject &result) override {
1347 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001348
Kate Stoneb9c1b512016-09-06 20:57:50 +00001349 if (target == nullptr) {
1350 result.AppendError("Invalid target. No current target or breakpoints.");
1351 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1352 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001353 }
1354
Kate Stoneb9c1b512016-09-06 20:57:50 +00001355 const BreakpointList &breakpoints =
1356 target->GetBreakpointList(m_options.m_internal);
1357 std::unique_lock<std::recursive_mutex> lock;
1358 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1359
1360 size_t num_breakpoints = breakpoints.GetSize();
1361
1362 if (num_breakpoints == 0) {
1363 result.AppendMessage("No breakpoints currently set.");
1364 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1365 return true;
1366 }
1367
1368 Stream &output_stream = result.GetOutputStream();
1369
Zachary Turner11eb9c62016-10-05 20:03:37 +00001370 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001371 // No breakpoint selected; show info about all currently set breakpoints.
1372 result.AppendMessage("Current breakpoints:");
1373 for (size_t i = 0; i < num_breakpoints; ++i) {
1374 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001375 if (breakpoint->AllowList())
1376 AddBreakpointDescription(&output_stream, breakpoint,
1377 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001378 }
1379 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1380 } else {
1381 // Particular breakpoints selected; show info about that breakpoint.
1382 BreakpointIDList valid_bp_ids;
1383 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001384 command, target, result, &valid_bp_ids,
1385 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001386
1387 if (result.Succeeded()) {
1388 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1389 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1390 Breakpoint *breakpoint =
1391 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1392 AddBreakpointDescription(&output_stream, breakpoint,
1393 m_options.m_level);
1394 }
1395 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1396 } else {
1397 result.AppendError("Invalid breakpoint ID.");
1398 result.SetStatus(eReturnStatusFailed);
1399 }
1400 }
1401
1402 return result.Succeeded();
1403 }
1404
Jim Ingham5a988412012-06-08 21:56:10 +00001405private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001406 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001407};
1408
Jim Ingham5a988412012-06-08 21:56:10 +00001409// CommandObjectBreakpointClear
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001410#pragma mark Clear::CommandOptions
1411
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001412static constexpr OptionDefinition g_breakpoint_clear_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001413 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001414 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1415 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001416 // clang-format on
1417};
1418
Jim Ingham5a988412012-06-08 21:56:10 +00001419#pragma mark Clear
1420
Kate Stoneb9c1b512016-09-06 20:57:50 +00001421class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001422public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +00001423 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
Jim Ingham5a988412012-06-08 21:56:10 +00001424
Kate Stoneb9c1b512016-09-06 20:57:50 +00001425 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1426 : CommandObjectParsed(interpreter, "breakpoint clear",
1427 "Delete or disable breakpoints matching the "
1428 "specified source file and line.",
1429 "breakpoint clear <cmd-options>"),
1430 m_options() {}
1431
1432 ~CommandObjectBreakpointClear() override = default;
1433
1434 Options *GetOptions() override { return &m_options; }
1435
1436 class CommandOptions : public Options {
1437 public:
1438 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1439
1440 ~CommandOptions() override = default;
1441
Zachary Turner97206d52017-05-12 04:51:55 +00001442 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1443 ExecutionContext *execution_context) override {
1444 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001445 const int short_option = m_getopt_table[option_idx].val;
1446
1447 switch (short_option) {
1448 case 'f':
1449 m_filename.assign(option_arg);
1450 break;
1451
1452 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001453 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001454 break;
1455
1456 default:
1457 error.SetErrorStringWithFormat("unrecognized option '%c'",
1458 short_option);
1459 break;
1460 }
1461
1462 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001463 }
1464
Kate Stoneb9c1b512016-09-06 20:57:50 +00001465 void OptionParsingStarting(ExecutionContext *execution_context) override {
1466 m_filename.clear();
1467 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001468 }
1469
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001470 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001471 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001472 }
Jim Ingham5a988412012-06-08 21:56:10 +00001473
Kate Stoneb9c1b512016-09-06 20:57:50 +00001474 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001475
Kate Stoneb9c1b512016-09-06 20:57:50 +00001476 std::string m_filename;
1477 uint32_t m_line_num;
1478 };
Jim Ingham5a988412012-06-08 21:56:10 +00001479
1480protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001481 bool DoExecute(Args &command, CommandReturnObject &result) override {
1482 Target *target = GetSelectedOrDummyTarget();
1483 if (target == nullptr) {
1484 result.AppendError("Invalid target. No existing target or breakpoints.");
1485 result.SetStatus(eReturnStatusFailed);
1486 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001487 }
1488
Adrian Prantl05097242018-04-30 16:49:04 +00001489 // The following are the various types of breakpoints that could be
1490 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001491 // 1). -f -l (clearing breakpoint by source location)
1492
1493 BreakpointClearType break_type = eClearTypeInvalid;
1494
1495 if (m_options.m_line_num != 0)
1496 break_type = eClearTypeFileAndLine;
1497
1498 std::unique_lock<std::recursive_mutex> lock;
1499 target->GetBreakpointList().GetListMutex(lock);
1500
1501 BreakpointList &breakpoints = target->GetBreakpointList();
1502 size_t num_breakpoints = breakpoints.GetSize();
1503
1504 // Early return if there's no breakpoint at all.
1505 if (num_breakpoints == 0) {
1506 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1507 result.SetStatus(eReturnStatusFailed);
1508 return result.Succeeded();
1509 }
1510
1511 // Find matching breakpoints and delete them.
1512
1513 // First create a copy of all the IDs.
1514 std::vector<break_id_t> BreakIDs;
1515 for (size_t i = 0; i < num_breakpoints; ++i)
1516 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1517
1518 int num_cleared = 0;
1519 StreamString ss;
1520 switch (break_type) {
1521 case eClearTypeFileAndLine: // Breakpoint by source position
1522 {
1523 const ConstString filename(m_options.m_filename.c_str());
1524 BreakpointLocationCollection loc_coll;
1525
1526 for (size_t i = 0; i < num_breakpoints; ++i) {
1527 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1528
1529 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1530 // If the collection size is 0, it's a full match and we can just
1531 // remove the breakpoint.
1532 if (loc_coll.GetSize() == 0) {
1533 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1534 ss.EOL();
1535 target->RemoveBreakpointByID(bp->GetID());
1536 ++num_cleared;
1537 }
1538 }
1539 }
1540 } break;
1541
1542 default:
1543 break;
1544 }
1545
1546 if (num_cleared > 0) {
1547 Stream &output_stream = result.GetOutputStream();
1548 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001549 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001550 output_stream.EOL();
1551 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1552 } else {
1553 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1554 result.SetStatus(eReturnStatusFailed);
1555 }
1556
1557 return result.Succeeded();
1558 }
1559
Jim Ingham5a988412012-06-08 21:56:10 +00001560private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001561 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001562};
1563
Jim Ingham5a988412012-06-08 21:56:10 +00001564// CommandObjectBreakpointDelete
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001565static constexpr OptionDefinition g_breakpoint_delete_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001566 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001567 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1568 { 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." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001569 // clang-format on
1570};
1571
Jim Ingham5a988412012-06-08 21:56:10 +00001572#pragma mark Delete
1573
Kate Stoneb9c1b512016-09-06 20:57:50 +00001574class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001575public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001576 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1577 : CommandObjectParsed(interpreter, "breakpoint delete",
1578 "Delete the specified breakpoint(s). If no "
1579 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001580 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001581 m_options() {
1582 CommandArgumentEntry arg;
1583 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1584 eArgTypeBreakpointIDRange);
1585 // Add the entry for the first argument for this command to the object's
1586 // arguments vector.
1587 m_arguments.push_back(arg);
1588 }
1589
1590 ~CommandObjectBreakpointDelete() override = default;
1591
1592 Options *GetOptions() override { return &m_options; }
1593
1594 class CommandOptions : public Options {
1595 public:
1596 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1597
1598 ~CommandOptions() override = default;
1599
Zachary Turner97206d52017-05-12 04:51:55 +00001600 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1601 ExecutionContext *execution_context) override {
1602 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001603 const int short_option = m_getopt_table[option_idx].val;
1604
1605 switch (short_option) {
1606 case 'f':
1607 m_force = true;
1608 break;
1609
1610 case 'D':
1611 m_use_dummy = true;
1612 break;
1613
1614 default:
1615 error.SetErrorStringWithFormat("unrecognized option '%c'",
1616 short_option);
1617 break;
1618 }
1619
1620 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001621 }
1622
Kate Stoneb9c1b512016-09-06 20:57:50 +00001623 void OptionParsingStarting(ExecutionContext *execution_context) override {
1624 m_use_dummy = false;
1625 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001626 }
1627
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001628 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001629 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001630 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001631
Kate Stoneb9c1b512016-09-06 20:57:50 +00001632 // Instance variables to hold the values for command options.
1633 bool m_use_dummy;
1634 bool m_force;
1635 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001636
Jim Ingham5a988412012-06-08 21:56:10 +00001637protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001638 bool DoExecute(Args &command, CommandReturnObject &result) override {
1639 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001640
Kate Stoneb9c1b512016-09-06 20:57:50 +00001641 if (target == nullptr) {
1642 result.AppendError("Invalid target. No existing target or breakpoints.");
1643 result.SetStatus(eReturnStatusFailed);
1644 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001645 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001646
Kate Stoneb9c1b512016-09-06 20:57:50 +00001647 std::unique_lock<std::recursive_mutex> lock;
1648 target->GetBreakpointList().GetListMutex(lock);
1649
1650 const BreakpointList &breakpoints = target->GetBreakpointList();
1651
1652 size_t num_breakpoints = breakpoints.GetSize();
1653
1654 if (num_breakpoints == 0) {
1655 result.AppendError("No breakpoints exist to be deleted.");
1656 result.SetStatus(eReturnStatusFailed);
1657 return false;
1658 }
1659
Zachary Turner11eb9c62016-10-05 20:03:37 +00001660 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001661 if (!m_options.m_force &&
1662 !m_interpreter.Confirm(
1663 "About to delete all breakpoints, do you want to do that?",
1664 true)) {
1665 result.AppendMessage("Operation cancelled...");
1666 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001667 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001668 result.AppendMessageWithFormat(
1669 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1670 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1671 }
1672 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1673 } else {
1674 // Particular breakpoint selected; disable that breakpoint.
1675 BreakpointIDList valid_bp_ids;
1676 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001677 command, target, result, &valid_bp_ids,
1678 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001679
1680 if (result.Succeeded()) {
1681 int delete_count = 0;
1682 int disable_count = 0;
1683 const size_t count = valid_bp_ids.GetSize();
1684 for (size_t i = 0; i < count; ++i) {
1685 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1686
1687 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1688 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1689 Breakpoint *breakpoint =
1690 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1691 BreakpointLocation *location =
1692 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1693 // It makes no sense to try to delete individual locations, so we
1694 // disable them instead.
1695 if (location) {
1696 location->SetEnabled(false);
1697 ++disable_count;
1698 }
1699 } else {
1700 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1701 ++delete_count;
1702 }
1703 }
1704 }
1705 result.AppendMessageWithFormat(
1706 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1707 delete_count, disable_count);
1708 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1709 }
1710 }
1711 return result.Succeeded();
1712 }
1713
Jim Ingham33df7cd2014-12-06 01:28:03 +00001714private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001715 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001716};
1717
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001718// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001719
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001720static constexpr OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001721 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001722 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1723 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1724 {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."},
1725 {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
Kate Stoneb9c1b512016-09-06 20:57:50 +00001726 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001727};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001728class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001729public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001730 BreakpointNameOptionGroup()
1731 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1732 }
1733
1734 ~BreakpointNameOptionGroup() override = default;
1735
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001736 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001737 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001738 }
1739
Zachary Turner97206d52017-05-12 04:51:55 +00001740 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1741 ExecutionContext *execution_context) override {
1742 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001743 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1744
1745 switch (short_option) {
1746 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001747 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001748 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001749 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001750 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001751 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001752 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001753 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001754 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001755 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001756 break;
1757 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001758 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001759 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001760 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001761 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001762 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001763 case 'H':
1764 m_help_string.SetValueFromString(option_arg);
1765 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001766
1767 default:
1768 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1769 short_option);
1770 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001771 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001772 return error;
1773 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001774
Kate Stoneb9c1b512016-09-06 20:57:50 +00001775 void OptionParsingStarting(ExecutionContext *execution_context) override {
1776 m_name.Clear();
1777 m_breakpoint.Clear();
1778 m_use_dummy.Clear();
1779 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001780 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001781 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001782
Kate Stoneb9c1b512016-09-06 20:57:50 +00001783 OptionValueString m_name;
1784 OptionValueUInt64 m_breakpoint;
1785 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001786 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001787};
1788
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001789static constexpr OptionDefinition g_breakpoint_access_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001790 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001791 {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."},
1792 {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."},
1793 {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."},
Jim Inghamb842f2e2017-09-14 20:22:49 +00001794 // clang-format on
1795};
1796
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001797class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001798public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001799 BreakpointAccessOptionGroup() : OptionGroup() {}
1800
Jim Inghamb842f2e2017-09-14 20:22:49 +00001801 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001802
Jim Inghamb842f2e2017-09-14 20:22:49 +00001803 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1804 return llvm::makeArrayRef(g_breakpoint_access_options);
1805 }
1806 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1807 ExecutionContext *execution_context) override {
1808 Status error;
1809 const int short_option
1810 = g_breakpoint_access_options[option_idx].short_option;
1811
1812 switch (short_option) {
1813 case 'L': {
1814 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001815 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001816 if (success) {
1817 m_permissions.SetAllowList(value);
1818 } else
1819 error.SetErrorStringWithFormat(
1820 "invalid boolean value '%s' passed for -L option",
1821 option_arg.str().c_str());
1822 } break;
1823 case 'A': {
1824 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001825 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001826 if (success) {
1827 m_permissions.SetAllowDisable(value);
1828 } else
1829 error.SetErrorStringWithFormat(
1830 "invalid boolean value '%s' passed for -L option",
1831 option_arg.str().c_str());
1832 } break;
1833 case 'D': {
1834 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001835 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001836 if (success) {
1837 m_permissions.SetAllowDelete(value);
1838 } else
1839 error.SetErrorStringWithFormat(
1840 "invalid boolean value '%s' passed for -L option",
1841 option_arg.str().c_str());
1842 } break;
1843
1844 }
1845
1846 return error;
1847 }
1848
1849 void OptionParsingStarting(ExecutionContext *execution_context) override {
1850 }
1851
1852 const BreakpointName::Permissions &GetPermissions() const
1853 {
1854 return m_permissions;
1855 }
1856 BreakpointName::Permissions m_permissions;
1857};
1858
1859class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1860public:
1861 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1862 : CommandObjectParsed(
1863 interpreter, "configure", "Configure the options for the breakpoint"
1864 " name provided. "
1865 "If you provide a breakpoint id, the options will be copied from "
1866 "the breakpoint, otherwise only the options specified will be set "
1867 "on the name.",
1868 "breakpoint name configure <command-options> "
1869 "<breakpoint-name-list>"),
1870 m_bp_opts(), m_option_group() {
1871 // Create the first variant for the first (and only) argument for this
1872 // command.
1873 CommandArgumentEntry arg1;
1874 CommandArgumentData id_arg;
1875 id_arg.arg_type = eArgTypeBreakpointName;
1876 id_arg.arg_repetition = eArgRepeatOptional;
1877 arg1.push_back(id_arg);
1878 m_arguments.push_back(arg1);
1879
1880 m_option_group.Append(&m_bp_opts,
1881 LLDB_OPT_SET_ALL,
1882 LLDB_OPT_SET_1);
1883 m_option_group.Append(&m_access_options,
1884 LLDB_OPT_SET_ALL,
1885 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001886 m_option_group.Append(&m_bp_id,
1887 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1888 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001889 m_option_group.Finalize();
1890 }
1891
1892 ~CommandObjectBreakpointNameConfigure() override = default;
1893
1894 Options *GetOptions() override { return &m_option_group; }
1895
1896protected:
1897 bool DoExecute(Args &command, CommandReturnObject &result) override {
1898
1899 const size_t argc = command.GetArgumentCount();
1900 if (argc == 0) {
1901 result.AppendError("No names provided.");
1902 result.SetStatus(eReturnStatusFailed);
1903 return false;
1904 }
1905
1906 Target *target =
1907 GetSelectedOrDummyTarget(false);
1908
1909 if (target == nullptr) {
1910 result.AppendError("Invalid target. No existing target or breakpoints.");
1911 result.SetStatus(eReturnStatusFailed);
1912 return false;
1913 }
1914
1915 std::unique_lock<std::recursive_mutex> lock;
1916 target->GetBreakpointList().GetListMutex(lock);
1917
1918 // Make a pass through first to see that all the names are legal.
1919 for (auto &entry : command.entries()) {
1920 Status error;
1921 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1922 {
1923 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1924 entry.c_str(), error.AsCString());
1925 result.SetStatus(eReturnStatusFailed);
1926 return false;
1927 }
1928 }
Adrian Prantl05097242018-04-30 16:49:04 +00001929 // Now configure them, we already pre-checked the names so we don't need to
1930 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001931 BreakpointSP bp_sp;
1932 if (m_bp_id.m_breakpoint.OptionWasSet())
1933 {
1934 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1935 bp_sp = target->GetBreakpointByID(bp_id);
1936 if (!bp_sp)
1937 {
1938 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1939 bp_id);
1940 result.SetStatus(eReturnStatusFailed);
1941 return false;
1942 }
1943 }
1944
1945 Status error;
1946 for (auto &entry : command.entries()) {
1947 ConstString name(entry.c_str());
1948 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1949 if (!bp_name)
1950 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001951 if (m_bp_id.m_help_string.OptionWasSet())
1952 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1953
Jim Inghamb842f2e2017-09-14 20:22:49 +00001954 if (bp_sp)
1955 target->ConfigureBreakpointName(*bp_name,
1956 *bp_sp->GetOptions(),
1957 m_access_options.GetPermissions());
1958 else
1959 target->ConfigureBreakpointName(*bp_name,
1960 m_bp_opts.GetBreakpointOptions(),
1961 m_access_options.GetPermissions());
1962 }
1963 return true;
1964 }
1965
1966private:
1967 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1968 BreakpointOptionGroup m_bp_opts;
1969 BreakpointAccessOptionGroup m_access_options;
1970 OptionGroupOptions m_option_group;
1971};
1972
Kate Stoneb9c1b512016-09-06 20:57:50 +00001973class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001974public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001975 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1976 : CommandObjectParsed(
1977 interpreter, "add", "Add a name to the breakpoints provided.",
1978 "breakpoint name add <command-options> <breakpoint-id-list>"),
1979 m_name_options(), m_option_group() {
1980 // Create the first variant for the first (and only) argument for this
1981 // command.
1982 CommandArgumentEntry arg1;
1983 CommandArgumentData id_arg;
1984 id_arg.arg_type = eArgTypeBreakpointID;
1985 id_arg.arg_repetition = eArgRepeatOptional;
1986 arg1.push_back(id_arg);
1987 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001988
Kate Stoneb9c1b512016-09-06 20:57:50 +00001989 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1990 m_option_group.Finalize();
1991 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001992
Kate Stoneb9c1b512016-09-06 20:57:50 +00001993 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001994
Kate Stoneb9c1b512016-09-06 20:57:50 +00001995 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001996
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001997protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001998 bool DoExecute(Args &command, CommandReturnObject &result) override {
1999 if (!m_name_options.m_name.OptionWasSet()) {
2000 result.SetError("No name option provided.");
2001 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002002 }
2003
Kate Stoneb9c1b512016-09-06 20:57:50 +00002004 Target *target =
2005 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2006
2007 if (target == nullptr) {
2008 result.AppendError("Invalid target. No existing target or breakpoints.");
2009 result.SetStatus(eReturnStatusFailed);
2010 return false;
2011 }
2012
2013 std::unique_lock<std::recursive_mutex> lock;
2014 target->GetBreakpointList().GetListMutex(lock);
2015
2016 const BreakpointList &breakpoints = target->GetBreakpointList();
2017
2018 size_t num_breakpoints = breakpoints.GetSize();
2019 if (num_breakpoints == 0) {
2020 result.SetError("No breakpoints, cannot add names.");
2021 result.SetStatus(eReturnStatusFailed);
2022 return false;
2023 }
2024
2025 // Particular breakpoint selected; disable that breakpoint.
2026 BreakpointIDList valid_bp_ids;
2027 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002028 command, target, result, &valid_bp_ids,
2029 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002030
2031 if (result.Succeeded()) {
2032 if (valid_bp_ids.GetSize() == 0) {
2033 result.SetError("No breakpoints specified, cannot add names.");
2034 result.SetStatus(eReturnStatusFailed);
2035 return false;
2036 }
2037 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00002038 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2039 Status error; // This error reports illegal names, but we've already
2040 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002041 for (size_t index = 0; index < num_valid_ids; index++) {
2042 lldb::break_id_t bp_id =
2043 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2044 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002045 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002046 }
2047 }
2048
2049 return true;
2050 }
2051
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002052private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002053 BreakpointNameOptionGroup m_name_options;
2054 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002055};
2056
Kate Stoneb9c1b512016-09-06 20:57:50 +00002057class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002058public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002059 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2060 : CommandObjectParsed(
2061 interpreter, "delete",
2062 "Delete a name from the breakpoints provided.",
2063 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2064 m_name_options(), m_option_group() {
2065 // Create the first variant for the first (and only) argument for this
2066 // command.
2067 CommandArgumentEntry arg1;
2068 CommandArgumentData id_arg;
2069 id_arg.arg_type = eArgTypeBreakpointID;
2070 id_arg.arg_repetition = eArgRepeatOptional;
2071 arg1.push_back(id_arg);
2072 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002073
Kate Stoneb9c1b512016-09-06 20:57:50 +00002074 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2075 m_option_group.Finalize();
2076 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002077
Kate Stoneb9c1b512016-09-06 20:57:50 +00002078 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002079
Kate Stoneb9c1b512016-09-06 20:57:50 +00002080 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002081
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002082protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002083 bool DoExecute(Args &command, CommandReturnObject &result) override {
2084 if (!m_name_options.m_name.OptionWasSet()) {
2085 result.SetError("No name option provided.");
2086 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002087 }
2088
Kate Stoneb9c1b512016-09-06 20:57:50 +00002089 Target *target =
2090 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2091
2092 if (target == nullptr) {
2093 result.AppendError("Invalid target. No existing target or breakpoints.");
2094 result.SetStatus(eReturnStatusFailed);
2095 return false;
2096 }
2097
2098 std::unique_lock<std::recursive_mutex> lock;
2099 target->GetBreakpointList().GetListMutex(lock);
2100
2101 const BreakpointList &breakpoints = target->GetBreakpointList();
2102
2103 size_t num_breakpoints = breakpoints.GetSize();
2104 if (num_breakpoints == 0) {
2105 result.SetError("No breakpoints, cannot delete names.");
2106 result.SetStatus(eReturnStatusFailed);
2107 return false;
2108 }
2109
2110 // Particular breakpoint selected; disable that breakpoint.
2111 BreakpointIDList valid_bp_ids;
2112 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002113 command, target, result, &valid_bp_ids,
2114 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002115
2116 if (result.Succeeded()) {
2117 if (valid_bp_ids.GetSize() == 0) {
2118 result.SetError("No breakpoints specified, cannot delete names.");
2119 result.SetStatus(eReturnStatusFailed);
2120 return false;
2121 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002122 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002123 size_t num_valid_ids = valid_bp_ids.GetSize();
2124 for (size_t index = 0; index < num_valid_ids; index++) {
2125 lldb::break_id_t bp_id =
2126 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2127 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002128 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002129 }
2130 }
2131
2132 return true;
2133 }
2134
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002135private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002136 BreakpointNameOptionGroup m_name_options;
2137 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002138};
2139
Kate Stoneb9c1b512016-09-06 20:57:50 +00002140class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002141public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002142 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2143 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002144 "List either the names for a breakpoint or info "
2145 "about a given name. With no arguments, lists all "
2146 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002147 "breakpoint name list <command-options>"),
2148 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002149 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002150 m_option_group.Finalize();
2151 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002152
Kate Stoneb9c1b512016-09-06 20:57:50 +00002153 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002154
Kate Stoneb9c1b512016-09-06 20:57:50 +00002155 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002156
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002157protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002158 bool DoExecute(Args &command, CommandReturnObject &result) override {
2159 Target *target =
2160 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002161
Kate Stoneb9c1b512016-09-06 20:57:50 +00002162 if (target == nullptr) {
2163 result.AppendError("Invalid target. No existing target or breakpoints.");
2164 result.SetStatus(eReturnStatusFailed);
2165 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002166 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002167
2168
2169 std::vector<std::string> name_list;
2170 if (command.empty()) {
2171 target->GetBreakpointNames(name_list);
2172 } else {
2173 for (const Args::ArgEntry &arg : command)
2174 {
2175 name_list.push_back(arg.c_str());
2176 }
2177 }
2178
2179 if (name_list.empty()) {
2180 result.AppendMessage("No breakpoint names found.");
2181 } else {
2182 for (const std::string &name_str : name_list) {
2183 const char *name = name_str.c_str();
2184 // First print out the options for the name:
2185 Status error;
2186 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2187 false,
2188 error);
2189 if (bp_name)
2190 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002191 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002192 result.AppendMessageWithFormat("Name: %s\n", name);
2193 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2194 {
2195 result.AppendMessage(s.GetString());
2196 }
2197
2198 std::unique_lock<std::recursive_mutex> lock;
2199 target->GetBreakpointList().GetListMutex(lock);
2200
2201 BreakpointList &breakpoints = target->GetBreakpointList();
2202 bool any_set = false;
2203 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2204 if (bp_sp->MatchesName(name)) {
2205 StreamString s;
2206 any_set = true;
2207 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2208 s.EOL();
2209 result.AppendMessage(s.GetString());
2210 }
2211 }
2212 if (!any_set)
2213 result.AppendMessage("No breakpoints using this name.");
2214 } else {
2215 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002216 }
2217 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002218 }
2219 return true;
2220 }
2221
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002222private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002223 BreakpointNameOptionGroup m_name_options;
2224 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002225};
2226
Jim Inghame14dc262016-09-12 23:10:56 +00002227// CommandObjectBreakpointName
Kate Stoneb9c1b512016-09-06 20:57:50 +00002228class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002229public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002230 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2231 : CommandObjectMultiword(
2232 interpreter, "name", "Commands to manage name tags for breakpoints",
2233 "breakpoint name <subcommand> [<command-options>]") {
2234 CommandObjectSP add_command_object(
2235 new CommandObjectBreakpointNameAdd(interpreter));
2236 CommandObjectSP delete_command_object(
2237 new CommandObjectBreakpointNameDelete(interpreter));
2238 CommandObjectSP list_command_object(
2239 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002240 CommandObjectSP configure_command_object(
2241 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002242
Kate Stoneb9c1b512016-09-06 20:57:50 +00002243 LoadSubCommand("add", add_command_object);
2244 LoadSubCommand("delete", delete_command_object);
2245 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002246 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002247 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002248
Kate Stoneb9c1b512016-09-06 20:57:50 +00002249 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002250};
2251
Jim Inghame14dc262016-09-12 23:10:56 +00002252// CommandObjectBreakpointRead
Jim Ingham3acdf382016-09-22 22:20:28 +00002253#pragma mark Read::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002254static constexpr OptionDefinition g_breakpoint_read_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002255 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002256 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2257 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002258 // clang-format on
2259};
2260
2261#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002262
2263class CommandObjectBreakpointRead : public CommandObjectParsed {
2264public:
2265 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2266 : CommandObjectParsed(interpreter, "breakpoint read",
2267 "Read and set the breakpoints previously saved to "
2268 "a file with \"breakpoint write\". ",
2269 nullptr),
2270 m_options() {
2271 CommandArgumentEntry arg;
2272 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2273 eArgTypeBreakpointIDRange);
2274 // Add the entry for the first argument for this command to the object's
2275 // arguments vector.
2276 m_arguments.push_back(arg);
2277 }
2278
2279 ~CommandObjectBreakpointRead() override = default;
2280
2281 Options *GetOptions() override { return &m_options; }
2282
2283 class CommandOptions : public Options {
2284 public:
2285 CommandOptions() : Options() {}
2286
2287 ~CommandOptions() override = default;
2288
Zachary Turner97206d52017-05-12 04:51:55 +00002289 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2290 ExecutionContext *execution_context) override {
2291 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002292 const int short_option = m_getopt_table[option_idx].val;
2293
2294 switch (short_option) {
2295 case 'f':
2296 m_filename.assign(option_arg);
2297 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002298 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002299 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002300 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2301 name_error)) {
2302 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2303 name_error.AsCString());
2304 }
2305 m_names.push_back(option_arg);
2306 break;
2307 }
Jim Inghame14dc262016-09-12 23:10:56 +00002308 default:
2309 error.SetErrorStringWithFormat("unrecognized option '%c'",
2310 short_option);
2311 break;
2312 }
2313
2314 return error;
2315 }
2316
2317 void OptionParsingStarting(ExecutionContext *execution_context) override {
2318 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002319 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002320 }
2321
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002322 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002323 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002324 }
Jim Inghame14dc262016-09-12 23:10:56 +00002325
2326 // Instance variables to hold the values for command options.
2327
2328 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002329 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002330 };
2331
2332protected:
2333 bool DoExecute(Args &command, CommandReturnObject &result) override {
2334 Target *target = GetSelectedOrDummyTarget();
2335 if (target == nullptr) {
2336 result.AppendError("Invalid target. No existing target or breakpoints.");
2337 result.SetStatus(eReturnStatusFailed);
2338 return false;
2339 }
2340
Jim Ingham3acdf382016-09-22 22:20:28 +00002341 std::unique_lock<std::recursive_mutex> lock;
2342 target->GetBreakpointList().GetListMutex(lock);
2343
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002344 FileSpec input_spec(m_options.m_filename);
2345 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002346 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002347 Status error = target->CreateBreakpointsFromFile(
2348 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002349
Jim Inghame14dc262016-09-12 23:10:56 +00002350 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002351 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002352 result.SetStatus(eReturnStatusFailed);
2353 return false;
2354 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002355
2356 Stream &output_stream = result.GetOutputStream();
2357
2358 size_t num_breakpoints = new_bps.GetSize();
2359 if (num_breakpoints == 0) {
2360 result.AppendMessage("No breakpoints added.");
2361 } else {
2362 // No breakpoint selected; show info about all currently set breakpoints.
2363 result.AppendMessage("New breakpoints:");
2364 for (size_t i = 0; i < num_breakpoints; ++i) {
2365 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2366 Breakpoint *bp = target->GetBreakpointList()
2367 .FindBreakpointByID(bp_id.GetBreakpointID())
2368 .get();
2369 if (bp)
2370 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2371 false);
2372 }
2373 }
Jim Inghame14dc262016-09-12 23:10:56 +00002374 return result.Succeeded();
2375 }
2376
2377private:
2378 CommandOptions m_options;
2379};
2380
Jim Inghame14dc262016-09-12 23:10:56 +00002381// CommandObjectBreakpointWrite
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002382#pragma mark Write::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002383static constexpr OptionDefinition g_breakpoint_write_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002384 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002385 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2386 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002387 // clang-format on
2388};
2389
2390#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002391class CommandObjectBreakpointWrite : public CommandObjectParsed {
2392public:
2393 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2394 : CommandObjectParsed(interpreter, "breakpoint write",
2395 "Write the breakpoints listed to a file that can "
2396 "be read in with \"breakpoint read\". "
2397 "If given no arguments, writes all breakpoints.",
2398 nullptr),
2399 m_options() {
2400 CommandArgumentEntry arg;
2401 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2402 eArgTypeBreakpointIDRange);
2403 // Add the entry for the first argument for this command to the object's
2404 // arguments vector.
2405 m_arguments.push_back(arg);
2406 }
2407
2408 ~CommandObjectBreakpointWrite() override = default;
2409
2410 Options *GetOptions() override { return &m_options; }
2411
2412 class CommandOptions : public Options {
2413 public:
2414 CommandOptions() : Options() {}
2415
2416 ~CommandOptions() override = default;
2417
Zachary Turner97206d52017-05-12 04:51:55 +00002418 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2419 ExecutionContext *execution_context) override {
2420 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002421 const int short_option = m_getopt_table[option_idx].val;
2422
2423 switch (short_option) {
2424 case 'f':
2425 m_filename.assign(option_arg);
2426 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002427 case 'a':
2428 m_append = true;
2429 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002430 default:
2431 error.SetErrorStringWithFormat("unrecognized option '%c'",
2432 short_option);
2433 break;
2434 }
2435
2436 return error;
2437 }
2438
2439 void OptionParsingStarting(ExecutionContext *execution_context) override {
2440 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002441 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002442 }
2443
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002444 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002445 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002446 }
Jim Inghame14dc262016-09-12 23:10:56 +00002447
2448 // Instance variables to hold the values for command options.
2449
2450 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002451 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002452 };
2453
2454protected:
2455 bool DoExecute(Args &command, CommandReturnObject &result) override {
2456 Target *target = GetSelectedOrDummyTarget();
2457 if (target == nullptr) {
2458 result.AppendError("Invalid target. No existing target or breakpoints.");
2459 result.SetStatus(eReturnStatusFailed);
2460 return false;
2461 }
2462
Jim Inghame14dc262016-09-12 23:10:56 +00002463 std::unique_lock<std::recursive_mutex> lock;
2464 target->GetBreakpointList().GetListMutex(lock);
2465
Jim Ingham01f16662016-09-14 19:07:35 +00002466 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002467 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002468 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002469 command, target, result, &valid_bp_ids,
2470 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002471
Jim Ingham01f16662016-09-14 19:07:35 +00002472 if (!result.Succeeded()) {
2473 result.SetStatus(eReturnStatusFailed);
2474 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002475 }
2476 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002477 FileSpec file_spec(m_options.m_filename);
2478 FileSystem::Instance().Resolve(file_spec);
2479 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2480 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002481 if (!error.Success()) {
2482 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2483 error.AsCString());
2484 result.SetStatus(eReturnStatusFailed);
2485 }
Jim Inghame14dc262016-09-12 23:10:56 +00002486 return result.Succeeded();
2487 }
2488
2489private:
2490 CommandOptions m_options;
2491};
2492
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002493// CommandObjectMultiwordBreakpoint
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002494#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002495
Kate Stoneb9c1b512016-09-06 20:57:50 +00002496CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2497 CommandInterpreter &interpreter)
2498 : CommandObjectMultiword(
2499 interpreter, "breakpoint",
2500 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2501 "breakpoint <subcommand> [<command-options>]") {
2502 CommandObjectSP list_command_object(
2503 new CommandObjectBreakpointList(interpreter));
2504 CommandObjectSP enable_command_object(
2505 new CommandObjectBreakpointEnable(interpreter));
2506 CommandObjectSP disable_command_object(
2507 new CommandObjectBreakpointDisable(interpreter));
2508 CommandObjectSP clear_command_object(
2509 new CommandObjectBreakpointClear(interpreter));
2510 CommandObjectSP delete_command_object(
2511 new CommandObjectBreakpointDelete(interpreter));
2512 CommandObjectSP set_command_object(
2513 new CommandObjectBreakpointSet(interpreter));
2514 CommandObjectSP command_command_object(
2515 new CommandObjectBreakpointCommand(interpreter));
2516 CommandObjectSP modify_command_object(
2517 new CommandObjectBreakpointModify(interpreter));
2518 CommandObjectSP name_command_object(
2519 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002520 CommandObjectSP write_command_object(
2521 new CommandObjectBreakpointWrite(interpreter));
2522 CommandObjectSP read_command_object(
2523 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002524
Kate Stoneb9c1b512016-09-06 20:57:50 +00002525 list_command_object->SetCommandName("breakpoint list");
2526 enable_command_object->SetCommandName("breakpoint enable");
2527 disable_command_object->SetCommandName("breakpoint disable");
2528 clear_command_object->SetCommandName("breakpoint clear");
2529 delete_command_object->SetCommandName("breakpoint delete");
2530 set_command_object->SetCommandName("breakpoint set");
2531 command_command_object->SetCommandName("breakpoint command");
2532 modify_command_object->SetCommandName("breakpoint modify");
2533 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002534 write_command_object->SetCommandName("breakpoint write");
2535 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002536
Kate Stoneb9c1b512016-09-06 20:57:50 +00002537 LoadSubCommand("list", list_command_object);
2538 LoadSubCommand("enable", enable_command_object);
2539 LoadSubCommand("disable", disable_command_object);
2540 LoadSubCommand("clear", clear_command_object);
2541 LoadSubCommand("delete", delete_command_object);
2542 LoadSubCommand("set", set_command_object);
2543 LoadSubCommand("command", command_command_object);
2544 LoadSubCommand("modify", modify_command_object);
2545 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002546 LoadSubCommand("write", write_command_object);
2547 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002548}
2549
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002550CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002551
Kate Stoneb9c1b512016-09-06 20:57:50 +00002552void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2553 bool allow_locations,
2554 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002555 BreakpointIDList *valid_ids,
2556 BreakpointName::Permissions
2557 ::PermissionKinds
2558 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002559 // args can be strings representing 1). integers (for breakpoint ids)
2560 // 2). the full breakpoint & location
2561 // canonical representation
2562 // 3). the word "to" or a hyphen,
2563 // representing a range (in which case there
2564 // had *better* be an entry both before &
2565 // after of one of the first two types.
2566 // 4). A breakpoint name
2567 // If args is empty, we will use the last created breakpoint (if there is
2568 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002569
Kate Stoneb9c1b512016-09-06 20:57:50 +00002570 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002571
Zachary Turner11eb9c62016-10-05 20:03:37 +00002572 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002573 if (target->GetLastCreatedBreakpoint()) {
2574 valid_ids->AddBreakpointID(BreakpointID(
2575 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2576 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2577 } else {
2578 result.AppendError(
2579 "No breakpoint specified and no last created breakpoint.");
2580 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002581 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002582 return;
2583 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002584
Kate Stoneb9c1b512016-09-06 20:57:50 +00002585 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002586 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2587 // id range strings over; instead generate a list of strings for all the
2588 // breakpoint ids in the range, and shove all of those breakpoint id strings
2589 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002590
Jim Inghamb842f2e2017-09-14 20:22:49 +00002591 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2592 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002593
Kate Stoneb9c1b512016-09-06 20:57:50 +00002594 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2595 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002596
Pavel Labath16662f32018-06-20 08:12:50 +00002597 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002598
Adrian Prantl05097242018-04-30 16:49:04 +00002599 // At this point, all of the breakpoint ids that the user passed in have
2600 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002601
Kate Stoneb9c1b512016-09-06 20:57:50 +00002602 if (result.Succeeded()) {
2603 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002604 // ids, go through our tentative list of breakpoint id's and verify that
2605 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002606
2607 const size_t count = valid_ids->GetSize();
2608 for (size_t i = 0; i < count; ++i) {
2609 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2610 Breakpoint *breakpoint =
2611 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2612 if (breakpoint != nullptr) {
2613 const size_t num_locations = breakpoint->GetNumLocations();
2614 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2615 StreamString id_str;
2616 BreakpointID::GetCanonicalReference(
2617 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2618 i = valid_ids->GetSize() + 1;
2619 result.AppendErrorWithFormat(
2620 "'%s' is not a currently valid breakpoint/location id.\n",
2621 id_str.GetData());
2622 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002623 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002624 } else {
2625 i = valid_ids->GetSize() + 1;
2626 result.AppendErrorWithFormat(
2627 "'%d' is not a currently valid breakpoint ID.\n",
2628 cur_bp_id.GetBreakpointID());
2629 result.SetStatus(eReturnStatusFailed);
2630 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002631 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002632 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002633}