blob: 0002b7f3497ff0e39b15fc586963666e6b191617 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000012#include <vector>
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014// Other libraries and framework includes
15// Project includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000016#include "CommandObjectBreakpoint.h"
17#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Breakpoint/Breakpoint.h"
19#include "lldb/Breakpoint/BreakpointIDList.h"
20#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000021#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/CommandCompletions.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000025#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000026#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000027#include "lldb/Interpreter/OptionValueString.h"
28#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000029#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000030#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000031#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000032#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000033#include "lldb/Target/Thread.h"
34#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000035#include "lldb/Utility/RegularExpression.h"
36#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
38using namespace lldb;
39using namespace lldb_private;
40
Kate Stoneb9c1b512016-09-06 20:57:50 +000041static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
42 lldb::DescriptionLevel level) {
43 s->IndentMore();
44 bp->GetDescription(s, level, true);
45 s->IndentLess();
46 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047}
48
Jim Inghamb842f2e2017-09-14 20:22:49 +000049//-------------------------------------------------------------------------
50// Modifiable Breakpoint Options
51//-------------------------------------------------------------------------
52#pragma mark Modify::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000053static constexpr OptionDefinition g_breakpoint_modify_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +000054 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000055 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
56 { 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." },
57 { 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." },
58 { 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." },
59 { 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." },
60 { 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." },
61 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
62 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
63 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
64 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
65 { 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 +000066 // clang-format on
67};
68class lldb_private::BreakpointOptionGroup : public OptionGroup
69{
70public:
71 BreakpointOptionGroup() :
72 OptionGroup(),
73 m_bp_opts(false) {}
74
75 ~BreakpointOptionGroup() override = default;
76
77 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
78 return llvm::makeArrayRef(g_breakpoint_modify_options);
79 }
80
81 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
82 ExecutionContext *execution_context) override {
83 Status error;
84 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
85
86 switch (short_option) {
87 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000088 // Normally an empty breakpoint condition marks is as unset. But we need
89 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000090 m_bp_opts.SetCondition(option_arg.str().c_str());
91 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
92 break;
93 case 'C':
94 m_commands.push_back(option_arg);
95 break;
96 case 'd':
97 m_bp_opts.SetEnabled(false);
98 break;
99 case 'e':
100 m_bp_opts.SetEnabled(true);
101 break;
102 case 'G': {
103 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000104 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000105 if (success) {
106 m_bp_opts.SetAutoContinue(value);
107 } else
108 error.SetErrorStringWithFormat(
109 "invalid boolean value '%s' passed for -G option",
110 option_arg.str().c_str());
111 }
112 break;
113 case 'i':
114 {
115 uint32_t ignore_count;
116 if (option_arg.getAsInteger(0, ignore_count))
117 error.SetErrorStringWithFormat("invalid ignore count '%s'",
118 option_arg.str().c_str());
119 else
120 m_bp_opts.SetIgnoreCount(ignore_count);
121 }
122 break;
123 case 'o': {
124 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000125 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000126 if (success) {
127 m_bp_opts.SetOneShot(value);
128 } else
129 error.SetErrorStringWithFormat(
130 "invalid boolean value '%s' passed for -o option",
131 option_arg.str().c_str());
132 } break;
133 case 't':
134 {
135 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
136 if (option_arg[0] != '\0') {
137 if (option_arg.getAsInteger(0, thread_id))
138 error.SetErrorStringWithFormat("invalid thread id string '%s'",
139 option_arg.str().c_str());
140 }
141 m_bp_opts.SetThreadID(thread_id);
142 }
143 break;
144 case 'T':
145 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
146 break;
147 case 'q':
148 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
149 break;
150 case 'x':
151 {
152 uint32_t thread_index = UINT32_MAX;
153 if (option_arg[0] != '\n') {
154 if (option_arg.getAsInteger(0, thread_index))
155 error.SetErrorStringWithFormat("invalid thread index string '%s'",
156 option_arg.str().c_str());
157 }
158 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
159 }
160 break;
161 default:
162 error.SetErrorStringWithFormat("unrecognized option '%c'",
163 short_option);
164 break;
165 }
166
167 return error;
168 }
169
170 void OptionParsingStarting(ExecutionContext *execution_context) override {
171 m_bp_opts.Clear();
172 m_commands.clear();
173 }
174
175 Status OptionParsingFinished(ExecutionContext *execution_context) override {
176 if (!m_commands.empty())
177 {
178 if (!m_commands.empty())
179 {
180 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
181
182 for (std::string &str : m_commands)
183 cmd_data->user_source.AppendString(str);
184
185 cmd_data->stop_on_error = true;
186 m_bp_opts.SetCommandDataCallback(cmd_data);
187 }
188 }
189 return Status();
190 }
191
192 const BreakpointOptions &GetBreakpointOptions()
193 {
194 return m_bp_opts;
195 }
196
197 std::vector<std::string> m_commands;
198 BreakpointOptions m_bp_opts;
199
200};
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000201static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000202 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000203 { 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 +0000204 "which prime new targets." },
205 // clang-format on
206};
207
208class BreakpointDummyOptionGroup : public OptionGroup
209{
210public:
211 BreakpointDummyOptionGroup() :
212 OptionGroup() {}
213
214 ~BreakpointDummyOptionGroup() override = default;
215
216 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
217 return llvm::makeArrayRef(g_breakpoint_dummy_options);
218 }
219
220 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
221 ExecutionContext *execution_context) override {
222 Status error;
223 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
224
225 switch (short_option) {
226 case 'D':
227 m_use_dummy = true;
228 break;
229 default:
230 error.SetErrorStringWithFormat("unrecognized option '%c'",
231 short_option);
232 break;
233 }
234
235 return error;
236 }
237
238 void OptionParsingStarting(ExecutionContext *execution_context) override {
239 m_use_dummy = false;
240 }
241
242 bool m_use_dummy;
243
244};
245
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000246// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
247// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Jim Ingham3815e702018-09-13 21:35:32 +0000248#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000249#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham3815e702018-09-13 21:35:32 +0000250#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
251#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000252#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
253#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
254
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000255static constexpr OptionDefinition g_breakpoint_set_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000256 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000257 { 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 +0000258 "multiple times to specify multiple shared libraries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000259 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
260 { 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 +0000261 "lldb only looks for files that are #included if they use the standard include "
262 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
263 "#included, set target.inline-breakpoint-strategy to \"always\"." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000264 { 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 +0000265
Adrian Prantl05097242018-04-30 16:49:04 +0000266 // Comment out this option for the moment, as we don't actually use it, but
267 // will in the future. This way users won't see it, but the infrastructure is
268 // left in place.
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000269 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
270 // "Set the breakpoint by source location at this particular column."},
271
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000272 { 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 +0000273 "a particular binary, then the address will be converted to a \"file\" "
274 "address, so that the breakpoint will track that binary+offset no matter where "
275 "the binary eventually loads. Alternately, if you also specify the module - "
276 "with the -s option - then the address will be treated as a file address in "
277 "that module, and resolved accordingly. Again, this will allow lldb to track "
278 "that offset on subsequent reloads. The module need not have been loaded at "
279 "the time you specify this breakpoint, and will get resolved when the module "
280 "is loaded." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000281 { 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 +0000282 "one breakpoint for multiple names" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000283 { 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 +0000284 "functions. Can be repeated multiple times." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000285 { 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 +0000286 "namespaces and all arguments, and for Objective-C this means a full function "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000287 "prototype with class and selector. Can be repeated multiple times to make "
288 "one breakpoint for multiple names." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000289 { 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 +0000290 "make one breakpoint for multiple Selectors." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000291 { 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 +0000292 "make one breakpoint for multiple methods." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000293 { 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 +0000294 "the function name(s)." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000295 { 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 +0000296 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
297 "symbols." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000298 { 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 +0000299 "against the source text in a source file or files specified with the -f "
300 "option. The -f option can be specified more than once. If no source files "
301 "are specified, uses the current \"default source file\". If you want to "
302 "match against all source files, pass the \"--all-files\" option." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000303 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
304 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
305 { 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." },
306 { 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." },
307 { 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 +0000308 "options, on throw but not catch.)" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000309 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
310 { 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 +0000311
312 // Don't add this option till it actually does something useful...
313 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
314 // "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" },
315
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000316 { 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 +0000317 "(note: currently only implemented for setting breakpoints on identifiers). "
318 "If not set the target.language setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000319 { 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 +0000320 "If not set the target.skip-prologue setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000321 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
322 { 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 +0000323 "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 +0000324 { 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 +0000325 "setting is used." },
326 // clang-format on
327};
328
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000330// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331//-------------------------------------------------------------------------
332
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000334public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 typedef enum BreakpointSetType {
336 eSetTypeInvalid,
337 eSetTypeFileAndLine,
338 eSetTypeAddress,
339 eSetTypeFunctionName,
340 eSetTypeFunctionRegexp,
341 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000342 eSetTypeException,
343 eSetTypeScripted,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344 } BreakpointSetType;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345
Kate Stoneb9c1b512016-09-06 20:57:50 +0000346 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
347 : CommandObjectParsed(
348 interpreter, "breakpoint set",
349 "Sets a breakpoint or set of breakpoints in the executable.",
350 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000351 m_bp_opts(), m_options() {
352 // We're picking up all the normal options, commands and disable.
353 m_all_options.Append(&m_bp_opts,
354 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
355 LLDB_OPT_SET_ALL);
356 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
357 m_all_options.Append(&m_options);
358 m_all_options.Finalize();
359 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360
361 ~CommandObjectBreakpointSet() override = default;
362
Jim Inghamb842f2e2017-09-14 20:22:49 +0000363 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364
Jim Inghamb842f2e2017-09-14 20:22:49 +0000365 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000366 public:
367 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000368 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
370 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
372 m_exception_language(eLanguageTypeUnknown),
373 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000374 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
376
377 ~CommandOptions() override = default;
378
Zachary Turner97206d52017-05-12 04:51:55 +0000379 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
380 ExecutionContext *execution_context) override {
381 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000382 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383
384 switch (short_option) {
385 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000386 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
387 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388 } break;
389
390 case 'A':
391 m_all_files = true;
392 break;
393
394 case 'b':
395 m_func_names.push_back(option_arg);
396 m_func_name_type_mask |= eFunctionNameTypeBase;
397 break;
398
Zachary Turnerfe114832016-11-12 16:56:47 +0000399 case 'C':
400 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000402 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404
Kate Stoneb9c1b512016-09-06 20:57:50 +0000405 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000406 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407
408 switch (language) {
409 case eLanguageTypeC89:
410 case eLanguageTypeC:
411 case eLanguageTypeC99:
412 case eLanguageTypeC11:
413 m_exception_language = eLanguageTypeC;
414 break;
415 case eLanguageTypeC_plus_plus:
416 case eLanguageTypeC_plus_plus_03:
417 case eLanguageTypeC_plus_plus_11:
418 case eLanguageTypeC_plus_plus_14:
419 m_exception_language = eLanguageTypeC_plus_plus;
420 break;
421 case eLanguageTypeObjC:
422 m_exception_language = eLanguageTypeObjC;
423 break;
424 case eLanguageTypeObjC_plus_plus:
425 error.SetErrorStringWithFormat(
426 "Set exception breakpoints separately for c++ and objective-c");
427 break;
428 case eLanguageTypeUnknown:
429 error.SetErrorStringWithFormat(
430 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000431 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 break;
433 default:
434 error.SetErrorStringWithFormat(
435 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000436 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000437 }
438 } break;
439
440 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000441 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 break;
443
444 case 'F':
445 m_func_names.push_back(option_arg);
446 m_func_name_type_mask |= eFunctionNameTypeFull;
447 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000448
Kate Stoneb9c1b512016-09-06 20:57:50 +0000449 case 'h': {
450 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000451 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000452 if (!success)
453 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000454 "Invalid boolean value for on-catch option: '%s'",
455 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 } break;
457
458 case 'H':
459 m_hardware = true;
460 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000461
462 case 'k': {
463 if (m_current_key.empty())
464 m_current_key.assign(option_arg);
465 else
466 error.SetErrorStringWithFormat("Key: %s missing value.",
467 m_current_key.c_str());
468
469 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 case 'K': {
471 bool success;
472 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000473 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 if (value)
475 m_skip_prologue = eLazyBoolYes;
476 else
477 m_skip_prologue = eLazyBoolNo;
478
479 if (!success)
480 error.SetErrorStringWithFormat(
481 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000482 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483 } break;
484
Zachary Turnerfe114832016-11-12 16:56:47 +0000485 case 'l':
486 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000487 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000488 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490
491 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000492 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000493 if (m_language == eLanguageTypeUnknown)
494 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000495 "Unknown language type: '%s' for breakpoint",
496 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000497 break;
498
499 case 'm': {
500 bool success;
501 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000502 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000503 if (value)
504 m_move_to_nearest_code = eLazyBoolYes;
505 else
506 m_move_to_nearest_code = eLazyBoolNo;
507
508 if (!success)
509 error.SetErrorStringWithFormat(
510 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000511 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000512 break;
513 }
514
515 case 'M':
516 m_func_names.push_back(option_arg);
517 m_func_name_type_mask |= eFunctionNameTypeMethod;
518 break;
519
520 case 'n':
521 m_func_names.push_back(option_arg);
522 m_func_name_type_mask |= eFunctionNameTypeAuto;
523 break;
524
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000525 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000526 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000528 else
529 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000530 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000532 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533
534 case 'R': {
535 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000536 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
537 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 if (error.Success())
539 m_offset_addr = tmp_offset_addr;
540 } break;
541
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000543 m_exception_extra_args.AppendArgument("-O");
544 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 break;
546
547 case 'p':
548 m_source_text_regexp.assign(option_arg);
549 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000550
551 case 'P':
552 m_python_class.assign(option_arg);
553 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 case 'r':
556 m_func_regexp.assign(option_arg);
557 break;
558
559 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000560 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561 break;
562
563 case 'S':
564 m_func_names.push_back(option_arg);
565 m_func_name_type_mask |= eFunctionNameTypeSelector;
566 break;
567
Jim Ingham3815e702018-09-13 21:35:32 +0000568 case 'v': {
569 if (!m_current_key.empty()) {
570 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
571 m_current_key.clear();
572 }
573 else
574 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
575 option_arg.str().c_str());
576 } break;
577
Kate Stoneb9c1b512016-09-06 20:57:50 +0000578 case 'w': {
579 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000580 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000581 if (!success)
582 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000583 "Invalid boolean value for on-throw option: '%s'",
584 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000585 } break;
586
Kate Stoneb9c1b512016-09-06 20:57:50 +0000587 case 'X':
588 m_source_regex_func_names.insert(option_arg);
589 break;
590
591 default:
592 error.SetErrorStringWithFormat("unrecognized option '%c'",
593 short_option);
594 break;
595 }
596
597 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000598 }
599
Kate Stoneb9c1b512016-09-06 20:57:50 +0000600 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000601 m_filenames.Clear();
602 m_line_num = 0;
603 m_column = 0;
604 m_func_names.clear();
605 m_func_name_type_mask = eFunctionNameTypeNone;
606 m_func_regexp.clear();
607 m_source_text_regexp.clear();
608 m_modules.Clear();
609 m_load_addr = LLDB_INVALID_ADDRESS;
610 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000611 m_catch_bp = false;
612 m_throw_bp = true;
613 m_hardware = false;
614 m_exception_language = eLanguageTypeUnknown;
615 m_language = lldb::eLanguageTypeUnknown;
616 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000617 m_breakpoint_names.clear();
618 m_all_files = false;
619 m_exception_extra_args.Clear();
620 m_move_to_nearest_code = eLazyBoolCalculate;
621 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000622 m_python_class.clear();
623 m_extra_args_sp.reset(new StructuredData::Dictionary());
624 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000625 }
626
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000627 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000628 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000629 }
Jim Ingham5a988412012-06-08 21:56:10 +0000630
Kate Stoneb9c1b512016-09-06 20:57:50 +0000631 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000632
Kate Stoneb9c1b512016-09-06 20:57:50 +0000633 std::string m_condition;
634 FileSpecList m_filenames;
635 uint32_t m_line_num;
636 uint32_t m_column;
637 std::vector<std::string> m_func_names;
638 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000639 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000640 std::string m_func_regexp;
641 std::string m_source_text_regexp;
642 FileSpecList m_modules;
643 lldb::addr_t m_load_addr;
644 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000645 bool m_catch_bp;
646 bool m_throw_bp;
647 bool m_hardware; // Request to use hardware breakpoints
648 lldb::LanguageType m_exception_language;
649 lldb::LanguageType m_language;
650 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000651 bool m_all_files;
652 Args m_exception_extra_args;
653 LazyBool m_move_to_nearest_code;
654 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000655 std::string m_python_class;
656 StructuredData::DictionarySP m_extra_args_sp;
657 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000658 };
Jim Ingham5a988412012-06-08 21:56:10 +0000659
660protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000661 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000662 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000663
Kate Stoneb9c1b512016-09-06 20:57:50 +0000664 if (target == nullptr) {
665 result.AppendError("Invalid target. Must set target before setting "
666 "breakpoints (see 'target create' command).");
667 result.SetStatus(eReturnStatusFailed);
668 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000669 }
670
Kate Stoneb9c1b512016-09-06 20:57:50 +0000671 // The following are the various types of breakpoints that could be set:
672 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
673 // 2). -a [-s -g] (setting breakpoint by address)
674 // 3). -n [-s -g] (setting breakpoint by function name)
675 // 4). -r [-s -g] (setting breakpoint by function name regular
676 // expression)
677 // 5). -p -f (setting a breakpoint by comparing a reg-exp
678 // to source text)
679 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
680 // given language.)
681
682 BreakpointSetType break_type = eSetTypeInvalid;
683
Jim Ingham3815e702018-09-13 21:35:32 +0000684 if (!m_options.m_python_class.empty())
685 break_type = eSetTypeScripted;
686 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000687 break_type = eSetTypeFileAndLine;
688 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
689 break_type = eSetTypeAddress;
690 else if (!m_options.m_func_names.empty())
691 break_type = eSetTypeFunctionName;
692 else if (!m_options.m_func_regexp.empty())
693 break_type = eSetTypeFunctionRegexp;
694 else if (!m_options.m_source_text_regexp.empty())
695 break_type = eSetTypeSourceRegexp;
696 else if (m_options.m_exception_language != eLanguageTypeUnknown)
697 break_type = eSetTypeException;
698
Jim Inghamb842f2e2017-09-14 20:22:49 +0000699 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000700 FileSpec module_spec;
701 const bool internal = false;
702
703 // If the user didn't specify skip-prologue, having an offset should turn
704 // that off.
705 if (m_options.m_offset_addr != 0 &&
706 m_options.m_skip_prologue == eLazyBoolCalculate)
707 m_options.m_skip_prologue = eLazyBoolNo;
708
709 switch (break_type) {
710 case eSetTypeFileAndLine: // Breakpoint by source position
711 {
712 FileSpec file;
713 const size_t num_files = m_options.m_filenames.GetSize();
714 if (num_files == 0) {
715 if (!GetDefaultFile(target, file, result)) {
716 result.AppendError("No file supplied and no default file available.");
717 result.SetStatus(eReturnStatusFailed);
718 return false;
719 }
720 } else if (num_files > 1) {
721 result.AppendError("Only one file at a time is allowed for file and "
722 "line breakpoints.");
723 result.SetStatus(eReturnStatusFailed);
724 return false;
725 } else
726 file = m_options.m_filenames.GetFileSpecAtIndex(0);
727
728 // Only check for inline functions if
729 LazyBool check_inlines = eLazyBoolCalculate;
730
Jim Inghamb842f2e2017-09-14 20:22:49 +0000731 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
732 file,
Adrian Prantl431b1582018-08-30 15:11:00 +0000733 m_options.m_line_num,
734 m_options.m_column,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000735 m_options.m_offset_addr,
736 check_inlines,
737 m_options.m_skip_prologue,
738 internal,
739 m_options.m_hardware,
740 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000741 } break;
742
743 case eSetTypeAddress: // Breakpoint by address
744 {
745 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000746 // with the library, and use that. That way the address breakpoint
747 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000748 size_t num_modules_specified = m_options.m_modules.GetSize();
749 if (num_modules_specified == 1) {
750 const FileSpec *file_spec =
751 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000752 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
753 internal, file_spec,
754 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000755 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000756 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
757 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000758 } else {
759 result.AppendError("Only one shared library can be specified for "
760 "address breakpoints.");
761 result.SetStatus(eReturnStatusFailed);
762 return false;
763 }
764 break;
765 }
766 case eSetTypeFunctionName: // Breakpoint by function name
767 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000768 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000769
770 if (name_type_mask == 0)
771 name_type_mask = eFunctionNameTypeAuto;
772
Jim Inghamb842f2e2017-09-14 20:22:49 +0000773 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
774 &(m_options.m_filenames),
775 m_options.m_func_names,
776 name_type_mask,
777 m_options.m_language,
778 m_options.m_offset_addr,
779 m_options.m_skip_prologue,
780 internal,
781 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000782 } break;
783
784 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
785 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000786 {
Zachary Turner95eae422016-09-21 16:01:28 +0000787 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000788 if (!regexp.IsValid()) {
789 char err_str[1024];
790 regexp.GetErrorAsCString(err_str, sizeof(err_str));
791 result.AppendErrorWithFormat(
792 "Function name regular expression could not be compiled: \"%s\"",
793 err_str);
794 result.SetStatus(eReturnStatusFailed);
795 return false;
796 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000797
Jim Inghamb842f2e2017-09-14 20:22:49 +0000798 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
799 &(m_options.m_filenames),
800 regexp,
801 m_options.m_language,
802 m_options.m_skip_prologue,
803 internal,
804 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000805 }
806 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000807 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
808 {
809 const size_t num_files = m_options.m_filenames.GetSize();
810
811 if (num_files == 0 && !m_options.m_all_files) {
812 FileSpec file;
813 if (!GetDefaultFile(target, file, result)) {
814 result.AppendError(
815 "No files provided and could not find default file.");
816 result.SetStatus(eReturnStatusFailed);
817 return false;
818 } else {
819 m_options.m_filenames.Append(file);
820 }
821 }
822
Zachary Turner95eae422016-09-21 16:01:28 +0000823 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000824 if (!regexp.IsValid()) {
825 char err_str[1024];
826 regexp.GetErrorAsCString(err_str, sizeof(err_str));
827 result.AppendErrorWithFormat(
828 "Source text regular expression could not be compiled: \"%s\"",
829 err_str);
830 result.SetStatus(eReturnStatusFailed);
831 return false;
832 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000833 bp_sp =
834 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
835 &(m_options.m_filenames),
836 m_options
837 .m_source_regex_func_names,
838 regexp,
839 internal,
840 m_options.m_hardware,
841 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000842 } break;
843 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000844 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000845 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
846 m_options.m_catch_bp,
847 m_options.m_throw_bp,
848 internal,
849 &m_options
850 .m_exception_extra_args,
851 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000852 if (precond_error.Fail()) {
853 result.AppendErrorWithFormat(
854 "Error setting extra exception arguments: %s",
855 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000856 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000857 result.SetStatus(eReturnStatusFailed);
858 return false;
859 }
860 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000861 case eSetTypeScripted: {
862
863 Status error;
864 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
865 &(m_options.m_modules),
866 &(m_options.m_filenames),
867 false,
868 m_options.m_hardware,
869 m_options.m_extra_args_sp,
870 &error);
871 if (error.Fail()) {
872 result.AppendErrorWithFormat(
873 "Error setting extra exception arguments: %s",
874 error.AsCString());
875 target->RemoveBreakpointByID(bp_sp->GetID());
876 result.SetStatus(eReturnStatusFailed);
877 return false;
878 }
879 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000880 default:
881 break;
882 }
883
884 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000885 if (bp_sp) {
886 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000887
888 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000889 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000890 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000891 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000892 if (name_error.Fail()) {
893 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
894 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000895 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000896 result.SetStatus(eReturnStatusFailed);
897 return false;
898 }
899 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000900 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000901 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000902
903 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000904 Stream &output_stream = result.GetOutputStream();
905 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000906 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000907 show_locations);
908 if (target == m_interpreter.GetDebugger().GetDummyTarget())
909 output_stream.Printf("Breakpoint set in dummy target, will get copied "
910 "into future targets.\n");
911 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000912 // Don't print out this warning for exception breakpoints. They can
913 // get set before the target is set, but we won't know how to actually
914 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000915 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
917 "actual locations.\n");
918 }
919 }
920 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000921 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922 result.AppendError("Breakpoint creation failed: No breakpoint created.");
923 result.SetStatus(eReturnStatusFailed);
924 }
925
926 return result.Succeeded();
927 }
928
Jim Ingham5a988412012-06-08 21:56:10 +0000929private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000930 bool GetDefaultFile(Target *target, FileSpec &file,
931 CommandReturnObject &result) {
932 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000933 // First use the Source Manager's default file. Then use the current stack
934 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000935 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
936 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
937 if (cur_frame == nullptr) {
938 result.AppendError(
939 "No selected frame to use to find the default file.");
940 result.SetStatus(eReturnStatusFailed);
941 return false;
942 } else if (!cur_frame->HasDebugInformation()) {
943 result.AppendError("Cannot use the selected frame to find the default "
944 "file, it has no debug info.");
945 result.SetStatus(eReturnStatusFailed);
946 return false;
947 } else {
948 const SymbolContext &sc =
949 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
950 if (sc.line_entry.file) {
951 file = sc.line_entry.file;
952 } else {
953 result.AppendError("Can't find the file for the selected frame to "
954 "use as the default file.");
955 result.SetStatus(eReturnStatusFailed);
956 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000957 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000958 }
Jim Ingham5a988412012-06-08 21:56:10 +0000959 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000960 return true;
961 }
962
Jim Inghamb842f2e2017-09-14 20:22:49 +0000963 BreakpointOptionGroup m_bp_opts;
964 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000965 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000966 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000967};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000968
Jim Ingham5a988412012-06-08 21:56:10 +0000969//-------------------------------------------------------------------------
970// CommandObjectBreakpointModify
971//-------------------------------------------------------------------------
972#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000973
Kate Stoneb9c1b512016-09-06 20:57:50 +0000974class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000975public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
977 : CommandObjectParsed(interpreter, "breakpoint modify",
978 "Modify the options on a breakpoint or set of "
979 "breakpoints in the executable. "
980 "If no breakpoint is specified, acts on the last "
981 "created breakpoint. "
982 "With the exception of -e, -d and -i, passing an "
983 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000984 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000985 m_options() {
986 CommandArgumentEntry arg;
987 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
988 eArgTypeBreakpointIDRange);
989 // Add the entry for the first argument for this command to the object's
990 // arguments vector.
991 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000992
993 m_options.Append(&m_bp_opts,
994 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
995 LLDB_OPT_SET_ALL);
996 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
997 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000998 }
999
1000 ~CommandObjectBreakpointModify() override = default;
1001
1002 Options *GetOptions() override { return &m_options; }
1003
Jim Ingham5a988412012-06-08 21:56:10 +00001004protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001005 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001006 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001007 if (target == nullptr) {
1008 result.AppendError("Invalid target. No existing target or breakpoints.");
1009 result.SetStatus(eReturnStatusFailed);
1010 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001011 }
1012
Kate Stoneb9c1b512016-09-06 20:57:50 +00001013 std::unique_lock<std::recursive_mutex> lock;
1014 target->GetBreakpointList().GetListMutex(lock);
1015
1016 BreakpointIDList valid_bp_ids;
1017
1018 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001019 command, target, result, &valid_bp_ids,
1020 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001021
1022 if (result.Succeeded()) {
1023 const size_t count = valid_bp_ids.GetSize();
1024 for (size_t i = 0; i < count; ++i) {
1025 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1026
1027 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1028 Breakpoint *bp =
1029 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1030 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1031 BreakpointLocation *location =
1032 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001033 if (location)
1034 location->GetLocationOptions()
1035 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001036 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001037 bp->GetOptions()
1038 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001039 }
1040 }
1041 }
1042 }
1043
1044 return result.Succeeded();
1045 }
1046
Jim Ingham5a988412012-06-08 21:56:10 +00001047private:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001048 BreakpointOptionGroup m_bp_opts;
1049 BreakpointDummyOptionGroup m_dummy_opts;
1050 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001051};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001052
Jim Ingham5a988412012-06-08 21:56:10 +00001053//-------------------------------------------------------------------------
1054// CommandObjectBreakpointEnable
1055//-------------------------------------------------------------------------
1056#pragma mark Enable
1057
Kate Stoneb9c1b512016-09-06 20:57:50 +00001058class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001059public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001060 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1061 : CommandObjectParsed(interpreter, "enable",
1062 "Enable the specified disabled breakpoint(s). If "
1063 "no breakpoints are specified, enable all of them.",
1064 nullptr) {
1065 CommandArgumentEntry arg;
1066 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1067 eArgTypeBreakpointIDRange);
1068 // Add the entry for the first argument for this command to the object's
1069 // arguments vector.
1070 m_arguments.push_back(arg);
1071 }
Jim Ingham5a988412012-06-08 21:56:10 +00001072
Kate Stoneb9c1b512016-09-06 20:57:50 +00001073 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001074
1075protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001076 bool DoExecute(Args &command, CommandReturnObject &result) override {
1077 Target *target = GetSelectedOrDummyTarget();
1078 if (target == nullptr) {
1079 result.AppendError("Invalid target. No existing target or breakpoints.");
1080 result.SetStatus(eReturnStatusFailed);
1081 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001082 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001083
1084 std::unique_lock<std::recursive_mutex> lock;
1085 target->GetBreakpointList().GetListMutex(lock);
1086
1087 const BreakpointList &breakpoints = target->GetBreakpointList();
1088
1089 size_t num_breakpoints = breakpoints.GetSize();
1090
1091 if (num_breakpoints == 0) {
1092 result.AppendError("No breakpoints exist to be enabled.");
1093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096
Zachary Turner11eb9c62016-10-05 20:03:37 +00001097 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001098 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001099 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001100 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1101 " breakpoints)\n",
1102 (uint64_t)num_breakpoints);
1103 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1104 } else {
1105 // Particular breakpoint selected; enable that breakpoint.
1106 BreakpointIDList valid_bp_ids;
1107 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001108 command, target, result, &valid_bp_ids,
1109 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001110
1111 if (result.Succeeded()) {
1112 int enable_count = 0;
1113 int loc_count = 0;
1114 const size_t count = valid_bp_ids.GetSize();
1115 for (size_t i = 0; i < count; ++i) {
1116 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1117
1118 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1119 Breakpoint *breakpoint =
1120 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1121 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1122 BreakpointLocation *location =
1123 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1124 if (location) {
1125 location->SetEnabled(true);
1126 ++loc_count;
1127 }
1128 } else {
1129 breakpoint->SetEnabled(true);
1130 ++enable_count;
1131 }
1132 }
1133 }
1134 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1135 enable_count + loc_count);
1136 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1137 }
1138 }
1139
1140 return result.Succeeded();
1141 }
Jim Ingham5a988412012-06-08 21:56:10 +00001142};
1143
1144//-------------------------------------------------------------------------
1145// CommandObjectBreakpointDisable
1146//-------------------------------------------------------------------------
1147#pragma mark Disable
1148
Kate Stoneb9c1b512016-09-06 20:57:50 +00001149class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001150public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001151 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1152 : CommandObjectParsed(
1153 interpreter, "breakpoint disable",
1154 "Disable the specified breakpoint(s) without deleting "
1155 "them. If none are specified, disable all "
1156 "breakpoints.",
1157 nullptr) {
1158 SetHelpLong(
1159 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001160If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001161 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001162
Kate Stone7428a182016-07-14 22:03:10 +00001163)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001164 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001165regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001167
1168 (lldb) break disable 1
1169 (lldb) break enable 1.1
1170
1171execution will NOT stop at location 1.1. To achieve that, type:
1172
1173 (lldb) break disable 1.*
1174 (lldb) break enable 1.1
1175
Kate Stone7428a182016-07-14 22:03:10 +00001176)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001177 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001178the second re-enables the first location.");
1179
Kate Stoneb9c1b512016-09-06 20:57:50 +00001180 CommandArgumentEntry arg;
1181 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1182 eArgTypeBreakpointIDRange);
1183 // Add the entry for the first argument for this command to the object's
1184 // arguments vector.
1185 m_arguments.push_back(arg);
1186 }
Jim Ingham5a988412012-06-08 21:56:10 +00001187
Kate Stoneb9c1b512016-09-06 20:57:50 +00001188 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001189
1190protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001191 bool DoExecute(Args &command, CommandReturnObject &result) override {
1192 Target *target = GetSelectedOrDummyTarget();
1193 if (target == nullptr) {
1194 result.AppendError("Invalid target. No existing target or breakpoints.");
1195 result.SetStatus(eReturnStatusFailed);
1196 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001197 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198
1199 std::unique_lock<std::recursive_mutex> lock;
1200 target->GetBreakpointList().GetListMutex(lock);
1201
1202 const BreakpointList &breakpoints = target->GetBreakpointList();
1203 size_t num_breakpoints = breakpoints.GetSize();
1204
1205 if (num_breakpoints == 0) {
1206 result.AppendError("No breakpoints exist to be disabled.");
1207 result.SetStatus(eReturnStatusFailed);
1208 return false;
1209 }
1210
Zachary Turner11eb9c62016-10-05 20:03:37 +00001211 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001212 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001213 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001214 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1215 " breakpoints)\n",
1216 (uint64_t)num_breakpoints);
1217 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1218 } else {
1219 // Particular breakpoint selected; disable that breakpoint.
1220 BreakpointIDList valid_bp_ids;
1221
1222 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001223 command, target, result, &valid_bp_ids,
1224 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001225
1226 if (result.Succeeded()) {
1227 int disable_count = 0;
1228 int loc_count = 0;
1229 const size_t count = valid_bp_ids.GetSize();
1230 for (size_t i = 0; i < count; ++i) {
1231 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1232
1233 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1234 Breakpoint *breakpoint =
1235 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1236 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1237 BreakpointLocation *location =
1238 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1239 if (location) {
1240 location->SetEnabled(false);
1241 ++loc_count;
1242 }
1243 } else {
1244 breakpoint->SetEnabled(false);
1245 ++disable_count;
1246 }
1247 }
1248 }
1249 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1250 disable_count + loc_count);
1251 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1252 }
1253 }
1254
1255 return result.Succeeded();
1256 }
Jim Ingham5a988412012-06-08 21:56:10 +00001257};
1258
1259//-------------------------------------------------------------------------
1260// CommandObjectBreakpointList
1261//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001262
1263#pragma mark List::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001264static constexpr OptionDefinition g_breakpoint_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001265 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001266 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1267 { 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 +00001268 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1269 // But I need to see it for now, and don't want to wait.
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001270 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1271 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1272 { 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 +00001273 // clang-format on
1274};
1275
Jim Ingham5a988412012-06-08 21:56:10 +00001276#pragma mark List
1277
Kate Stoneb9c1b512016-09-06 20:57:50 +00001278class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001279public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001280 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1281 : CommandObjectParsed(
1282 interpreter, "breakpoint list",
1283 "List some or all breakpoints at configurable levels of detail.",
1284 nullptr),
1285 m_options() {
1286 CommandArgumentEntry arg;
1287 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001288
Kate Stoneb9c1b512016-09-06 20:57:50 +00001289 // Define the first (and only) variant of this arg.
1290 bp_id_arg.arg_type = eArgTypeBreakpointID;
1291 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001292
Kate Stoneb9c1b512016-09-06 20:57:50 +00001293 // There is only one variant this argument could be; put it into the
1294 // argument entry.
1295 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001296
Kate Stoneb9c1b512016-09-06 20:57:50 +00001297 // Push the data for the first argument into the m_arguments vector.
1298 m_arguments.push_back(arg);
1299 }
1300
1301 ~CommandObjectBreakpointList() override = default;
1302
1303 Options *GetOptions() override { return &m_options; }
1304
1305 class CommandOptions : public Options {
1306 public:
1307 CommandOptions()
1308 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001309 }
1310
Kate Stoneb9c1b512016-09-06 20:57:50 +00001311 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001312
Zachary Turner97206d52017-05-12 04:51:55 +00001313 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1314 ExecutionContext *execution_context) override {
1315 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001316 const int short_option = m_getopt_table[option_idx].val;
1317
1318 switch (short_option) {
1319 case 'b':
1320 m_level = lldb::eDescriptionLevelBrief;
1321 break;
1322 case 'D':
1323 m_use_dummy = true;
1324 break;
1325 case 'f':
1326 m_level = lldb::eDescriptionLevelFull;
1327 break;
1328 case 'v':
1329 m_level = lldb::eDescriptionLevelVerbose;
1330 break;
1331 case 'i':
1332 m_internal = true;
1333 break;
1334 default:
1335 error.SetErrorStringWithFormat("unrecognized option '%c'",
1336 short_option);
1337 break;
1338 }
1339
1340 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001341 }
Jim Ingham5a988412012-06-08 21:56:10 +00001342
Kate Stoneb9c1b512016-09-06 20:57:50 +00001343 void OptionParsingStarting(ExecutionContext *execution_context) override {
1344 m_level = lldb::eDescriptionLevelFull;
1345 m_internal = false;
1346 m_use_dummy = false;
1347 }
Jim Ingham5a988412012-06-08 21:56:10 +00001348
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001349 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001350 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001351 }
Jim Ingham5a988412012-06-08 21:56:10 +00001352
Kate Stoneb9c1b512016-09-06 20:57:50 +00001353 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001354
Kate Stoneb9c1b512016-09-06 20:57:50 +00001355 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001356
Kate Stoneb9c1b512016-09-06 20:57:50 +00001357 bool m_internal;
1358 bool m_use_dummy;
1359 };
Jim Ingham5a988412012-06-08 21:56:10 +00001360
1361protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001362 bool DoExecute(Args &command, CommandReturnObject &result) override {
1363 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001364
Kate Stoneb9c1b512016-09-06 20:57:50 +00001365 if (target == nullptr) {
1366 result.AppendError("Invalid target. No current target or breakpoints.");
1367 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1368 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001369 }
1370
Kate Stoneb9c1b512016-09-06 20:57:50 +00001371 const BreakpointList &breakpoints =
1372 target->GetBreakpointList(m_options.m_internal);
1373 std::unique_lock<std::recursive_mutex> lock;
1374 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1375
1376 size_t num_breakpoints = breakpoints.GetSize();
1377
1378 if (num_breakpoints == 0) {
1379 result.AppendMessage("No breakpoints currently set.");
1380 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1381 return true;
1382 }
1383
1384 Stream &output_stream = result.GetOutputStream();
1385
Zachary Turner11eb9c62016-10-05 20:03:37 +00001386 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001387 // No breakpoint selected; show info about all currently set breakpoints.
1388 result.AppendMessage("Current breakpoints:");
1389 for (size_t i = 0; i < num_breakpoints; ++i) {
1390 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001391 if (breakpoint->AllowList())
1392 AddBreakpointDescription(&output_stream, breakpoint,
1393 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001394 }
1395 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1396 } else {
1397 // Particular breakpoints selected; show info about that breakpoint.
1398 BreakpointIDList valid_bp_ids;
1399 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001400 command, target, result, &valid_bp_ids,
1401 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001402
1403 if (result.Succeeded()) {
1404 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1405 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1406 Breakpoint *breakpoint =
1407 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1408 AddBreakpointDescription(&output_stream, breakpoint,
1409 m_options.m_level);
1410 }
1411 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1412 } else {
1413 result.AppendError("Invalid breakpoint ID.");
1414 result.SetStatus(eReturnStatusFailed);
1415 }
1416 }
1417
1418 return result.Succeeded();
1419 }
1420
Jim Ingham5a988412012-06-08 21:56:10 +00001421private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001422 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001423};
1424
Jim Ingham5a988412012-06-08 21:56:10 +00001425//-------------------------------------------------------------------------
1426// CommandObjectBreakpointClear
1427//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001428#pragma mark Clear::CommandOptions
1429
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001430static constexpr OptionDefinition g_breakpoint_clear_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001431 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001432 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1433 { 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 +00001434 // clang-format on
1435};
1436
Jim Ingham5a988412012-06-08 21:56:10 +00001437#pragma mark Clear
1438
Kate Stoneb9c1b512016-09-06 20:57:50 +00001439class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001440public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001441 typedef enum BreakpointClearType {
1442 eClearTypeInvalid,
1443 eClearTypeFileAndLine
1444 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001445
Kate Stoneb9c1b512016-09-06 20:57:50 +00001446 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1447 : CommandObjectParsed(interpreter, "breakpoint clear",
1448 "Delete or disable breakpoints matching the "
1449 "specified source file and line.",
1450 "breakpoint clear <cmd-options>"),
1451 m_options() {}
1452
1453 ~CommandObjectBreakpointClear() override = default;
1454
1455 Options *GetOptions() override { return &m_options; }
1456
1457 class CommandOptions : public Options {
1458 public:
1459 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1460
1461 ~CommandOptions() override = default;
1462
Zachary Turner97206d52017-05-12 04:51:55 +00001463 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1464 ExecutionContext *execution_context) override {
1465 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001466 const int short_option = m_getopt_table[option_idx].val;
1467
1468 switch (short_option) {
1469 case 'f':
1470 m_filename.assign(option_arg);
1471 break;
1472
1473 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001474 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001475 break;
1476
1477 default:
1478 error.SetErrorStringWithFormat("unrecognized option '%c'",
1479 short_option);
1480 break;
1481 }
1482
1483 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001484 }
1485
Kate Stoneb9c1b512016-09-06 20:57:50 +00001486 void OptionParsingStarting(ExecutionContext *execution_context) override {
1487 m_filename.clear();
1488 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001489 }
1490
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001491 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001492 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001493 }
Jim Ingham5a988412012-06-08 21:56:10 +00001494
Kate Stoneb9c1b512016-09-06 20:57:50 +00001495 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001496
Kate Stoneb9c1b512016-09-06 20:57:50 +00001497 std::string m_filename;
1498 uint32_t m_line_num;
1499 };
Jim Ingham5a988412012-06-08 21:56:10 +00001500
1501protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001502 bool DoExecute(Args &command, CommandReturnObject &result) override {
1503 Target *target = GetSelectedOrDummyTarget();
1504 if (target == nullptr) {
1505 result.AppendError("Invalid target. No existing target or breakpoints.");
1506 result.SetStatus(eReturnStatusFailed);
1507 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001508 }
1509
Adrian Prantl05097242018-04-30 16:49:04 +00001510 // The following are the various types of breakpoints that could be
1511 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001512 // 1). -f -l (clearing breakpoint by source location)
1513
1514 BreakpointClearType break_type = eClearTypeInvalid;
1515
1516 if (m_options.m_line_num != 0)
1517 break_type = eClearTypeFileAndLine;
1518
1519 std::unique_lock<std::recursive_mutex> lock;
1520 target->GetBreakpointList().GetListMutex(lock);
1521
1522 BreakpointList &breakpoints = target->GetBreakpointList();
1523 size_t num_breakpoints = breakpoints.GetSize();
1524
1525 // Early return if there's no breakpoint at all.
1526 if (num_breakpoints == 0) {
1527 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1528 result.SetStatus(eReturnStatusFailed);
1529 return result.Succeeded();
1530 }
1531
1532 // Find matching breakpoints and delete them.
1533
1534 // First create a copy of all the IDs.
1535 std::vector<break_id_t> BreakIDs;
1536 for (size_t i = 0; i < num_breakpoints; ++i)
1537 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1538
1539 int num_cleared = 0;
1540 StreamString ss;
1541 switch (break_type) {
1542 case eClearTypeFileAndLine: // Breakpoint by source position
1543 {
1544 const ConstString filename(m_options.m_filename.c_str());
1545 BreakpointLocationCollection loc_coll;
1546
1547 for (size_t i = 0; i < num_breakpoints; ++i) {
1548 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1549
1550 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1551 // If the collection size is 0, it's a full match and we can just
1552 // remove the breakpoint.
1553 if (loc_coll.GetSize() == 0) {
1554 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1555 ss.EOL();
1556 target->RemoveBreakpointByID(bp->GetID());
1557 ++num_cleared;
1558 }
1559 }
1560 }
1561 } break;
1562
1563 default:
1564 break;
1565 }
1566
1567 if (num_cleared > 0) {
1568 Stream &output_stream = result.GetOutputStream();
1569 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001570 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001571 output_stream.EOL();
1572 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1573 } else {
1574 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1575 result.SetStatus(eReturnStatusFailed);
1576 }
1577
1578 return result.Succeeded();
1579 }
1580
Jim Ingham5a988412012-06-08 21:56:10 +00001581private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001582 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001583};
1584
Jim Ingham5a988412012-06-08 21:56:10 +00001585//-------------------------------------------------------------------------
1586// CommandObjectBreakpointDelete
1587//-------------------------------------------------------------------------
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001588static constexpr OptionDefinition g_breakpoint_delete_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001589 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001590 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1591 { 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 +00001592 // clang-format on
1593};
1594
Jim Ingham5a988412012-06-08 21:56:10 +00001595#pragma mark Delete
1596
Kate Stoneb9c1b512016-09-06 20:57:50 +00001597class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001598public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001599 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1600 : CommandObjectParsed(interpreter, "breakpoint delete",
1601 "Delete the specified breakpoint(s). If no "
1602 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001603 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001604 m_options() {
1605 CommandArgumentEntry arg;
1606 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1607 eArgTypeBreakpointIDRange);
1608 // Add the entry for the first argument for this command to the object's
1609 // arguments vector.
1610 m_arguments.push_back(arg);
1611 }
1612
1613 ~CommandObjectBreakpointDelete() override = default;
1614
1615 Options *GetOptions() override { return &m_options; }
1616
1617 class CommandOptions : public Options {
1618 public:
1619 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1620
1621 ~CommandOptions() override = default;
1622
Zachary Turner97206d52017-05-12 04:51:55 +00001623 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1624 ExecutionContext *execution_context) override {
1625 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001626 const int short_option = m_getopt_table[option_idx].val;
1627
1628 switch (short_option) {
1629 case 'f':
1630 m_force = true;
1631 break;
1632
1633 case 'D':
1634 m_use_dummy = true;
1635 break;
1636
1637 default:
1638 error.SetErrorStringWithFormat("unrecognized option '%c'",
1639 short_option);
1640 break;
1641 }
1642
1643 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001644 }
1645
Kate Stoneb9c1b512016-09-06 20:57:50 +00001646 void OptionParsingStarting(ExecutionContext *execution_context) override {
1647 m_use_dummy = false;
1648 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001649 }
1650
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001651 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001652 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001653 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001654
Kate Stoneb9c1b512016-09-06 20:57:50 +00001655 // Instance variables to hold the values for command options.
1656 bool m_use_dummy;
1657 bool m_force;
1658 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001659
Jim Ingham5a988412012-06-08 21:56:10 +00001660protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001661 bool DoExecute(Args &command, CommandReturnObject &result) override {
1662 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001663
Kate Stoneb9c1b512016-09-06 20:57:50 +00001664 if (target == nullptr) {
1665 result.AppendError("Invalid target. No existing target or breakpoints.");
1666 result.SetStatus(eReturnStatusFailed);
1667 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001668 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001669
Kate Stoneb9c1b512016-09-06 20:57:50 +00001670 std::unique_lock<std::recursive_mutex> lock;
1671 target->GetBreakpointList().GetListMutex(lock);
1672
1673 const BreakpointList &breakpoints = target->GetBreakpointList();
1674
1675 size_t num_breakpoints = breakpoints.GetSize();
1676
1677 if (num_breakpoints == 0) {
1678 result.AppendError("No breakpoints exist to be deleted.");
1679 result.SetStatus(eReturnStatusFailed);
1680 return false;
1681 }
1682
Zachary Turner11eb9c62016-10-05 20:03:37 +00001683 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001684 if (!m_options.m_force &&
1685 !m_interpreter.Confirm(
1686 "About to delete all breakpoints, do you want to do that?",
1687 true)) {
1688 result.AppendMessage("Operation cancelled...");
1689 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001690 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001691 result.AppendMessageWithFormat(
1692 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1693 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1694 }
1695 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1696 } else {
1697 // Particular breakpoint selected; disable that breakpoint.
1698 BreakpointIDList valid_bp_ids;
1699 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001700 command, target, result, &valid_bp_ids,
1701 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001702
1703 if (result.Succeeded()) {
1704 int delete_count = 0;
1705 int disable_count = 0;
1706 const size_t count = valid_bp_ids.GetSize();
1707 for (size_t i = 0; i < count; ++i) {
1708 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1709
1710 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1711 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1712 Breakpoint *breakpoint =
1713 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1714 BreakpointLocation *location =
1715 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1716 // It makes no sense to try to delete individual locations, so we
1717 // disable them instead.
1718 if (location) {
1719 location->SetEnabled(false);
1720 ++disable_count;
1721 }
1722 } else {
1723 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1724 ++delete_count;
1725 }
1726 }
1727 }
1728 result.AppendMessageWithFormat(
1729 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1730 delete_count, disable_count);
1731 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1732 }
1733 }
1734 return result.Succeeded();
1735 }
1736
Jim Ingham33df7cd2014-12-06 01:28:03 +00001737private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001738 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001739};
1740
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001741//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001742// CommandObjectBreakpointName
1743//-------------------------------------------------------------------------
1744
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001745static constexpr OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001746 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001747 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1748 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1749 {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."},
1750 {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 +00001751 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001752};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001753class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001754public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001755 BreakpointNameOptionGroup()
1756 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1757 }
1758
1759 ~BreakpointNameOptionGroup() override = default;
1760
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001761 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001762 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001763 }
1764
Zachary Turner97206d52017-05-12 04:51:55 +00001765 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1766 ExecutionContext *execution_context) override {
1767 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001768 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1769
1770 switch (short_option) {
1771 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001772 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001773 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001774 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001775 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001776 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001777 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001778 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001779 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001780 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001781 break;
1782 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001783 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001784 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001785 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001786 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001787 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001788 case 'H':
1789 m_help_string.SetValueFromString(option_arg);
1790 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001791
1792 default:
1793 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1794 short_option);
1795 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001796 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001797 return error;
1798 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001799
Kate Stoneb9c1b512016-09-06 20:57:50 +00001800 void OptionParsingStarting(ExecutionContext *execution_context) override {
1801 m_name.Clear();
1802 m_breakpoint.Clear();
1803 m_use_dummy.Clear();
1804 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001805 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001806 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001807
Kate Stoneb9c1b512016-09-06 20:57:50 +00001808 OptionValueString m_name;
1809 OptionValueUInt64 m_breakpoint;
1810 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001811 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001812};
1813
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001814static constexpr OptionDefinition g_breakpoint_access_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001815 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001816 {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."},
1817 {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."},
1818 {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 +00001819 // clang-format on
1820};
1821
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001822class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001823public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001824 BreakpointAccessOptionGroup() : OptionGroup() {}
1825
Jim Inghamb842f2e2017-09-14 20:22:49 +00001826 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001827
Jim Inghamb842f2e2017-09-14 20:22:49 +00001828 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1829 return llvm::makeArrayRef(g_breakpoint_access_options);
1830 }
1831 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1832 ExecutionContext *execution_context) override {
1833 Status error;
1834 const int short_option
1835 = g_breakpoint_access_options[option_idx].short_option;
1836
1837 switch (short_option) {
1838 case 'L': {
1839 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001840 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001841 if (success) {
1842 m_permissions.SetAllowList(value);
1843 } else
1844 error.SetErrorStringWithFormat(
1845 "invalid boolean value '%s' passed for -L option",
1846 option_arg.str().c_str());
1847 } break;
1848 case 'A': {
1849 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001850 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001851 if (success) {
1852 m_permissions.SetAllowDisable(value);
1853 } else
1854 error.SetErrorStringWithFormat(
1855 "invalid boolean value '%s' passed for -L option",
1856 option_arg.str().c_str());
1857 } break;
1858 case 'D': {
1859 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001860 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001861 if (success) {
1862 m_permissions.SetAllowDelete(value);
1863 } else
1864 error.SetErrorStringWithFormat(
1865 "invalid boolean value '%s' passed for -L option",
1866 option_arg.str().c_str());
1867 } break;
1868
1869 }
1870
1871 return error;
1872 }
1873
1874 void OptionParsingStarting(ExecutionContext *execution_context) override {
1875 }
1876
1877 const BreakpointName::Permissions &GetPermissions() const
1878 {
1879 return m_permissions;
1880 }
1881 BreakpointName::Permissions m_permissions;
1882};
1883
1884class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1885public:
1886 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1887 : CommandObjectParsed(
1888 interpreter, "configure", "Configure the options for the breakpoint"
1889 " name provided. "
1890 "If you provide a breakpoint id, the options will be copied from "
1891 "the breakpoint, otherwise only the options specified will be set "
1892 "on the name.",
1893 "breakpoint name configure <command-options> "
1894 "<breakpoint-name-list>"),
1895 m_bp_opts(), m_option_group() {
1896 // Create the first variant for the first (and only) argument for this
1897 // command.
1898 CommandArgumentEntry arg1;
1899 CommandArgumentData id_arg;
1900 id_arg.arg_type = eArgTypeBreakpointName;
1901 id_arg.arg_repetition = eArgRepeatOptional;
1902 arg1.push_back(id_arg);
1903 m_arguments.push_back(arg1);
1904
1905 m_option_group.Append(&m_bp_opts,
1906 LLDB_OPT_SET_ALL,
1907 LLDB_OPT_SET_1);
1908 m_option_group.Append(&m_access_options,
1909 LLDB_OPT_SET_ALL,
1910 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001911 m_option_group.Append(&m_bp_id,
1912 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1913 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001914 m_option_group.Finalize();
1915 }
1916
1917 ~CommandObjectBreakpointNameConfigure() override = default;
1918
1919 Options *GetOptions() override { return &m_option_group; }
1920
1921protected:
1922 bool DoExecute(Args &command, CommandReturnObject &result) override {
1923
1924 const size_t argc = command.GetArgumentCount();
1925 if (argc == 0) {
1926 result.AppendError("No names provided.");
1927 result.SetStatus(eReturnStatusFailed);
1928 return false;
1929 }
1930
1931 Target *target =
1932 GetSelectedOrDummyTarget(false);
1933
1934 if (target == nullptr) {
1935 result.AppendError("Invalid target. No existing target or breakpoints.");
1936 result.SetStatus(eReturnStatusFailed);
1937 return false;
1938 }
1939
1940 std::unique_lock<std::recursive_mutex> lock;
1941 target->GetBreakpointList().GetListMutex(lock);
1942
1943 // Make a pass through first to see that all the names are legal.
1944 for (auto &entry : command.entries()) {
1945 Status error;
1946 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1947 {
1948 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1949 entry.c_str(), error.AsCString());
1950 result.SetStatus(eReturnStatusFailed);
1951 return false;
1952 }
1953 }
Adrian Prantl05097242018-04-30 16:49:04 +00001954 // Now configure them, we already pre-checked the names so we don't need to
1955 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001956 BreakpointSP bp_sp;
1957 if (m_bp_id.m_breakpoint.OptionWasSet())
1958 {
1959 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1960 bp_sp = target->GetBreakpointByID(bp_id);
1961 if (!bp_sp)
1962 {
1963 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1964 bp_id);
1965 result.SetStatus(eReturnStatusFailed);
1966 return false;
1967 }
1968 }
1969
1970 Status error;
1971 for (auto &entry : command.entries()) {
1972 ConstString name(entry.c_str());
1973 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1974 if (!bp_name)
1975 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001976 if (m_bp_id.m_help_string.OptionWasSet())
1977 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1978
Jim Inghamb842f2e2017-09-14 20:22:49 +00001979 if (bp_sp)
1980 target->ConfigureBreakpointName(*bp_name,
1981 *bp_sp->GetOptions(),
1982 m_access_options.GetPermissions());
1983 else
1984 target->ConfigureBreakpointName(*bp_name,
1985 m_bp_opts.GetBreakpointOptions(),
1986 m_access_options.GetPermissions());
1987 }
1988 return true;
1989 }
1990
1991private:
1992 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1993 BreakpointOptionGroup m_bp_opts;
1994 BreakpointAccessOptionGroup m_access_options;
1995 OptionGroupOptions m_option_group;
1996};
1997
Kate Stoneb9c1b512016-09-06 20:57:50 +00001998class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001999public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002000 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
2001 : CommandObjectParsed(
2002 interpreter, "add", "Add a name to the breakpoints provided.",
2003 "breakpoint name add <command-options> <breakpoint-id-list>"),
2004 m_name_options(), m_option_group() {
2005 // Create the first variant for the first (and only) argument for this
2006 // command.
2007 CommandArgumentEntry arg1;
2008 CommandArgumentData id_arg;
2009 id_arg.arg_type = eArgTypeBreakpointID;
2010 id_arg.arg_repetition = eArgRepeatOptional;
2011 arg1.push_back(id_arg);
2012 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002013
Kate Stoneb9c1b512016-09-06 20:57:50 +00002014 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2015 m_option_group.Finalize();
2016 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002017
Kate Stoneb9c1b512016-09-06 20:57:50 +00002018 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002019
Kate Stoneb9c1b512016-09-06 20:57:50 +00002020 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002021
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002022protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002023 bool DoExecute(Args &command, CommandReturnObject &result) override {
2024 if (!m_name_options.m_name.OptionWasSet()) {
2025 result.SetError("No name option provided.");
2026 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002027 }
2028
Kate Stoneb9c1b512016-09-06 20:57:50 +00002029 Target *target =
2030 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2031
2032 if (target == nullptr) {
2033 result.AppendError("Invalid target. No existing target or breakpoints.");
2034 result.SetStatus(eReturnStatusFailed);
2035 return false;
2036 }
2037
2038 std::unique_lock<std::recursive_mutex> lock;
2039 target->GetBreakpointList().GetListMutex(lock);
2040
2041 const BreakpointList &breakpoints = target->GetBreakpointList();
2042
2043 size_t num_breakpoints = breakpoints.GetSize();
2044 if (num_breakpoints == 0) {
2045 result.SetError("No breakpoints, cannot add names.");
2046 result.SetStatus(eReturnStatusFailed);
2047 return false;
2048 }
2049
2050 // Particular breakpoint selected; disable that breakpoint.
2051 BreakpointIDList valid_bp_ids;
2052 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002053 command, target, result, &valid_bp_ids,
2054 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002055
2056 if (result.Succeeded()) {
2057 if (valid_bp_ids.GetSize() == 0) {
2058 result.SetError("No breakpoints specified, cannot add names.");
2059 result.SetStatus(eReturnStatusFailed);
2060 return false;
2061 }
2062 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00002063 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2064 Status error; // This error reports illegal names, but we've already
2065 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002066 for (size_t index = 0; index < num_valid_ids; index++) {
2067 lldb::break_id_t bp_id =
2068 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2069 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002070 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002071 }
2072 }
2073
2074 return true;
2075 }
2076
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002077private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002078 BreakpointNameOptionGroup m_name_options;
2079 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002080};
2081
Kate Stoneb9c1b512016-09-06 20:57:50 +00002082class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002083public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002084 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2085 : CommandObjectParsed(
2086 interpreter, "delete",
2087 "Delete a name from the breakpoints provided.",
2088 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2089 m_name_options(), m_option_group() {
2090 // Create the first variant for the first (and only) argument for this
2091 // command.
2092 CommandArgumentEntry arg1;
2093 CommandArgumentData id_arg;
2094 id_arg.arg_type = eArgTypeBreakpointID;
2095 id_arg.arg_repetition = eArgRepeatOptional;
2096 arg1.push_back(id_arg);
2097 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002098
Kate Stoneb9c1b512016-09-06 20:57:50 +00002099 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2100 m_option_group.Finalize();
2101 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002102
Kate Stoneb9c1b512016-09-06 20:57:50 +00002103 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002104
Kate Stoneb9c1b512016-09-06 20:57:50 +00002105 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002106
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002107protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002108 bool DoExecute(Args &command, CommandReturnObject &result) override {
2109 if (!m_name_options.m_name.OptionWasSet()) {
2110 result.SetError("No name option provided.");
2111 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002112 }
2113
Kate Stoneb9c1b512016-09-06 20:57:50 +00002114 Target *target =
2115 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2116
2117 if (target == nullptr) {
2118 result.AppendError("Invalid target. No existing target or breakpoints.");
2119 result.SetStatus(eReturnStatusFailed);
2120 return false;
2121 }
2122
2123 std::unique_lock<std::recursive_mutex> lock;
2124 target->GetBreakpointList().GetListMutex(lock);
2125
2126 const BreakpointList &breakpoints = target->GetBreakpointList();
2127
2128 size_t num_breakpoints = breakpoints.GetSize();
2129 if (num_breakpoints == 0) {
2130 result.SetError("No breakpoints, cannot delete names.");
2131 result.SetStatus(eReturnStatusFailed);
2132 return false;
2133 }
2134
2135 // Particular breakpoint selected; disable that breakpoint.
2136 BreakpointIDList valid_bp_ids;
2137 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002138 command, target, result, &valid_bp_ids,
2139 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002140
2141 if (result.Succeeded()) {
2142 if (valid_bp_ids.GetSize() == 0) {
2143 result.SetError("No breakpoints specified, cannot delete names.");
2144 result.SetStatus(eReturnStatusFailed);
2145 return false;
2146 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002147 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002148 size_t num_valid_ids = valid_bp_ids.GetSize();
2149 for (size_t index = 0; index < num_valid_ids; index++) {
2150 lldb::break_id_t bp_id =
2151 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2152 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002153 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002154 }
2155 }
2156
2157 return true;
2158 }
2159
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002160private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002161 BreakpointNameOptionGroup m_name_options;
2162 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002163};
2164
Kate Stoneb9c1b512016-09-06 20:57:50 +00002165class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002166public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002167 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2168 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002169 "List either the names for a breakpoint or info "
2170 "about a given name. With no arguments, lists all "
2171 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002172 "breakpoint name list <command-options>"),
2173 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002174 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002175 m_option_group.Finalize();
2176 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002177
Kate Stoneb9c1b512016-09-06 20:57:50 +00002178 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002179
Kate Stoneb9c1b512016-09-06 20:57:50 +00002180 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002181
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002182protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002183 bool DoExecute(Args &command, CommandReturnObject &result) override {
2184 Target *target =
2185 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002186
Kate Stoneb9c1b512016-09-06 20:57:50 +00002187 if (target == nullptr) {
2188 result.AppendError("Invalid target. No existing target or breakpoints.");
2189 result.SetStatus(eReturnStatusFailed);
2190 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002191 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002192
2193
2194 std::vector<std::string> name_list;
2195 if (command.empty()) {
2196 target->GetBreakpointNames(name_list);
2197 } else {
2198 for (const Args::ArgEntry &arg : command)
2199 {
2200 name_list.push_back(arg.c_str());
2201 }
2202 }
2203
2204 if (name_list.empty()) {
2205 result.AppendMessage("No breakpoint names found.");
2206 } else {
2207 for (const std::string &name_str : name_list) {
2208 const char *name = name_str.c_str();
2209 // First print out the options for the name:
2210 Status error;
2211 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2212 false,
2213 error);
2214 if (bp_name)
2215 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002216 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002217 result.AppendMessageWithFormat("Name: %s\n", name);
2218 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2219 {
2220 result.AppendMessage(s.GetString());
2221 }
2222
2223 std::unique_lock<std::recursive_mutex> lock;
2224 target->GetBreakpointList().GetListMutex(lock);
2225
2226 BreakpointList &breakpoints = target->GetBreakpointList();
2227 bool any_set = false;
2228 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2229 if (bp_sp->MatchesName(name)) {
2230 StreamString s;
2231 any_set = true;
2232 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2233 s.EOL();
2234 result.AppendMessage(s.GetString());
2235 }
2236 }
2237 if (!any_set)
2238 result.AppendMessage("No breakpoints using this name.");
2239 } else {
2240 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002241 }
2242 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002243 }
2244 return true;
2245 }
2246
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002247private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002248 BreakpointNameOptionGroup m_name_options;
2249 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002250};
2251
2252//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002253// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002254//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002255class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002256public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002257 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2258 : CommandObjectMultiword(
2259 interpreter, "name", "Commands to manage name tags for breakpoints",
2260 "breakpoint name <subcommand> [<command-options>]") {
2261 CommandObjectSP add_command_object(
2262 new CommandObjectBreakpointNameAdd(interpreter));
2263 CommandObjectSP delete_command_object(
2264 new CommandObjectBreakpointNameDelete(interpreter));
2265 CommandObjectSP list_command_object(
2266 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002267 CommandObjectSP configure_command_object(
2268 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002269
Kate Stoneb9c1b512016-09-06 20:57:50 +00002270 LoadSubCommand("add", add_command_object);
2271 LoadSubCommand("delete", delete_command_object);
2272 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002273 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002274 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002275
Kate Stoneb9c1b512016-09-06 20:57:50 +00002276 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002277};
2278
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002279//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002280// CommandObjectBreakpointRead
2281//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002282#pragma mark Read::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002283static constexpr OptionDefinition g_breakpoint_read_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002284 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002285 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2286 {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 +00002287 // clang-format on
2288};
2289
2290#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002291
2292class CommandObjectBreakpointRead : public CommandObjectParsed {
2293public:
2294 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2295 : CommandObjectParsed(interpreter, "breakpoint read",
2296 "Read and set the breakpoints previously saved to "
2297 "a file with \"breakpoint write\". ",
2298 nullptr),
2299 m_options() {
2300 CommandArgumentEntry arg;
2301 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2302 eArgTypeBreakpointIDRange);
2303 // Add the entry for the first argument for this command to the object's
2304 // arguments vector.
2305 m_arguments.push_back(arg);
2306 }
2307
2308 ~CommandObjectBreakpointRead() override = default;
2309
2310 Options *GetOptions() override { return &m_options; }
2311
2312 class CommandOptions : public Options {
2313 public:
2314 CommandOptions() : Options() {}
2315
2316 ~CommandOptions() override = default;
2317
Zachary Turner97206d52017-05-12 04:51:55 +00002318 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2319 ExecutionContext *execution_context) override {
2320 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002321 const int short_option = m_getopt_table[option_idx].val;
2322
2323 switch (short_option) {
2324 case 'f':
2325 m_filename.assign(option_arg);
2326 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002327 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002328 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002329 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2330 name_error)) {
2331 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2332 name_error.AsCString());
2333 }
2334 m_names.push_back(option_arg);
2335 break;
2336 }
Jim Inghame14dc262016-09-12 23:10:56 +00002337 default:
2338 error.SetErrorStringWithFormat("unrecognized option '%c'",
2339 short_option);
2340 break;
2341 }
2342
2343 return error;
2344 }
2345
2346 void OptionParsingStarting(ExecutionContext *execution_context) override {
2347 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002348 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002349 }
2350
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002351 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002352 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002353 }
Jim Inghame14dc262016-09-12 23:10:56 +00002354
2355 // Instance variables to hold the values for command options.
2356
2357 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002358 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002359 };
2360
2361protected:
2362 bool DoExecute(Args &command, CommandReturnObject &result) override {
2363 Target *target = GetSelectedOrDummyTarget();
2364 if (target == nullptr) {
2365 result.AppendError("Invalid target. No existing target or breakpoints.");
2366 result.SetStatus(eReturnStatusFailed);
2367 return false;
2368 }
2369
Jim Ingham3acdf382016-09-22 22:20:28 +00002370 std::unique_lock<std::recursive_mutex> lock;
2371 target->GetBreakpointList().GetListMutex(lock);
2372
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002373 FileSpec input_spec(m_options.m_filename);
2374 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002375 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002376 Status error = target->CreateBreakpointsFromFile(
2377 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002378
Jim Inghame14dc262016-09-12 23:10:56 +00002379 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002380 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002381 result.SetStatus(eReturnStatusFailed);
2382 return false;
2383 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002384
2385 Stream &output_stream = result.GetOutputStream();
2386
2387 size_t num_breakpoints = new_bps.GetSize();
2388 if (num_breakpoints == 0) {
2389 result.AppendMessage("No breakpoints added.");
2390 } else {
2391 // No breakpoint selected; show info about all currently set breakpoints.
2392 result.AppendMessage("New breakpoints:");
2393 for (size_t i = 0; i < num_breakpoints; ++i) {
2394 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2395 Breakpoint *bp = target->GetBreakpointList()
2396 .FindBreakpointByID(bp_id.GetBreakpointID())
2397 .get();
2398 if (bp)
2399 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2400 false);
2401 }
2402 }
Jim Inghame14dc262016-09-12 23:10:56 +00002403 return result.Succeeded();
2404 }
2405
2406private:
2407 CommandOptions m_options;
2408};
2409
Jim Inghame14dc262016-09-12 23:10:56 +00002410//-------------------------------------------------------------------------
2411// CommandObjectBreakpointWrite
2412//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002413#pragma mark Write::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002414static constexpr OptionDefinition g_breakpoint_write_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002415 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002416 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2417 { 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 +00002418 // clang-format on
2419};
2420
2421#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002422class CommandObjectBreakpointWrite : public CommandObjectParsed {
2423public:
2424 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2425 : CommandObjectParsed(interpreter, "breakpoint write",
2426 "Write the breakpoints listed to a file that can "
2427 "be read in with \"breakpoint read\". "
2428 "If given no arguments, writes all breakpoints.",
2429 nullptr),
2430 m_options() {
2431 CommandArgumentEntry arg;
2432 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2433 eArgTypeBreakpointIDRange);
2434 // Add the entry for the first argument for this command to the object's
2435 // arguments vector.
2436 m_arguments.push_back(arg);
2437 }
2438
2439 ~CommandObjectBreakpointWrite() override = default;
2440
2441 Options *GetOptions() override { return &m_options; }
2442
2443 class CommandOptions : public Options {
2444 public:
2445 CommandOptions() : Options() {}
2446
2447 ~CommandOptions() override = default;
2448
Zachary Turner97206d52017-05-12 04:51:55 +00002449 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2450 ExecutionContext *execution_context) override {
2451 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002452 const int short_option = m_getopt_table[option_idx].val;
2453
2454 switch (short_option) {
2455 case 'f':
2456 m_filename.assign(option_arg);
2457 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002458 case 'a':
2459 m_append = true;
2460 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002461 default:
2462 error.SetErrorStringWithFormat("unrecognized option '%c'",
2463 short_option);
2464 break;
2465 }
2466
2467 return error;
2468 }
2469
2470 void OptionParsingStarting(ExecutionContext *execution_context) override {
2471 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002472 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002473 }
2474
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002475 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002476 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002477 }
Jim Inghame14dc262016-09-12 23:10:56 +00002478
2479 // Instance variables to hold the values for command options.
2480
2481 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002482 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002483 };
2484
2485protected:
2486 bool DoExecute(Args &command, CommandReturnObject &result) override {
2487 Target *target = GetSelectedOrDummyTarget();
2488 if (target == nullptr) {
2489 result.AppendError("Invalid target. No existing target or breakpoints.");
2490 result.SetStatus(eReturnStatusFailed);
2491 return false;
2492 }
2493
Jim Inghame14dc262016-09-12 23:10:56 +00002494 std::unique_lock<std::recursive_mutex> lock;
2495 target->GetBreakpointList().GetListMutex(lock);
2496
Jim Ingham01f16662016-09-14 19:07:35 +00002497 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002498 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002499 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002500 command, target, result, &valid_bp_ids,
2501 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002502
Jim Ingham01f16662016-09-14 19:07:35 +00002503 if (!result.Succeeded()) {
2504 result.SetStatus(eReturnStatusFailed);
2505 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002506 }
2507 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002508 FileSpec file_spec(m_options.m_filename);
2509 FileSystem::Instance().Resolve(file_spec);
2510 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2511 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002512 if (!error.Success()) {
2513 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2514 error.AsCString());
2515 result.SetStatus(eReturnStatusFailed);
2516 }
Jim Inghame14dc262016-09-12 23:10:56 +00002517 return result.Succeeded();
2518 }
2519
2520private:
2521 CommandOptions m_options;
2522};
2523
Jim Inghame14dc262016-09-12 23:10:56 +00002524//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002525// CommandObjectMultiwordBreakpoint
2526//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002527#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002528
Kate Stoneb9c1b512016-09-06 20:57:50 +00002529CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2530 CommandInterpreter &interpreter)
2531 : CommandObjectMultiword(
2532 interpreter, "breakpoint",
2533 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2534 "breakpoint <subcommand> [<command-options>]") {
2535 CommandObjectSP list_command_object(
2536 new CommandObjectBreakpointList(interpreter));
2537 CommandObjectSP enable_command_object(
2538 new CommandObjectBreakpointEnable(interpreter));
2539 CommandObjectSP disable_command_object(
2540 new CommandObjectBreakpointDisable(interpreter));
2541 CommandObjectSP clear_command_object(
2542 new CommandObjectBreakpointClear(interpreter));
2543 CommandObjectSP delete_command_object(
2544 new CommandObjectBreakpointDelete(interpreter));
2545 CommandObjectSP set_command_object(
2546 new CommandObjectBreakpointSet(interpreter));
2547 CommandObjectSP command_command_object(
2548 new CommandObjectBreakpointCommand(interpreter));
2549 CommandObjectSP modify_command_object(
2550 new CommandObjectBreakpointModify(interpreter));
2551 CommandObjectSP name_command_object(
2552 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002553 CommandObjectSP write_command_object(
2554 new CommandObjectBreakpointWrite(interpreter));
2555 CommandObjectSP read_command_object(
2556 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002557
Kate Stoneb9c1b512016-09-06 20:57:50 +00002558 list_command_object->SetCommandName("breakpoint list");
2559 enable_command_object->SetCommandName("breakpoint enable");
2560 disable_command_object->SetCommandName("breakpoint disable");
2561 clear_command_object->SetCommandName("breakpoint clear");
2562 delete_command_object->SetCommandName("breakpoint delete");
2563 set_command_object->SetCommandName("breakpoint set");
2564 command_command_object->SetCommandName("breakpoint command");
2565 modify_command_object->SetCommandName("breakpoint modify");
2566 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002567 write_command_object->SetCommandName("breakpoint write");
2568 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002569
Kate Stoneb9c1b512016-09-06 20:57:50 +00002570 LoadSubCommand("list", list_command_object);
2571 LoadSubCommand("enable", enable_command_object);
2572 LoadSubCommand("disable", disable_command_object);
2573 LoadSubCommand("clear", clear_command_object);
2574 LoadSubCommand("delete", delete_command_object);
2575 LoadSubCommand("set", set_command_object);
2576 LoadSubCommand("command", command_command_object);
2577 LoadSubCommand("modify", modify_command_object);
2578 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002579 LoadSubCommand("write", write_command_object);
2580 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002581}
2582
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002583CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002584
Kate Stoneb9c1b512016-09-06 20:57:50 +00002585void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2586 bool allow_locations,
2587 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002588 BreakpointIDList *valid_ids,
2589 BreakpointName::Permissions
2590 ::PermissionKinds
2591 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002592 // args can be strings representing 1). integers (for breakpoint ids)
2593 // 2). the full breakpoint & location
2594 // canonical representation
2595 // 3). the word "to" or a hyphen,
2596 // representing a range (in which case there
2597 // had *better* be an entry both before &
2598 // after of one of the first two types.
2599 // 4). A breakpoint name
2600 // If args is empty, we will use the last created breakpoint (if there is
2601 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002602
Kate Stoneb9c1b512016-09-06 20:57:50 +00002603 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002604
Zachary Turner11eb9c62016-10-05 20:03:37 +00002605 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002606 if (target->GetLastCreatedBreakpoint()) {
2607 valid_ids->AddBreakpointID(BreakpointID(
2608 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2609 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2610 } else {
2611 result.AppendError(
2612 "No breakpoint specified and no last created breakpoint.");
2613 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002614 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002615 return;
2616 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002617
Kate Stoneb9c1b512016-09-06 20:57:50 +00002618 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002619 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2620 // id range strings over; instead generate a list of strings for all the
2621 // breakpoint ids in the range, and shove all of those breakpoint id strings
2622 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002623
Jim Inghamb842f2e2017-09-14 20:22:49 +00002624 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2625 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002626
Kate Stoneb9c1b512016-09-06 20:57:50 +00002627 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2628 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002629
Pavel Labath16662f32018-06-20 08:12:50 +00002630 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002631
Adrian Prantl05097242018-04-30 16:49:04 +00002632 // At this point, all of the breakpoint ids that the user passed in have
2633 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002634
Kate Stoneb9c1b512016-09-06 20:57:50 +00002635 if (result.Succeeded()) {
2636 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002637 // ids, go through our tentative list of breakpoint id's and verify that
2638 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002639
2640 const size_t count = valid_ids->GetSize();
2641 for (size_t i = 0; i < count; ++i) {
2642 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2643 Breakpoint *breakpoint =
2644 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2645 if (breakpoint != nullptr) {
2646 const size_t num_locations = breakpoint->GetNumLocations();
2647 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2648 StreamString id_str;
2649 BreakpointID::GetCanonicalReference(
2650 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2651 i = valid_ids->GetSize() + 1;
2652 result.AppendErrorWithFormat(
2653 "'%s' is not a currently valid breakpoint/location id.\n",
2654 id_str.GetData());
2655 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002656 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002657 } else {
2658 i = valid_ids->GetSize() + 1;
2659 result.AppendErrorWithFormat(
2660 "'%d' is not a currently valid breakpoint ID.\n",
2661 cur_bp_id.GetBreakpointID());
2662 result.SetStatus(eReturnStatusFailed);
2663 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002664 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002665 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002666}